Created
December 25, 2016 21:30
-
-
Save Pan-Maciek/3dce2c9363e2410fd3d9d904bfa2f34f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function addSocketWrapper() { | |
| if("undefined" != typeof WebSocket) { | |
| var a = parseInt(localStorage.simulatedLatency) / 2; | |
| if(a > 0) { | |
| var b = WebSocket; | |
| WrappedWebSocket = function(c) { | |
| var d = new b(c); | |
| d.binaryType = "arraybuffer", this.onclose = function() {}, this.onopen = function() {}, this.onmessage = function() {}; | |
| var e = this; | |
| d.onclose = function() { | |
| window.setTimeout(function() { | |
| e.onclose() | |
| }, a) | |
| }, d.onopen = function() { | |
| window.setTimeout(function() { | |
| e.onopen() | |
| }, a) | |
| }, d.onmessage = function(b) { | |
| window.setTimeout(function() { | |
| e.onmessage(b) | |
| }, a) | |
| }, this.send = function(b) { | |
| window.setTimeout(function() { | |
| d.send(b) | |
| }, a) | |
| }, this.close = function() { | |
| window.setTimeout(function() { | |
| d.close() | |
| }, a) | |
| } | |
| }, window.WebSocket = WrappedWebSocket.bind() | |
| } | |
| } | |
| } | |
| function simpleRequest(a, b) { | |
| var c = new XMLHttpRequest; | |
| c.onreadystatechange = function() { | |
| c.readyState == XMLHttpRequest.DONE && 200 == c.status && null !== b && void 0 !== b && b(c.responseText) | |
| }, c.open("GET", a, !0), c.send() | |
| } | |
| function trackGameStart() { | |
| var a = ""; | |
| localStorage.playId ? a = "&id=" + localStorage.playId : (lsSet("playId", "test"), "test" != localStorage.playId && (a = "&id=donottrack")), simpleRequest("http://stats.splix.io/play.php?type=0" + a, function(a) { | |
| a && lsSet("playId", a) | |
| }) | |
| } | |
| function countPlayGame() { | |
| var a = 0; | |
| null !== localStorage.getItem("totalGamesPlayed") && (a = localStorage.totalGamesPlayed), a++, lsSet("totalGamesPlayed", a) | |
| } | |
| function getServers() { | |
| simpleRequest("/json/servers.2.json", function(a) { | |
| serversJsonGetTime = Date.now(); | |
| var b = JSON.parse(a), | |
| c = b.locations; | |
| servers = []; | |
| for(var d in c) { | |
| var e = c[d], | |
| f = generateServerLocation(e); | |
| servers.push(f), serversRequestDone = !0 | |
| } | |
| teamServers = b.teamServers; | |
| for(var g = 0; g < teamServers.length; g++) teamServers[g].active && activeTeamServers.push(teamServers[g]); | |
| retentionSamples = b.retentionSamples, doConnectAfterServersGet && (doConnectAfterServersGet = !1, doConnect()), teamDoConnectAfterServersGet && (teamDoConnectAfterServersGet = !1, teamDoConnect()), startPingServers() | |
| }) | |
| } | |
| function generateServerLocation(a) { | |
| return { | |
| pingUrlV4: a.pingIpv4 + ":7999/ping-" + a.loc, | |
| pingUrlV6: "[" + a.pingIpv6 + "]:7999/ping6-" + a.loc, | |
| gamemodes: a.gamemodes, | |
| loc: a.loc, | |
| locId: a.locId, | |
| ws: null, | |
| ws6: null, | |
| pingTries: 0, | |
| pingTries6: 0, | |
| avgPing: 0, | |
| avgPing6: 0, | |
| open: !1, | |
| open6: !1, | |
| initSocket: function() { | |
| this.connectionTries++, this.lastConnectionTry = Date.now(), null !== this.ws && (this.ws.onmessage = null, this.ws.onopen = null, this.ws.onclose = null, this.ws.close(), this.pingTries = 0, this.avgPing = 0, this.lastPingTime = 0, this.waitingForPing = !1), this.ws = new WebSocket("ws://" + this.pingUrlV4), this.ws.binaryType = "arraybuffer"; | |
| var a = this; | |
| this.ws.onmessage = function() { | |
| if(a.waitingForPing) { | |
| var b = Date.now() - a.lastPingTime; | |
| b += 10, a.avgPing = a.avgPing * a.pingTries + b, a.pingTries++, a.avgPing /= a.pingTries, a.lastPingTime = Date.now(), a.waitingForPing = !1, a.pingTries >= 4 && (a.open = !1, a.ws.close()) | |
| } | |
| }, this.ws.onopen = function() { | |
| a.open = !0, a.connectedOnce = !0 | |
| }, this.ws.onclose = function() { | |
| a.open = !1 | |
| } | |
| }, | |
| initSocket6: function() { | |
| this.connectionTries6++, this.lastConnectionTry6 = Date.now(), null !== this.ws6 && (this.ws6.onmessage = null, this.ws6.onopen = null, this.ws6.onclose = null, this.ws6.close(), this.pingTries6 = 0, this.avgPing6 = 0, this.lastPingTime6 = 0, this.waitingForPing6 = !1), this.ws6 = new WebSocket("ws://" + this.pingUrlV6), this.ws6.binaryType = "arraybuffer"; | |
| var a = this; | |
| this.ws6.onmessage = function() { | |
| if(a.waitingForPing6) { | |
| var b = Date.now() - a.lastPingTime6; | |
| a.avgPing6 = a.avgPing6 * a.pingTries6 + b, a.pingTries6++, a.avgPing6 /= a.pingTries6, a.lastPingTime6 = Date.now(), a.waitingForPing6 = !1, a.pingTries6 >= 4 && (a.open6 = !1, a.ws6.close()) | |
| } | |
| }, this.ws6.onopen = function() { | |
| a.open6 = !0, a.connectedOnce6 = !0 | |
| }, this.ws6.onclose = function() { | |
| a.open6 = !1 | |
| } | |
| }, | |
| lastPingTime: 0, | |
| lastPingTime6: 0, | |
| waitingForPing: !1, | |
| waitingForPing6: !1, | |
| ping: function() { | |
| if(!this.waitingForPing) return this.open && this.ws && this.ws.readyState == WebSocket.OPEN ? (this.waitingForPing = !0, this.lastPingTime = Date.now(), this.ws.send(new Uint8Array([0])), this.pingTries >= 4) : this.testSuccessfulConnection(); | |
| var a = Date.now() - this.lastPingTime; | |
| a > 1e4 && this.initSocket() | |
| }, | |
| ping6: function() { | |
| if(!this.waitingForPing6) return this.open6 && this.ws6 && this.ws6.readyState == WebSocket.OPEN ? (this.waitingForPing6 = !0, this.lastPingTime6 = Date.now(), this.ws6.send(new Uint8Array([0])), this.pingTries6 >= 4) : this.testSuccessfulConnection(); | |
| var a = Date.now() - this.lastPingTime6; | |
| a > 1e4 && this.initSocket6() | |
| }, | |
| connectedOnce: !1, | |
| connectedOnce6: !1, | |
| connectionTries: 0, | |
| connectionTries6: 0, | |
| lastConnectionTry: Date.now(), | |
| lastConnectionTry6: Date.now(), | |
| testSuccessfulConnection: function() { | |
| return !(!this.connectedOnce && !this.connectedOnce6) || (this.connectionTries > 3 || !(Date.now() - this.lastConnectionTry < 5e3) && (this.initSocket(), !1)) | |
| }, | |
| testSuccessfulConnection6: function() { | |
| return !(!this.connectedOnce && !this.connectedOnce6) || (this.connectionTries6 > 3 || !(Date.now() - this.lastConnectionTry6 < 5e3) && (this.initSocket6(), !1)) | |
| } | |
| } | |
| } | |
| function startPingServers() { | |
| for(var a = 0; a < servers.length; a++) { | |
| var b = servers[a]; | |
| b.initSocket(), b.initSocket6() | |
| } | |
| } | |
| function pingServers() { | |
| if(donePing = !0, servers.length > 0) | |
| for(var a = 0; a < servers.length; a++) { | |
| var b = servers[a]; | |
| b.ping() || (donePing = !1), b.ping6() || (donePing = !1) | |
| } else donePing = !1; | |
| donePing && "Teams" == selectedGamemode && teamSendPingData() | |
| } | |
| function getServer(a, b) { | |
| console.log("searching for best server"); | |
| var c, d, e, f, g, h; | |
| void 0 === a && (a = -1), void 0 === b && (b = !0); | |
| var i = null, | |
| j = null; | |
| if(b && location.hash) { | |
| if(location.hash.startsWith("#ip-")) return console.log("ip provided in url, using " + location.hash), { | |
| ip: "ws://" + location.hash.substring(4), | |
| ping: 30 | |
| }; | |
| if(location.hash.startsWith("#team-") && "Teams" == selectedGamemode) { | |
| if(testExistingTeamHash()) return console.log("disconnect from previous teams session was unexpected, using the ip from the old teams session"), { | |
| ip: "ws://" + localStorage.lastTeamIp + "/splix", | |
| ping: 30 | |
| } | |
| } else { | |
| if(servers.length <= 0) return console.log("servers length <= 0, unable to connect (1)"), null; | |
| var k = selectedGamemode.toLowerCase(); | |
| "normal" == k && (k = "default"); | |
| for(var l = 0; l < servers.length; l++) { | |
| var m = servers[l]; | |
| for(e = 0; e < m.gamemodes.length; e++) | |
| if(g = m.gamemodes[e], g.gm == k) | |
| for(f = 0; f < g.versions.length; f++) | |
| if(h = g.versions[f], h.ver == COMPATIBLE_CLIENT_VERSION) | |
| for(var n = h.lobbies, o = 0; o < n.length; o++) | |
| if(d = n[o], d.hash == location.hash.substring(1)) { | |
| i = d, j = m; | |
| break | |
| } | |
| } | |
| } | |
| } | |
| if(null === i) { | |
| j = null; | |
| var p = 1 / 0; | |
| if(servers.length <= 0) return console.log("servers length <= 0, unable to connect (2)"), null; | |
| for(console.log("determining what the best location is"), e = 0; e < servers.length; e++) { | |
| if(c = servers[e], a >= 0 && c.locId == a) { | |
| j = c; | |
| break | |
| } | |
| c.avgPing < p && c.pingTries > 0 && (p = c.avgPing, j = c), c.avgPing6 < p && c.pingTries6 > 0 && (p = c.avgPing6, j = c) | |
| } | |
| null === j && (console.log("Couldn't determine best location, picking a random one"), j = randFromArray(servers)), console.log("found location is " + j.loc); | |
| var q = null; | |
| console.log("searching for lobby group in this location with version " + COMPATIBLE_CLIENT_VERSION + " and gamemode " + selectedGamemode); | |
| var r = { | |
| Normal: "default", | |
| Teams: "teams" | |
| }; | |
| for(e = 0; e < j.gamemodes.length; e++) | |
| if(g = j.gamemodes[e], g.gm == r[selectedGamemode]) | |
| for(console.log("found gamemode", g.gm), f = 0; f < g.versions.length; f++) | |
| if(h = g.versions[f], h.ver == COMPATIBLE_CLIENT_VERSION) { | |
| q = h.lobbies; | |
| break | |
| } | |
| if(null === q || q.length <= 0) return console.log(q), console.log("lobbiesGroup not found or lobbiesGroup.length <= 0, couldn't find server"), null; | |
| i = randFromArray(q), console.log("a lobby was found:", i) | |
| } | |
| var s = location.href; | |
| b && (location.hash || s.lastIndexOf("#") == s.length - 1) && (location.hash = i.hash); | |
| var t, u; | |
| return j.pingTries6 > 0 && (j.avgPing6 < j.avgPing || j.pingTries <= 0) ? (t = "[" + i.ipv6 + "]", u = j.avgPing6) : (t = i.ipv4, u = j.avgPing), { | |
| ip: "ws://" + t + ":" + i.port + "/splix", | |
| ip4: i.ipv4 + ":" + i.port, | |
| ip6: "[" + i.ipv6 + "]:" + i.port, | |
| ping: u | |
| } | |
| } | |
| function getBlock(a, b, c) { | |
| var d; | |
| void 0 === c && (c = blocks); | |
| for(var e = 0; e < c.length; e++) | |
| if(d = c[e], d.x == a && d.y == b) return d; | |
| return d = { | |
| x: a, | |
| y: b, | |
| currentBlock: -1, | |
| nextBlock: -1, | |
| animDirection: 0, | |
| animProgress: 0, | |
| animDelay: 0, | |
| lastSetTime: Date.now(), | |
| setBlockId: function(a, b) { | |
| if(this.lastSetTime = Date.now(), b === !1) this.currentBlock = this.nextBlock = a, this.animDirection = 0, this.animProgress = 1; | |
| else { | |
| void 0 === b && (b = 0), this.animDelay = b; | |
| var c = a == this.currentBlock, | |
| d = a == this.nextBlock; | |
| c && d && this.animDirection == -1 && (this.animDirection = 1), c && !d && (this.animDirection = 1, this.nextBlock = this.currentBlock), !c && d && 1 == this.animDirection && (this.animDirection = -1), c || d || (this.nextBlock = a, this.animDirection = -1) | |
| } | |
| } | |
| }, c.push(d), d | |
| } | |
| function getPlayer(a, b) { | |
| var c; | |
| void 0 === b && (b = players); | |
| for(var d = 0; d < b.length; d++) | |
| if(c = b[d], c.id == a) return c; | |
| return c = { | |
| id: a, | |
| pos: [0, 0], | |
| drawPos: [-1, -1], | |
| drawPosSet: !1, | |
| serverPos: [0, 0], | |
| dir: 0, | |
| isMyPlayer: 0 === a, | |
| isDead: !1, | |
| deathWasCertain: !1, | |
| didUncertainDeathLastTick: !1, | |
| isDeadTimer: 0, | |
| uncertainDeathPosition: [0, 0], | |
| die: function(a) { | |
| if(a = !!a, this.isDead) this.deathWasCertain = a || this.deathWasCertain; | |
| else if(a || !this.didUncertainDeathLastTick) { | |
| a || (this.didUncertainDeathLastTick = !0, this.uncertainDeathPosition = [this.pos[0], this.pos[1]]), this.isDead = !0, this.deathWasCertain = a, this.deadAnimParts = [0], this.isDeadTimer = 0, this.isMyPlayer && doCamShakeDir(this.dir); | |
| for(var b = 0;;) { | |
| if(b += .4 * Math.random() + .5, b >= 2 * Math.PI) { | |
| this.deadAnimParts.push(2 * Math.PI); | |
| break | |
| } | |
| this.deadAnimParts.push(b), this.deadAnimPartsRandDist.push(Math.random()) | |
| } | |
| } | |
| }, | |
| undoDie: function() { | |
| this.isDead = !1 | |
| }, | |
| deadAnimParts: [], | |
| deadAnimPartsRandDist: [], | |
| addHitLine: function(a, b) { | |
| this.hitLines.push({ | |
| pos: a, | |
| vanishTimer: 0, | |
| color: b | |
| }) | |
| }, | |
| hitLines: [], | |
| doHonk: function(a) { | |
| this.honkTimer = 0, this.honkMaxTime = a | |
| }, | |
| moveRelativeToServerPosNextFrame: !1, | |
| lastServerPosSentTime: 0, | |
| honkTimer: 0, | |
| honkMaxTime: 0, | |
| trails: [], | |
| name: "", | |
| skinBlock: 0, | |
| lastBlock: null, | |
| hasReceivedPosition: !1 | |
| }, b.push(c), c.isMyPlayer && (myPlayer = c), c | |
| } | |
| function lsSet(a, b) { | |
| try { | |
| return localStorage.setItem(a, b), !0 | |
| } catch(a) { | |
| return !1 | |
| } | |
| } | |
| function checkUsername(a) { | |
| var b = a.toLowerCase(); | |
| if("denniskoe" == b) { | |
| var c = document.body.style; | |
| c.webkitFilter = c.filter = "contrast(200%) hue-rotate(90deg) invert(100%)" | |
| } else "kwebbelkop" == b ? (lsSet("skinColor", 12), lsSet("skinPattern", 18), updateSkin()) : "jelly" == b ? (lsSet("skinColor", 8), lsSet("skinPattern", 19), updateSkin()) : b.indexOf("masterov") > -1 || 0 === b.indexOf("[mg]") || 0 === b.indexOf("(mg)") ? (lsSet("skinColor", 12), lsSet("skinPattern", 20), updateSkin()) : "farsattack" == b ? (lsSet("skinColor", 8), lsSet("skinPattern", 21), updateSkin()) : 0 === b.indexOf("[am]") || 0 === b.indexOf("(am)") ? (lsSet("skinColor", 11), lsSet("skinPattern", 23), updateSkin()) : "hetgames" == b ? (lsSet("skinColor", 1), lsSet("skinPattern", 24), updateSkin()) : 0 === b.indexOf("[gym]") || 0 === b.indexOf("(gym)") ? (lsSet("skinColor", 4), lsSet("skinPattern", 25), updateSkin()) : "luh" == b && (lsSet("skinColor", 12), lsSet("skinPattern", 26), updateSkin()) | |
| } | |
| function sendName() { | |
| var a = nameInput.value; | |
| void 0 !== a && null !== a && "" !== a && "" !== a.trim() && wsSendMsg(sendAction.SET_USERNAME, a) | |
| } | |
| function nameInputOnChange() { | |
| lsSet("name", nameInput.value), teamSendPlayerName() | |
| } | |
| function sendTeamName() { | |
| if("Teams" == selectedGamemode && teamBeginUIIsHost) { | |
| var a = teamNameInput.value; | |
| void 0 !== a && null !== a && "" !== a && "" !== a.trim() && wsSendMsg(sendAction.SET_TEAM_USERNAME, a) | |
| } | |
| } | |
| function sendVersion() { | |
| wsSendMsg(sendAction.VERSION, { | |
| type: 0, | |
| ver: CLIENT_VERSION | |
| }) | |
| } | |
| function sendSkin() { | |
| var a = localStorage.getItem("skinColor"); | |
| null === a && (a = 0); | |
| var b = localStorage.getItem("skinPattern"); | |
| null === b && (b = 0), wsSendMsg(sendAction.SKIN, { | |
| blockColor: a, | |
| pattern: b | |
| }) | |
| } | |
| function sendTeamUrl() { | |
| "Teams" == selectedGamemode && wsSendMsg(sendAction.MY_TEAM_URL, teamShareUrl) | |
| } | |
| function sendPatreonCode() { | |
| "" !== localStorage.patreonLastSplixCode && void 0 !== localStorage.patreonLastSplixCode && wsSendMsg(sendAction.PATREON_CODE, localStorage.patreonLastSplixCode) | |
| } | |
| function sendDir(a, b) { | |
| if(!ws || !myPos) return !1; | |
| if(!myPlayer) return !1; | |
| if(a == lastSendDir && Date.now() - lastSendDirTime < .7 / GLOBAL_SPEED) return !1; | |
| if(lastSendDir = a, lastSendDirTime = Date.now(), myPlayer.dir == a) return addSendDirQueue(a, b), !1; | |
| if(0 === a && 2 == myPlayer.dir || 2 == a && 0 === myPlayer.dir || 1 == a && 3 == myPlayer.dir || 3 == a && 1 == myPlayer.dir) return addSendDirQueue(a, b), !1; | |
| mouseHidePos = [lastMousePos[0], lastMousePos[1]], document.body.style.cursor = "none"; | |
| var c = 1 == myPlayer.dir || 3 == myPlayer.dir, | |
| d = myPos[c ? 1 : 0], | |
| e = [myPos[0], myPos[1]], | |
| f = Math.round(d); | |
| if(e[c ? 1 : 0] = f, 0 === myPlayer.dir && e[0] <= lastChangedDirPos[0] || 1 == myPlayer.dir && e[1] <= lastChangedDirPos[1] || 2 == myPlayer.dir && e[0] >= lastChangedDirPos[0] || 3 == myPlayer.dir && e[1] >= lastChangedDirPos[1]) return addSendDirQueue(a, b), !1; | |
| var g = !1, | |
| h = d - Math.floor(d); | |
| return myPlayer.dir <= 1 ? h < .45 && (g = !0) : myPlayer.dir <= 3 ? h > .55 && (g = !0) : g = !0, g ? changeMyDir(a, e) : (myNextDir = a, changeDirAt = f, changeDirAtIsHorizontal = c, lastChangedDirPos = [e[0], e[1]]), lastMyPosSetClientSideTime = Date.now(), lastMyPosHasBeenConfirmed && (lastMyPosSetValidClientSideTime = Date.now()), lastMyPosHasBeenConfirmed = !1, wsSendMsg(sendAction.UPDATE_DIR, { | |
| dir: a, | |
| coord: e | |
| }), !0 | |
| } | |
| function addSendDirQueue(a, b) { | |
| !b && sendDirQueue.length < 3 && sendDirQueue.push({ | |
| dir: a, | |
| addTime: Date.now() | |
| }) | |
| } | |
| function changeMyDir(a, b, c, d) { | |
| myPlayer.dir = myNextDir = a, myPlayer.pos = [b[0], b[1]], lastChangedDirPos = [b[0], b[1]], void 0 === c && (c = !0), void 0 === d && (d = !0), c && trailPush(myPlayer), d && lastClientsideMoves.push({ | |
| dir: a, | |
| pos: b | |
| }) | |
| } | |
| function startRequestMyTrail() { | |
| isRequestingMyTrail = !0, trailPushesDuringRequest = [], wsSendMsg(sendAction.REQUEST_MY_TRAIL) | |
| } | |
| function trailPush(a, b) { | |
| if(a.trails.length > 0) { | |
| var c = a.trails[a.trails.length - 1].trail; | |
| if(c.length > 0) { | |
| var d = c[c.length - 1]; | |
| d[0] == a.pos[0] && d[1] == a.pos[1] || (b = void 0 === b ? [a.pos[0], a.pos[1]] : [b[0], b[1]], c.push(b), a.isMyPlayer && isRequestingMyTrail && trailPushesDuringRequest.push(b)) | |
| } | |
| } | |
| } | |
| function honkStart() { | |
| honkStartTime = Date.now() | |
| } | |
| function honkEnd() { | |
| var a = Date.now(); | |
| if(a > lastHonkTime) { | |
| var b = a - honkStartTime; | |
| b = clamp(b, 0, 1e3), lastHonkTime = a + b, b = iLerp(0, 1e3, b), b *= 255, b = Math.floor(b), wsSendMsg(sendAction.HONK, b); | |
| for(var c = 0; c < players.length; c++) { | |
| var d = players[c]; | |
| d.isMyPlayer && d.doHonk(Math.max(70, b)) | |
| } | |
| } | |
| } | |
| function onOpen() { | |
| isConnecting = !1, sendVersion(), sendPatreonCode(), sendName(), sendSkin(), sendTeamUrl(), sendTeamName(), wsSendMsg(sendAction.READY), playingAndReady && onConnectOrMiddleOfTransition(), trackGameStart(), countPlayGame(), wsOnOpenTime = Date.now() | |
| } | |
| function onConnectOrMiddleOfTransition() { | |
| hideSkinScreen(), hideBeginShowMain(), skipChangeToNormalOnce = !0, teamWsClose() | |
| } | |
| function hideBeginShowMain() { | |
| hideBegin(), showMainCanvas() | |
| } | |
| function hideBegin() { | |
| beginScreen.style.display = "none", beginScreenVisible = !1 | |
| } | |
| function showMainCanvas() { | |
| playUI.style.display = null, mainCanvas.style.display = null, "ontouchstart" in window && (touchControlsElem.style.display = null), myNameAlphaTimer = 0, setNotification("") | |
| } | |
| function setNotification(a) { | |
| notificationElem.innerHTML = a, notificationElem.style.display = a ? null : "none" | |
| } | |
| function showBegin() { | |
| beginScreen.style.display = null, beginScreenVisible = !0, nameInput.focus(), setAdBoxLeft() | |
| } | |
| function hideMainCanvas() { | |
| playUI.style.display = "none", mainCanvas.style.display = "none", touchControlsElem.style.display = "none" | |
| } | |
| function showSkinScreen() { | |
| skinScreenVisible = !0, skinScreen.style.display = null | |
| } | |
| function hideSkinScreen() { | |
| skinScreenVisible = !1, skinScreen.style.display = "none" | |
| } | |
| function openSkinScreen() { | |
| hideBegin(), showSkinScreen() | |
| } | |
| function showBeginHideMainCanvas() { | |
| showBegin(), hideMainCanvas() | |
| } | |
| function showBeginHideSkin() { | |
| showBegin(), hideSkinScreen() | |
| } | |
| function onClose() { | |
| ws && ws.readyState == WebSocket.OPEN && ws.close(), playingAndReady ? closedBecauseOfDeath || (doTransition("", !1, resetAll), setNotification("The connection was lost :/")) : isTransitioning ? showCouldntConnectAfterTransition = !0 : couldntConnect() && showBeginHideMainCanvas(), ws = null, isConnecting = !1, "Teams" != selectedGamemode || testTeamWsConnection() || teamDoConnect() | |
| } | |
| function couldntConnect() { | |
| var a = Date.now() - serversJsonGetTime; | |
| if(resetAll(), a /= 1e3, a > 5) return doConnectAfterServersGet = !0, console.log("requesting server list again"), getServers(), !1; | |
| setNotification("Couldn't connect to the server :/"); | |
| var b = new Error("couldntConnectError"); | |
| return console.log(b.stack), isTransitioning = !0, !0 | |
| } | |
| function connectWithTransition(a) { | |
| isConnectingWithTransition || isWaitingForAd || (isConnectingWithTransition = !0, doConnect(a) && (doTransition("", !1, function() { | |
| playingAndReady || (isTransitioning = !1), showCouldntConnectAfterTransition ? couldntConnect() : onConnectOrMiddleOfTransition(), showCouldntConnectAfterTransition = !1 | |
| }), nameInput.blur(), checkUsername(nameInput.value)), isConnectingWithTransition = !1) | |
| } | |
| function doConnect(a) { | |
| if(!ws && !isConnecting && !isTransitioning) { | |
| if(canRunAds && !a && testPatreonAdsAllowed()) { | |
| var b = getAdCounter(), | |
| c = localStorage.lastAdTime; | |
| if(c = parseInt(c), c = Date.now() - c, 1 == b || !isNaN(c) && c > 3e5) return displayAd(), !1; | |
| countAd() | |
| } | |
| isConnecting = !0, showCouldntConnectAfterTransition = !1, closedBecauseOfDeath = !1; | |
| var d = getServer(); | |
| return d ? (thisServerAvgPing = thisServerLastPing = d.ping, console.log("connecting to " + d.ip + "..."), ws = new WebSocket(d.ip), ws.binaryType = "arraybuffer", ws.onmessage = function(a) { | |
| ws == this && onMessage(a) | |
| }, ws.onclose = function(a) { | |
| ws == this && onClose(a) | |
| }, ws.onopen = function(a) { | |
| ws == this && onOpen(a) | |
| }, !0) : (onClose(), !1) | |
| } | |
| return !1 | |
| } | |
| function onMessage(a) { | |
| var b, c, d, e, f, g, h, i, j, k, l, m = new Uint8Array(a.data); | |
| if(m[0] == receiveAction.UPDATE_BLOCKS && (b = bytesToInt(m[1], m[2]), c = bytesToInt(m[3], m[4]), d = m[5], i = getBlock(b, c), i.setBlockId(d)), m[0] == receiveAction.PLAYER_POS) { | |
| b = bytesToInt(m[1], m[2]), c = bytesToInt(m[3], m[4]), e = bytesToInt(m[5], m[6]), f = getPlayer(e), f.hasReceivedPosition = !0, f.moveRelativeToServerPosNextFrame = !0, f.lastServerPosSentTime = Date.now(), lastMyPosHasBeenConfirmed = !0; | |
| var n = m[7], | |
| o = [b, c], | |
| p = [b, c], | |
| q = 0; | |
| (f.isMyPlayer || thisServerAvgPing > 50) && (q = thisServerAvgPing / 2 * GLOBAL_SPEED), movePos(p, n, q); | |
| var r = !0; | |
| if(f.isMyPlayer) { | |
| if(lastMyPosServerSideTime = Date.now(), (f.dir == n || myNextDir == n) && Math.abs(p[0] - f.pos[0]) < 1 && Math.abs(p[1] - f.pos[1]) < 1 && (r = !1), lastClientsideMoves.length > 0) { | |
| var s = lastClientsideMoves.shift(); | |
| s.dir == n && s.pos[0] == o[0] && s.pos[1] == o[1] ? r = !1 : lastClientsideMoves = [] | |
| } | |
| 4 != f.dir && 4 != n || (r = !0), r && (myNextDir = n, changeMyDir(n, o, !1, !1), startRequestMyTrail(), sendDirQueue = []), f.serverPos = [p[0], p[1]], f.serverDir = n, removeBlocksOutsideViewport(f.pos) | |
| } else f.dir = n; | |
| if(r) { | |
| f.pos = p; | |
| var t = m.length > 8; | |
| t && trailPush(f, o) | |
| } | |
| f.drawPosSet || (f.drawPos = [f.pos[0], f.pos[1]], f.drawPosSet = !0) | |
| } | |
| if(m[0] == receiveAction.FILL_AREA) { | |
| b = bytesToInt(m[1], m[2]), c = bytesToInt(m[3], m[4]), g = bytesToInt(m[5], m[6]), h = bytesToInt(m[7], m[8]), d = m[9]; | |
| var u = m[10]; | |
| fillArea(b, c, g, h, d, u) | |
| } | |
| if(m[0] == receiveAction.SET_TRAIL) { | |
| e = bytesToInt(m[1], m[2]), f = getPlayer(e); | |
| var v = [], | |
| w = !1; | |
| for(j = 3; j < m.length; j += 4) { | |
| var x = [bytesToInt(m[j], m[j + 1]), bytesToInt(m[j + 2], m[j + 3])]; | |
| v.push(x) | |
| } | |
| if(f.isMyPlayer) | |
| if(skipTrailRequestResponse) skipTrailRequestResponse = !1, trailPushesDuringRequest = []; | |
| else { | |
| if(isRequestingMyTrail) { | |
| for(isRequestingMyTrail = !1, w = !0, j = 0; j < trailPushesDuringRequest.length; j++) v.push(trailPushesDuringRequest[j]); | |
| trailPushesDuringRequest = [] | |
| } | |
| if(f.trails.length > 0) { | |
| var y = f.trails[f.trails.length - 1]; | |
| y.trail.length <= 0 && v.length > 0 && startRequestMyTrail() | |
| } | |
| } | |
| if(w) | |
| if(f.trails.length > 0) { | |
| var z = f.trails[f.trails.length - 1]; | |
| z.trail = v, z.vanishTimer = 0 | |
| } else w = !1; | |
| w || f.trails.push({ | |
| trail: v, | |
| vanishTimer: 0 | |
| }) | |
| } | |
| if(m[0] == receiveAction.EMPTY_TRAIL_WITH_LAST_POS) { | |
| if(e = bytesToInt(m[1], m[2]), f = getPlayer(e), f.trails.length > 0) { | |
| var A = f.trails[f.trails.length - 1].trail; | |
| A.length > 0 && (b = bytesToInt(m[3], m[4]), c = bytesToInt(m[5], m[6]), A.push([b, c])) | |
| } | |
| f.isMyPlayer && isRequestingMyTrail && (skipTrailRequestResponse = !0), f.trails.push({ | |
| trail: [], | |
| vanishTimer: 0 | |
| }) | |
| } | |
| if(m[0] == receiveAction.PLAYER_DIE && (e = bytesToInt(m[1], m[2]), f = getPlayer(e), m.length > 3 && (b = bytesToInt(m[3], m[4]), c = bytesToInt(m[5], m[6]), f.pos = [b, c]), f.die(!0)), m[0] == receiveAction.CHUNK_OF_BLOCKS) { | |
| for(b = bytesToInt(m[1], m[2]), c = bytesToInt(m[3], m[4]), g = bytesToInt(m[5], m[6]), h = bytesToInt(m[7], m[8]), j = 9, k = b; k < b + g; k++) | |
| for(var B = c; B < c + h; B++) i = getBlock(k, B), i.setBlockId(m[j], !1), j++; | |
| hasReceivedChunkThisGame || (hasReceivedChunkThisGame = !0, wsSendMsg(sendAction.READY), didSendSecondReady = !0) | |
| } | |
| if(m[0] == receiveAction.REMOVE_PLAYER) | |
| for(e = bytesToInt(m[1], m[2]), j = players.length - 1; j >= 0; j--) f = players[j], e == f.id && players.splice(j, 1); | |
| if(m[0] == receiveAction.PLAYER_NAME) { | |
| e = bytesToInt(m[1], m[2]), l = m.subarray(3, m.length); | |
| var C = Utf8ArrayToStr(l); | |
| f = getPlayer(e), f.name = filter(C) | |
| } | |
| if(m[0] == receiveAction.MY_SCORE) { | |
| var D = bytesToInt(m[1], m[2], m[3], m[4]), | |
| E = 0; | |
| m.length > 5 && (E = bytesToInt(m[5], m[6])), scoreStatTarget = D, realScoreStatTarget = D + 500 * E, myKillsElem.innerHTML = E | |
| } | |
| if(m[0] == receiveAction.MY_RANK && (myRank = bytesToInt(m[1], m[2]), myRankSent = !0, updateStats()), m[0] == receiveAction.LEADERBOARD) { | |
| leaderboardElem.innerHTML = "", totalPlayers = bytesToInt(m[1], m[2]), updateStats(), j = 3; | |
| for(var F = 1;;) { | |
| if(j >= m.length) break; | |
| var G = bytesToInt(m[j], m[j + 1], m[j + 2], m[j + 3]), | |
| H = m[j + 4]; | |
| l = m.subarray(j + 5, j + 5 + H); | |
| var I = Utf8ArrayToStr(l), | |
| J = document.createElement("tr"); | |
| J.className = "scoreRank"; | |
| var K = document.createElement("td"); | |
| K.innerHTML = "#" + F, J.appendChild(K); | |
| var L = document.createElement("td"); | |
| L.innerHTML = filter(htmlEscape(I)), J.appendChild(L); | |
| var M = document.createElement("td"); | |
| M.innerHTML = G, J.appendChild(M), leaderboardElem.appendChild(J), j = j + 5 + H, F++ | |
| } | |
| totalPlayers < 30 && doRefreshAfterDie && null === closeNotification && (closeNotification = doTopNotification("This server is about to close, refresh to join a full server.")) | |
| } | |
| if(m[0] == receiveAction.MAP_SIZE && (mapSize = bytesToInt(m[1], m[2])), m[0] == receiveAction.YOU_DED) { | |
| if(m.length > 1) switch(lastStatBlocks = bytesToInt(m[1], m[2], m[3], m[4]), lastStatBlocks > bestStatBlocks && (bestStatBlocks = lastStatBlocks, lsSet("bestStatBlocks", bestStatBlocks)), lastStatKills = bytesToInt(m[5], m[6]), lastStatKills > bestStatKills && (bestStatKills = lastStatKills, lsSet("bestStatKills", bestStatKills)), lastStatLbRank = bytesToInt(m[7], m[8]), (lastStatLbRank < bestStatLbRank || bestStatLbRank <= 0) && lastStatLbRank > 0 && (bestStatLbRank = lastStatLbRank, lsSet("bestStatLbRank", bestStatLbRank)), lastStatAlive = bytesToInt(m[9], m[10], m[11], m[12]), lastStatAlive > bestStatAlive && (bestStatAlive = lastStatAlive, lsSet("bestStatAlive", bestStatAlive)), lastStatNo1Time = bytesToInt(m[13], m[14], m[15], m[16]), lastStatNo1Time > bestStatNo1Time && (bestStatNo1Time = lastStatNo1Time, lsSet("bestStatNo1Time", bestStatNo1Time)), lastStatDeathType = m[17], lastStatKiller = "", document.getElementById("lastStats").style.display = null, document.getElementById("bestStats").style.display = null, lastStatCounter = 0, lastStatTimer = 0, lastStatValueElem.innerHTML = bestStatValueElem.innerHTML = "", lastStatDeathType) { | |
| case 1: | |
| m.length > 18 && (l = m.subarray(18, m.length), lastStatKiller = Utf8ArrayToStr(l)); | |
| break; | |
| case 2: | |
| lastStatKiller = "the wall"; | |
| break; | |
| case 3: | |
| lastStatKiller = "yourself" | |
| } | |
| lsSet("lastTeamShareUrl", ""), lsSet("lastTeamIp", ""), closedBecauseOfDeath = !0, allowSkipDeathTransition = !0, hideBanner(), refreshBanner(), document.getElementById("newsbox").style.display = null, deathTransitionTimeout = window.setTimeout(function() { | |
| skipDeathTransition ? doTransition("", !1, function() { | |
| window.setTimeout(afterDeath, 700), onClose(), resetAll() | |
| }) : doTransition("GAME OVER", !0, null, function() { | |
| window.setTimeout(afterDeath, 250), onClose(), resetAll() | |
| }, !0), deathTransitionTimeout = null | |
| }, 1e3) | |
| } | |
| if(m[0] == receiveAction.MINIMAP) { | |
| var N = m[1], | |
| O = 20 * N; | |
| for(minimapCtx.clearRect(2 * O, 0, 40, 160), minimapCtx.fillStyle = "#000000", j = 1; j < m.length; j++) | |
| for(k = 0; k < 8; k++) { | |
| var P = 0 !== (m[j] & 1 << k); | |
| if(P) { | |
| var Q = 8 * (j - 2) + k; | |
| b = Math.floor(Q / 80) % 80 + O, c = Q % 80, minimapCtx.fillRect(2 * b, 2 * c, 2, 2) | |
| } | |
| } | |
| } | |
| if(m[0] == receiveAction.PLAYER_SKIN && (e = bytesToInt(m[1], m[2]), f = getPlayer(e), f.isMyPlayer && (myColorId = m[3], colorUI()), f.skinBlock = m[3]), m[0] == receiveAction.READY && (playingAndReady = !0, isTransitioning || (isTransitioning = !0, onConnectOrMiddleOfTransition())), m[0] == receiveAction.PLAYER_HIT_LINE) { | |
| e = bytesToInt(m[1], m[2]), f = getPlayer(e); | |
| var R = getColorForBlockSkinId(m[3]); | |
| b = bytesToInt(m[4], m[5]), c = bytesToInt(m[6], m[7]); | |
| var S = !1; | |
| m.length > 8 && (S = 1 == m[8]), f.addHitLine([b, c], R, S), f.isMyPlayer && !S && doCamShakeDir(f.dir, 10, !1) | |
| } | |
| if(m[0] == receiveAction.REFRESH_AFTER_DIE && (doRefreshAfterDie = !0), m[0] == receiveAction.PLAYER_HONK) { | |
| e = bytesToInt(m[1], m[2]), f = getPlayer(e); | |
| var T = m[3]; | |
| f.doHonk(T) | |
| } | |
| if(m[0] == receiveAction.PONG) { | |
| var U = Date.now() - lastPingTime, | |
| V = Math.abs(U - thisServerLastPing); | |
| thisServerDiffPing = Math.max(thisServerDiffPing, V), thisServerDiffPing = lerp(V, thisServerDiffPing, .5), thisServerAvgPing = lerp(thisServerAvgPing, U, .5), thisServerLastPing = U, lastPingTime = Date.now(), waitingForPing = !1 | |
| } | |
| if(m[0] == receiveAction.UNDO_PLAYER_DIE && (e = bytesToInt(m[1], m[2]), f = getPlayer(e), f.undoDie()), m[0] == receiveAction.TEAM_LIFE_COUNT) { | |
| var W = m[1], | |
| X = m[2]; | |
| setLives(W, X) | |
| } | |
| } | |
| function wsSendMsg(a, b) { | |
| var c; | |
| if(ws && ws.readyState == WebSocket.OPEN) { | |
| var d = [a]; | |
| if(a == sendAction.UPDATE_DIR) { | |
| d.push(b.dir); | |
| var e = intToBytes(b.coord[0], 2); | |
| d.push(e[0]), d.push(e[1]); | |
| var f = intToBytes(b.coord[1], 2); | |
| d.push(f[0]), d.push(f[1]) | |
| } | |
| if(a != sendAction.SET_USERNAME && a != sendAction.SET_TEAM_USERNAME && a != sendAction.PATREON_CODE || (c = toUTF8Array(b), d.push.apply(d, c)), a == sendAction.SKIN && (d.push(b.blockColor), d.push(b.pattern)), a == sendAction.REQUEST_CLOSE) | |
| for(var g = 0; g < b.length; g++) d.push(b[g]); | |
| if(a == sendAction.HONK && d.push(b), a == sendAction.MY_TEAM_URL && (c = toUTF8Array(b), d.push.apply(d, c)), a == sendAction.VERSION) { | |
| d.push(b.type); | |
| var h = intToBytes(b.ver, 2); | |
| d.push(h[0]), d.push(h[1]) | |
| } | |
| var i = new Uint8Array(d); | |
| try { | |
| return ws.send(i), !0 | |
| } catch(c) { | |
| console.log("error sending message", a, b, d, c) | |
| } | |
| } | |
| return !1 | |
| } | |
| function resetAll() { | |
| ws && ws.readyState == WebSocket.OPEN && ws.close(), ws = null, isConnecting = !1, blocks = [], players = [], camPosSet = !1, beginScreenVisible = !0, myPos = null, myRank = 0, scoreStat = scoreStatTarget = realScoreStat = realScoreStatTarget = 25, myRankSent = !1, totalPlayers = 0, playingAndReady = !1, camShakeForces = [], titleComplete = !1, resetTitleNextFrame = !0, allowSkipDeathTransition = !1, skipDeathTransition = !1, minimapCtx.clearRect(0, 0, 160, 160), hasReceivedChunkThisGame = !1, didSendSecondReady = !1, showBeginHideMainCanvas(), doRefreshAfterDie && location.reload(); | |
| var a = document.body.style; | |
| a.webkitFilter = a.filter = null; | |
| for(var b = currentTopNotifications.length - 1; b >= 0; b--) { | |
| var c = currentTopNotifications[b]; | |
| c.destroy() | |
| } | |
| currentTopNotifications = [], sendDirQueue = [], clearAllLives() | |
| } | |
| function initTutorial() { | |
| tutorialBlocks = []; | |
| for(var a = 0; a < 10; a++) | |
| for(var b = 0; b < 10; b++) { | |
| var c = getBlock(a, b, tutorialBlocks), | |
| d = 1; | |
| a >= 1 && a <= 3 && b >= 1 && b <= 3 && (d = 10), c.setBlockId(d, !1) | |
| } | |
| tutorialPlayers = []; | |
| var e = getPlayer(1, tutorialPlayers); | |
| e.skinBlock = 8, e.hasReceivedPosition = !0; | |
| var f = getPlayer(2, tutorialPlayers); | |
| f.skinBlock = 0, f.pos = [-2, 7], f.hasReceivedPosition = !0 | |
| } | |
| function initSkinScreen() { | |
| skinButtonCanvas = document.getElementById("skinButton"), skinButtonShadow = document.getElementById("skinButtonShadow"), shareTw = document.getElementById("shareTw"), shareFb = document.getElementById("shareFb"), shareTw.onclick = function() { | |
| popUp("https://twitter.com/intent/tweet?text=Check%20out%20this%20game%20I%27ve%20just%20found&url=http://splix.io&hashtags=splixio&related=splixio%3AOfficial%20Twitter%20account,jespertheend%3ADeveloper,", 500, 300), share() | |
| }, shareFb.onclick = function() { | |
| popUp("https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.facebook.com%2Fsplix.io%2F&display=popup&ref=plugin&src=like&app_id=840486436000126", 500, 300), share() | |
| }, shareToUnlock = document.getElementById("shareToUnlock"), skinButtonCtx = skinButtonCanvas.getContext("2d"), skinButtonCanvas.onclick = function() { | |
| ws || isTransitioning || playingAndReady || doTransition("", !1, openSkinScreen) | |
| }; | |
| var a = localStorage.getItem("skinColor"); | |
| null === a && (a = 0), a = parseInt(a); | |
| var b = localStorage.getItem("skinPattern"); | |
| null === b && (b = 0), b = parseInt(b), skinScreenBlocks = [], fillArea(0, 0, 2 * VIEWPORT_RADIUS, 2 * VIEWPORT_RADIUS, a + 1, b, skinScreenBlocks), document.getElementById("prevColor").onclick = function() { | |
| skinButton(-1, 0) | |
| }, document.getElementById("nextColor").onclick = function() { | |
| skinButton(1, 0) | |
| }, document.getElementById("prevPattern").onclick = function() { | |
| skinButton(-1, 1) | |
| }, document.getElementById("nextPattern").onclick = function() { | |
| skinButton(1, 1) | |
| }, document.getElementById("skinSave").onclick = function() { | |
| doTransition("", !1, showBeginHideSkin) | |
| }; | |
| var c = getBlock(0, 0, skinButtonBlocks); | |
| c.setBlockId(a + 1, !1), skinButtonCanvas.onmouseover = function() { | |
| var a = localStorage.getItem("skinColor"); | |
| null === a && (a = 0), a = parseInt(a), a > 0 && skinButtonBlocks[0].setBlockId(a + 1 + SKIN_BLOCK_COUNT, !1) | |
| }, skinButtonCanvas.onmouseout = function() { | |
| var a = localStorage.getItem("skinColor"); | |
| null === a && (a = 0), skinButtonBlocks[0].setBlockId(parseInt(a) + 1, !1) | |
| }, checkShared() | |
| } | |
| function initTitle() { | |
| for(var a = 0; a < titleLines.length; a++) | |
| for(var b = titleLines[a], c = 0; c < b.line.length; c++) | |
| for(var d = b.line[c], e = 0; e < d.length; e += 2) d[e] += b.posOffset[0] - 40, d[e + 1] += b.posOffset[1] - 20; | |
| titCanvas = document.getElementById("logoCanvas"), titCtx = titCanvas.getContext("2d") | |
| } | |
| function initGameModeUI() { | |
| gamemodeDropDownEl = document.getElementById("gamemodeSelect"), gamemodeDropDownEl.value = "Normal", gamemodeDropDownEl.onchange = function() { | |
| selectedGamemode = gamemodeDropDownEl.options[gamemodeDropDownEl.selectedIndex].value, setJoinButton(); | |
| var a = "Teams" == selectedGamemode; | |
| teamBox.style.display = a ? null : "none", a ? teamDoConnect() : changeTeamModeToNormalMode() | |
| }, initTeamUI() | |
| } | |
| function setJoinButton() { | |
| if(joinButton.disabled = !1, joinButton.title = "", "Normal" == selectedGamemode) joinButton.value = "Join"; | |
| else if("Teams" == selectedGamemode) { | |
| joinButton.value = "Start", testTeamWsConnection() ? (teamBeginUIIsHost || (joinButton.disabled = !0, joinButton.title = "Only the team host can start a game"), teamPlayersList.childNodes.length <= 1 && (joinButton.disabled = !0, joinButton.title = "Not enough players")) : (joinButton.disabled = !0, joinButton.title = "Not connected to the team server"); | |
| var a = teamPlayersList.childNodes.length > 1; | |
| document.getElementById("teamShareLinkDesc").innerHTML = a ? teamBeginUIIsHost ? "Click Start to start the game." : "Waiting for host to start the game." : "Share this url with your<br>friends to create a team.", document.getElementById("teamPlayersContainer").style.display = a ? null : "none" | |
| } | |
| } | |
| function initTeamUI() { | |
| if(teamShareLink.ondblclick = function() { | |
| window.getSelection && selectTeamShareLink() | |
| }, document.addEventListener("mouseup", function() { | |
| var a = window.getSelection(); | |
| if(a.rangeCount > 0) { | |
| var b = a.getRangeAt(0); | |
| if(b.startContainer.parentElement == teamShareLink && 0 === b.startOffset) { | |
| a.removeAllRanges(); | |
| var c = document.createRange(); | |
| c.selectNodeContents(teamShareLink), c.setEnd(b.endContainer, b.endOffset), a.addRange(c) | |
| } | |
| } | |
| }), teamShareCopyBtn.onclick = function() { | |
| var a = selectTeamShareLink(); | |
| document.execCommand("copy"), a.removeAllRanges() | |
| }, 0 === location.hash.indexOf("#team-")) { | |
| teamShareUrl = location.hash.substring(6); | |
| var a = testExistingTeamHash(); | |
| a && (preventTeamServerConnection = !0), gamemodeDropDownEl.value = "Teams", gamemodeDropDownEl.onchange(), a && connectWithTransition(!0) | |
| } | |
| nameInput.addEventListener("change", nameInputOnChange), teamNameInput.addEventListener("change", teamNameInputOnChange) | |
| } | |
| function testExistingTeamHash() { | |
| var a = Date.now() - parseInt(localStorage.lastTeamJoinTime), | |
| b = localStorage.lastTeamShareUrl, | |
| c = location.hash.substring(6); | |
| return a < 36e5 && b == c | |
| } | |
| function selectTeamShareLink() { | |
| var a = document.createRange(); | |
| a.selectNodeContents(teamShareLink); | |
| var b = window.getSelection(); | |
| return b.removeAllRanges(), b.addRange(a), b | |
| } | |
| function teamDoConnect() { | |
| if(preventTeamServerConnection) return void(preventTeamServerConnection = !1); | |
| if(setTeamBoxLoadVisibility(), teamServers.length <= 0) return void(teamDoConnectAfterServersGet = !0); | |
| var a = null; | |
| if(0 === location.hash.indexOf("#team-")) | |
| for(var b = location.hash.substr(6, 1), c = 0; c < teamServers.length; c++) { | |
| var d = teamServers[c]; | |
| d.letter == b && (a = d) | |
| } | |
| null === a && (a = randFromArray(activeTeamServers)); | |
| var e = a.port; | |
| connectedTeamServerLetter = a.letter, teamWs4 = newTeamWs(a.ipv4 + ":" + e + "/teamServer"), teamWs6 = newTeamWs("[" + a.ipv6 + "]:" + e + "/teamServer") | |
| } | |
| function newTeamWs(a) { | |
| var b = new WebSocket("ws://" + a); | |
| return b.binaryType = "arraybuffer", b.onmessage = function(a) { | |
| teamWs == this && teamWsOnMessage(a) | |
| }, b.onclose = function() { | |
| teamWs4 == this && (teamWs4Failed = !0), teamWs6 == this && (teamWs6Failed = !0), (teamWs == this || teamWs4Failed && teamWs6Failed) && teamWsOnClose() | |
| }, b.onopen = function() { | |
| testTeamWsConnection() ? b.close() : (teamWs = b, teamWs4 = null, teamWs6 = null, teamWsOnConnect()), setTeamBoxLoadVisibility() | |
| }, b | |
| } | |
| function testTeamWsConnection() { | |
| return null !== teamWs && teamWs.readyState == WebSocket.OPEN | |
| } | |
| function setTeamBoxLoadVisibility() { | |
| var a = testTeamWsConnection(); | |
| teamBoxLoading.style.display = a ? "none" : null, teamBoxLoaded.style.display = a ? null : "none" | |
| } | |
| function teamWsOnConnect() { | |
| if(teamBeginUIIsHost = !1, teamWsWasConnected = !0, setJoinButton(), setTeamNameUI(), 0 === location.hash.indexOf("#team-")) { | |
| var a = location.hash, | |
| b = a.substring(7, a.length); | |
| teamWsSendMsg(teamSendAction.REQUEST_TEAM_ID, b) | |
| } else "" !== lastTeamLostConnShareUrl && Date.now() - lastTeamLostConnTime < 12e4 ? (teamWsSendMsg(teamSendAction.REQUEST_TEAM_ID, lastTeamLostConnShareUrl.substring(1)), lastTeamLostConnShareUrl = "") : teamWsSendMsg(teamSendAction.REQUEST_TEAM_ID); | |
| teamSendPlayerName(), teamSendTeamName(), teamSendPingData(), setNotification("") | |
| } | |
| function teamWsOnClose() { | |
| teamWsCloseWasIntended || (teamWsWasConnected ? (setNotification("The connection to the team server was lost :/"), lastTeamLostConnShareUrl = teamShareUrl, lastTeamLostConnTime = Date.now()) : setNotification("Couldn't connect to the team server :/")), setTeamBoxLoadVisibility(), changeTeamModeToNormalMode(), teamWsWasConnected = !1, teamWsCloseWasIntended = !1, teamWs4Failed = !1, teamWs6Failed = !1, teamPlayersList.innerHTML = "", teamShareLink.innerHTML = "loading..." | |
| } | |
| function teamWsClose() { | |
| teamWsCloseWasIntended = !0, testTeamWsConnection() && teamWs.close(), teamWs = null, teamWsOnClose() | |
| } | |
| function changeTeamModeToNormalMode() { | |
| skipChangeToNormalOnce ? skipChangeToNormalOnce = !1 : (location.hash.startsWith("#team") && removeHash(), "Teams" == gamemodeDropDownEl.value && (gamemodeDropDownEl.value = "Normal", gamemodeDropDownEl.onchange()), skipChangeToNormalOnce = !0, teamWsClose()) | |
| } | |
| function removeHash() { | |
| history.pushState("", document.title, location.pathname + location.search) | |
| } | |
| function teamWsOnMessage(a) { | |
| var b, c, d, e, f = new Uint8Array(a.data); | |
| if(f[0] == teamReceiveAction.URL) { | |
| var g = f.subarray(1, f.length); | |
| teamShareUrl = connectedTeamServerLetter + Utf8ArrayToStr(g); | |
| var h = location.host + location.pathname + "#team-" + teamShareUrl; | |
| teamShareLink.innerHTML = '<span class="teamShareLinkHidden">http://</span>' + h, location.hash = "team-" + teamShareUrl | |
| } | |
| if(f[0] == teamReceiveAction.BECOME_HOST && (teamBeginUIIsHost = !0, setJoinButton(), setTeamNameUI()), f[0] == teamReceiveAction.ADD_PLAYER) { | |
| b = bytesToInt(f[1]); | |
| var i = f.subarray(2, f.length), | |
| j = Utf8ArrayToStr(i); | |
| d = "teamPlayer-" + b, c = document.getElementById(d), null === c && (c = document.createElement("li"), c.id = d, teamPlayersList.appendChild(c)), c.innerHTML = testEmtpyName(filter(htmlEscape(j))), setJoinButton() | |
| } | |
| if(f[0] == teamReceiveAction.REMOVE_PLAYER && (b = bytesToInt(f[1]), d = "teamPlayer-" + b, c = document.getElementById(d), null !== c && teamPlayersList.removeChild(c)), f[0] == teamReceiveAction.REQUEST_IPS) { | |
| e = f[1]; | |
| var k = getServer(e, !1); | |
| if(null === k) return void setNotification("Couldn't find a server to connect to :/"); | |
| if(void 0 === k.ip4 || void 0 === k.ip6) { | |
| if(void 0 === k.ip) return void setNotification("Couldn't find a server to connect to :/"); | |
| teamWsSendMsg(teamSendAction.SEND_IPS, [e, k.ip, k.ip]) | |
| } | |
| teamWsSendMsg(teamSendAction.SEND_IPS, [e, k.ip4, k.ip6]) | |
| } | |
| if(f[0] == teamReceiveAction.GAME_START) { | |
| e = f[1]; | |
| for(var l = bytesToInt(f[2], f[3]), m = f.subarray(4, l + 4), n = Utf8ArrayToStr(m), o = f.subarray(l + 4, f.length), p = Utf8ArrayToStr(o), q = "", r = 0; r < servers.length; r++) { | |
| var s = servers[r]; | |
| if(s.locId == e) { | |
| var t = !1; | |
| s.pingTries6 > 0 && s.pingTries <= 0 ? t = !0 : s.pingTries6 > 0 && s.pingTries > 0 && s.avgPing6 < s.avgPing && (t = !0), q = t ? p : n; | |
| break | |
| } | |
| } | |
| lsSet("lastTeamShareUrl", teamShareUrl), lsSet("lastTeamIp", q), lsSet("lastTeamJoinTime", Date.now()), connectWithTransition(!0) | |
| } | |
| if(f[0] == teamReceiveAction.TEAM_IS_FULL && (setNotification("This team is full :("), teamWsClose()), f[0] == teamReceiveAction.SET_TEAM_USERNAME) { | |
| var u = f.subarray(1, f.length), | |
| v = Utf8ArrayToStr(u); | |
| teamNameH.innerHTML = v, teamBeginUIIsHost || (teamNameInput.value = v) | |
| } | |
| } | |
| function teamWsSendMsg(a, b) { | |
| var c; | |
| if(testTeamWsConnection()) { | |
| var d = [a]; | |
| if(a == teamSendAction.REQUEST_TEAM_ID && b && (c = toUTF8Array(b), d.push.apply(d, c)), a != teamSendAction.MY_USERNAME && a != teamSendAction.SET_TEAM_USERNAME || b && (c = toUTF8Array(b), d.push.apply(d, c)), a == teamSendAction.PING_DATA) | |
| for(var e = 0; e < b.length; e++) { | |
| var f = servers[e]; | |
| d.push(f.locId); | |
| var g = f.pingTries > 0 ? f.avgPing : 0, | |
| h = f.pingTries6 > 0 ? f.avgPing6 : 0; | |
| g = Math.round(Math.min(Math.max(0, g), 65e3)), h = Math.round(Math.min(Math.max(0, h), 65e3)); | |
| var i = intToBytes(g, 2), | |
| j = intToBytes(h, 2); | |
| d.push(i[0]), d.push(i[1]), d.push(j[0]), d.push(j[1]) | |
| } | |
| if(a == teamSendAction.SEND_IPS) { | |
| var k = toUTF8Array(b[1]), | |
| l = toUTF8Array(b[2]), | |
| m = intToBytes(k.length, 2); | |
| d.push(b[0]), d.push(m[0]), d.push(m[1]), d.push.apply(d, k), d.push.apply(d, l) | |
| } | |
| var n = new Uint8Array(d); | |
| try { | |
| return teamWs.send(n), !0 | |
| } catch(c) { | |
| console.log("error sending team message", a, b, d, c) | |
| } | |
| } | |
| return !1 | |
| } | |
| function teamSendPlayerName() { | |
| teamWsSendMsg(teamSendAction.MY_USERNAME, nameInput.value) | |
| } | |
| function teamSendTeamName() { | |
| teamWsSendMsg(teamSendAction.SET_TEAM_USERNAME, teamNameInput.value) | |
| } | |
| function teamSendPingData() { | |
| teamWsSendMsg(teamSendAction.PING_DATA, servers) | |
| } | |
| function testEmtpyName(a) { | |
| return /\S/.test(a) ? a : "Enter your name..." | |
| } | |
| function setTeamNameUI() { | |
| teamBeginUIIsHost ? (teamNameH.style.display = "none", teamNameInput.style.display = null) : (teamNameH.style.display = null, teamNameInput.style.display = "none") | |
| } | |
| function teamNameInputOnChange() { | |
| teamSendTeamName(), lsSet("teamName", teamNameInput.value) | |
| } | |
| function requestCanRunAds() { | |
| if(!canRunAdsRequested && testPatreonAdsAllowed()) { | |
| canRunAdsRequested = !0; | |
| var a = document.createElement("script"); | |
| a.type = "text/javascript", a.src = "/js/ads.js"; | |
| var b = document.getElementsByTagName("head")[0]; | |
| b.appendChild(a) | |
| } | |
| } | |
| function initAipScript() { | |
| if(!initAipCalled && testPatreonAdsAllowed()) { | |
| initAipCalled = !0; | |
| var a = document.createElement("script"); | |
| a.type = "text/javascript", a.src = "http://api.adinplay.com/player/v2/JTE/splix.io/player.min.js"; | |
| var b = document.getElementsByTagName("head")[0]; | |
| b.appendChild(a) | |
| } | |
| } | |
| function displayAd() { | |
| isWaitingForAd = !0, formElem.style.display = "none", prerollElem.style.display = null, "undefined" != typeof aipPlayer ? (adplayer = new aipPlayer({ | |
| AD_WIDTH: 960, | |
| AD_HEIGHT: 540, | |
| PREROLL_ELEM: prerollElem, | |
| AIP_COMPLETE: function() { | |
| onAdFinish() | |
| } | |
| }), adplayer.startPreRoll(), onAdLoaded()) : (console.log("couldn't load ad, aipPlayer not defined"), onAdFinish()), scrollAd() | |
| } | |
| function getScript(a, b) { | |
| var c = document.head || document.getElementsByTagName("head")[0], | |
| d = document.createElement("script"), | |
| e = !0; | |
| d.async = "async", d.type = "text/javascript", d.charset = "UTF-8", d.src = a, d.onload = d.onreadystatechange = function() { | |
| !e || d.readyState && !/loaded|complete/.test(d.readyState) || (e = !1, b(), d.onload = d.onreadystatechange = null) | |
| }, c.appendChild(d) | |
| } | |
| function onAdLoaded(a) { | |
| lsSet("refreshDuringAd", "true"), prerollIsVisible = !0, document.getElementById("shareText").className = shareToUnlock.className = appLinksElem.className = "adRunning", hideBanner() | |
| } | |
| function scrollAd() { | |
| var a = prerollElem.offsetTop, | |
| b = a + prerollElem.offsetHeight, | |
| c = document.documentElement.scrollTop || document.body.scrollTop, | |
| d = c + window.innerHeight, | |
| e = (a + b) / 2; | |
| (a < c || b > d) && window.scroll(0, e - window.innerHeight / 2) | |
| } | |
| function onAdFinish() { | |
| countAd(), lsSet("refreshDuringAd", ""), prerollIsVisible = !1, lsSet("lastAdTime", Date.now()), formElem.style.display = null, prerollElem.style.display = "none", document.getElementById("shareText").className = shareToUnlock.className = null, isConnectingWithTransition = !1, isWaitingForAd = !1, connectWithTransition(!0) | |
| } | |
| function getAdCounter() { | |
| var a = localStorage.adCounter; | |
| return void 0 === a && (a = 0), a = parseInt(a), isNaN(a) && (a = 0), a | |
| } | |
| function countAd() { | |
| var a = getAdCounter(); | |
| a++, a > 5 && (a = 0), lsSet("adCounter", a) | |
| } | |
| function refreshBanner() { | |
| testPatreonAdsAllowed() && googletag.cmd.push(function() { | |
| googletag.pubads().refresh() | |
| }) | |
| } | |
| function showBanner() { | |
| prerollIsVisible || (adBox.style.display = null) | |
| } | |
| function hideBanner() { | |
| adBox.style.display = "none" | |
| } | |
| function setAdBoxLeft() { | |
| adBox.style.left = "-" + (adBox.clientWidth + 20) + "px" | |
| } | |
| function showCursor() { | |
| document.body.style.cursor = null | |
| } | |
| function afterDeath() { | |
| switch(afterDeathCounter++, afterDeathCounter) { | |
| case 1: | |
| window.twttr = function(a, b, c) { | |
| var d, e = a.getElementsByTagName(b)[0], | |
| f = window.twttr || {}; | |
| return a.getElementById(c) ? f : (d = a.createElement(b), d.id = c, d.src = "https://platform.twitter.com/widgets.js", e.parentNode.insertBefore(d, e), f._e = [], f.ready = function(a) { | |
| f._e.push(a) | |
| }, f) | |
| }(document, "script", "twitter-wjs"), twttr.ready(function(a) { | |
| a.events.bind("rendered", function() { | |
| twttrIsInit = !0, testSocialReady() | |
| }), a.events.bind("tweet", function() { | |
| share() | |
| }) | |
| }), window.fbAsyncInit = function() { | |
| FB.Event.subscribe("xfbml.render", function() { | |
| fbIsInit = !0, testSocialReady() | |
| }) | |
| }, | |
| function(a, b, c) { | |
| var d, e = a.getElementsByTagName(b)[0]; | |
| a.getElementById(c) || (d = a.createElement(b), d.id = c, d.src = "//connect.facebook.net/en_US/sdk/xfbml.ad.js#xfbml=1&version=v2.5&appId=1812921762327343", e.parentNode.insertBefore(d, e)) | |
| }(document, "script", "facebook-jssdk"); | |
| var a = document.getElementsByTagName("head")[0], | |
| b = document.createElement("script"); | |
| b.type = "text/javascript", b.src = "https://apis.google.com/js/platform.js", b.onload = function() { | |
| ytIsInit = !0 | |
| }, a.appendChild(b); | |
| var c = document.createElement("img"); | |
| c.id = "discord", c.className = "socialHover", c.draggable = !1, c.title = "splix.io discord group", c.onload = function() { | |
| discordIsInit = !0, testSocialReady() | |
| }, c.src = "/img/discord.svg", document.getElementById("discordA").appendChild(c); | |
| var d = document.createElement("img"); | |
| d.id = "reddit", d.className = "socialHover", d.draggable = !1, d.title = "splix.io on reddit", d.onload = function() { | |
| redditIsInit = !0, testSocialReady() | |
| }, d.src = "/img/reddit.svg", document.getElementById("redditA").appendChild(d); | |
| var e = document.createElement("img"); | |
| e.id = "patreonCornerButton", e.className = "socialHover", e.draggable = !1, e.title = "Become a patreon of splix.io", e.onload = function() { | |
| patreonCornerButtonIsInit = !0, testSocialReady() | |
| }, e.src = "/img/patreon.png"; | |
| var f = document.getElementById("patreonA"); | |
| f.appendChild(e), f.appendChild(document.createElement("br")), requestCanRunAds(); | |
| var g = document.createElement("img"); | |
| g.alt = "Get it on Google Play", g.style.width = "250px", g.style.display = "block", g.onload = function() { | |
| androidImgIsInit = !0, testAppLinksReady() | |
| }, g.src = "https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"; | |
| var h = document.createElement("a"); | |
| h.href = "https://play.google.com/store/apps/details?id=com.Jespertheend.splix", h.target = "_blank", h.appendChild(g), appLinksElem.appendChild(h); | |
| var i = document.createElement("img"); | |
| i.alt = "Download on the App Store", i.style.width = "220px", i.style.marginBottom = "15px", i.onload = function() { | |
| appleImgIsInit = !0, testAppLinksReady() | |
| }, i.src = "https://linkmaker.itunes.apple.com/images/badges/en-us/badge_appstore-lrg.svg"; | |
| var j = document.createElement("a"); | |
| j.href = "https://itunes.apple.com/app/id1150901618", j.target = "_blank", j.appendChild(i), appLinksElem.appendChild(j); | |
| var k = "splixio.org;splix-io.net;splixio.net;splixio.org".split(";"); | |
| if(this.top.location !== this.location) | |
| for(var l = 0; l < k.length; l++) { | |
| var m = k[l]; | |
| document.referrer.indexOf(m) != -1 && (this.top.location = this.location) | |
| } | |
| initAipScript() | |
| } | |
| } | |
| function testAppLinksReady() { | |
| androidImgIsInit && appleImgIsInit && !doneAppLinksReady && (doneAppLinksReady = !0, onAppLinksReady()) | |
| } | |
| function onAppLinksReady() { | |
| animateAppLinks = !0 | |
| } | |
| function testSocialReady() { | |
| twttrIsInit && fbIsInit && ytIsInit && discordIsInit && redditIsInit && patreonCornerButtonIsInit && !doneOnSocialReady && (doneOnSocialReady = !0, onSocialReady()) | |
| } | |
| function onSocialReady() { | |
| socialIsReady = !0, socialElem.style.display = null, window.setTimeout(function() { | |
| testSocialTarget() | |
| }, 500) | |
| } | |
| function testSocialTarget() { | |
| socialOTarget = socialIsReady ? socialHovering ? 1 : .2 : 0 | |
| } | |
| function popUp(a, b, c) { | |
| var d = screen.width / 2 - b / 2, | |
| e = screen.height / 2 - c / 2; | |
| window.open(a, "_blank", "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=" + b + ", height=" + c + ", top=" + e + ", left=" + d) | |
| } | |
| function share(a) { | |
| void 0 === a && (a = 3e3), lsSet("s", 1), window.setTimeout(function() { | |
| checkShared() | |
| }, a) | |
| } | |
| function checkShared() { | |
| var a = !!localStorage.s, | |
| b = a ? null : "none", | |
| c = a ? "none" : null; | |
| skinButtonCanvas.style.display = b, skinButtonShadow.style.display = b, shareToUnlock.style.display = c | |
| } | |
| function colorUI() { | |
| for(var a = getColorForBlockSkinId(myColorId), b = a.brighter, c = a.darker, d = 0; d < uiElems.length; d++) { | |
| var e = uiElems[d]; | |
| colorBox(e, b, c) | |
| } | |
| } | |
| function colorBox(a, b, c) { | |
| a.style.backgroundColor = b, a.style.boxShadow = "1px 1px " + c + ",2px 2px " + c + ",3px 3px " + c + ",4px 4px " + c + ",5px 5px " + c + ",10px 30px 80px rgba(0,0,0,0.3)" | |
| } | |
| function skinButton(a, b) { | |
| if(0 === b) { | |
| var c = localStorage.getItem("skinColor"), | |
| d = []; | |
| localStorage.patreonLastPledgedValue >= 300 || d.push(13), null === c && (c = 0), c = parseInt(c); | |
| for(var e = !1; !e;) c += a, c = mod(c, SKIN_BLOCK_COUNT + 1), d.indexOf(c) < 0 && (e = !0); | |
| lsSet("skinColor", c) | |
| } else if(1 == b) { | |
| var f = localStorage.getItem("skinPattern"), | |
| g = [18, 19, 20, 21, 23, 24, 25, 26]; | |
| localStorage.patreonLastPledgedValue > 0 || g.push(27), null === f && (f = 0), f = parseInt(f); | |
| for(var h = !1; !h;) f += a, f = mod(f, SKIN_PATTERN_COUNT), g.indexOf(f) < 0 && (h = !0); | |
| lsSet("skinPattern", f) | |
| } | |
| updateSkin() | |
| } | |
| function updateSkin() { | |
| var a = parseInt(localStorage.skinColor) + 1; | |
| fillArea(0, 0, 2 * VIEWPORT_RADIUS, 2 * VIEWPORT_RADIUS, a, parseInt(localStorage.skinPattern), skinScreenBlocks), skinButtonBlocks[0].setBlockId(a) | |
| } | |
| function clearAllLives() { | |
| lifeBox.innerHTML = "", lives = [] | |
| } | |
| function setLives(a, b) { | |
| var c, d, e = lives.length; | |
| for(d = 0; d < b - e; d++) { | |
| var f = document.createElement("canvas"); | |
| f.style.margin = "-15px"; | |
| var g = f.getContext("2d"); | |
| c = { | |
| node: f, | |
| ctx: g, | |
| timer: 0, | |
| animDir: 0, | |
| isLife: !0, | |
| render: function(a, b) { | |
| if(0 !== this.animDir || b) | |
| if(this.timer += a * this.animDir * .002, 1 == this.animDir ? this.timer > 1 && (this.timer = 1, this.afterAnimate()) : this.timer < 0 && (this.timer = 0, this.afterAnimate()), canvasTransformType = canvasTransformTypes.LIFE, ctxApplyCamTransform(this.ctx, !0, !0), this.ctx.fillStyle = "rgba(0,0,0,0.3)", this.drawHeart(!1, 15.7, 15.7), 1 == this.animDir) { | |
| this.ctx.fillStyle = colors.red.darker, this.ctx.translate(30, 30); | |
| var c = this.timer; | |
| c = c < .8 ? lerp(0, 1.2, ease.in(iLerp(0, .8, c))) : lerp(1.2, 1, ease.in(iLerp(.8, 1, c))); | |
| var d = .5 * (1 - c); | |
| this.ctx.rotate(d), this.ctx.scale(c, c), this.ctx.translate(-30, -30), this.drawHeart(!1, 15.7, 15.7), this.ctx.fillStyle = colors.red.brighter, this.drawHeart(!1, 14.3, 14.3), this.ctx.restore() | |
| } else this.ctx.globalAlpha = this.timer, this.ctx.fillStyle = colors.red.darker, this.drawHeart(!0, 15.7, 15.7), this.ctx.fillStyle = colors.red.brighter, this.drawHeart(!0, 14.3, 14.3), this.ctx.restore() | |
| }, | |
| drawHeart: function(a, b, c) { | |
| if(a && 1 != this.timer) { | |
| var d, e, f = ease.out(1 - this.timer); | |
| d = b + 3 * f, e = c - 12 * f, this.ctx.beginPath(), this.ctx.moveTo(15 + d, 16.5 + e), this.ctx.lineTo(15 + d, 12 + e), this.ctx.bezierCurveTo(15 + d, 8.1 + e, 17.4 + d, 5.25 + e, 21 + d, 5.25 + e), this.ctx.fill(), d = b + 9 * f, e = c - 1.5 * f, this.ctx.beginPath(), this.ctx.moveTo(15 + d, 16.5 + e), this.ctx.lineTo(21 + d, 5.25 + e), this.ctx.bezierCurveTo(24 + d, 5.25 + e, 27 + d, 7.5 + e, 27 + d, 12 + e), this.ctx.bezierCurveTo(27 + d, 15.3 + e, 23.25 + d, 19.35 + e, 23.1 + d, 19.5 + e), this.ctx.fill(), d = b + 6 * f, e = c + 9 * f, this.ctx.beginPath(), this.ctx.moveTo(15 + d, 16.5 + e), this.ctx.lineTo(23.1 + d, 19.5 + e), this.ctx.bezierCurveTo(23.1 + d, 19.8 + e, 17.55 + d, 25.11 + e, 17.1 + d, 25.35 + e), this.ctx.fill(), d = b - 1.5 * f, e = c + 9 * f, this.ctx.beginPath(), this.ctx.moveTo(15 + d, 16.5 + e), this.ctx.lineTo(17.1 + d, 25.35 + e), this.ctx.lineTo(15 + d, 27 + e), this.ctx.bezierCurveTo(14.91 + d, 27 + e, 10.5 + d, 23.28 + e, 10.5 + d, 23.16 + e), this.ctx.fill(), d = b - 12 * f, e = c + 1.5 * f, this.ctx.beginPath(), this.ctx.moveTo(15 + d, 16.5 + e), this.ctx.lineTo(10.5 + d, 23.16 + e), this.ctx.bezierCurveTo(10.5 + d, 23.16 + e, 3 + d, 16.65 + e, 3 + d, 12 + e), this.ctx.fill(), d = b - 3 * f, e = c - 6 * f, this.ctx.beginPath(), this.ctx.moveTo(15 + d, 16.5 + e), this.ctx.lineTo(3 + d, 12 + e), this.ctx.bezierCurveTo(3 + d, 3 + e, 15 + d, 3 + e, 15 + d, 12 + e), this.ctx.fill() | |
| } else this.ctx.beginPath(), this.ctx.moveTo(15 + b, 12 + c), this.ctx.bezierCurveTo(15 + b, 3 + c, 27 + b, 3 + c, 27 + b, 12 + c), this.ctx.bezierCurveTo(27 + b, 18 + c, 15 + b, 27 + c, 15 + b, 27 + c), this.ctx.bezierCurveTo(15 + b, 27 + c, 3 + b, 18 + c, 3 + b, 12 + c), this.ctx.bezierCurveTo(3 + b, 3 + c, 15 + b, 3 + c, 15 + b, 12 + c), this.ctx.fill() | |
| }, | |
| afterAnimate: function() { | |
| this.animDir = 0, this.set(this.isLife) | |
| }, | |
| set: function(a) { | |
| this.isLife = a, 0 === this.animDir && (a ? this.timer < 1 && (this.animDir = 1) : this.timer > 0 && (this.animDir = -1)) | |
| } | |
| }, lifeBox.appendChild(f), lives.push(c), c.render(0, !0) | |
| } | |
| for(d = e - 1; d >= b; d--) c = lives[d], lifeBox.removeChild(c.node), lives.splice(d, 1); | |
| for(d = 0; d < lives.length; d++) c = lives[d], c.set(a > d) | |
| } | |
| function renderAllLives(a) { | |
| for(var b = 0; b < lives.length; b++) { | |
| var c = lives[b]; | |
| c.render(a) | |
| } | |
| } | |
| function engagementSetIsPlaying(a) { | |
| var b = Date.now(); | |
| if(a != engagementIsPlaying) { | |
| lsSet("engagementIsPlaying", a), engagementIsPlaying = a; | |
| var c; | |
| c = a ? engagementLastNoPlayTime : engagementLastPlayTime; | |
| var d = c - engagementLastChangeTime; | |
| d /= 2e4, engagementValue = a ? lerptt(engagementValue, 0, .01, d / 100) : lerptt(engagementValue, 1, .01, d), lsSet("engagementValue", engagementValue), engagementLastChangeTime = b, lsSet("engagementLastChangeTime", b) | |
| } | |
| a ? (lsSet("engagementLastPlayTime", b), engagementLastPlayTime = b) : engagementLastNoPlayTime = b | |
| } | |
| function loopRetentionSamples(a) { | |
| for(var b = 0; b < retentionSamples.length; b++) { | |
| var c = retentionSamples[b]; | |
| if(c.secondsFromNow -= a / 1e3, c.secondsFromNow < 0) { | |
| var d = c.sampleId; | |
| if(sentRetentionSamples.indexOf(d) == -1) { | |
| sentRetentionSamples.push(d), saveSentRetentionSamples(); | |
| var e = Math.round(100 * engagementValue); | |
| simpleRequest("http://stats.splix.io/retention.php?value=" + e + "&id=" + d) | |
| } | |
| } | |
| } | |
| } | |
| function loadSentRetentionSamples() { | |
| var a = localStorage.sentRetentionSamples; | |
| void 0 === a && (a = ""); | |
| var b = a.split(","); | |
| sentRetentionSamples = []; | |
| for(var c = 0; c < b.length; c++) { | |
| var d = parseInt(b[c]); | |
| isNaN(d) || sentRetentionSamples.push(d) | |
| } | |
| } | |
| function saveSentRetentionSamples() { | |
| lsSet("sentRetentionSamples", sentRetentionSamples.join(",")) | |
| } | |
| function loginWithPatreon() { | |
| lsSet("clickedLoginWithPatreonButton", "true"), window.location = "http://www.patreon.com/oauth2/authorize?response_type=code&client_id=29edae8672a352342c2ecda5ff440eda65e5e52ebc7500b02eefb481c94c88b1&scope=users%20pledges-to-me%20my-campaign&redirect_uri=http%3A%2F%2Fsplix.io" | |
| } | |
| function parsePatreonAuths(a) { | |
| a = JSON.parse(a), "access" in a && "refresh" in a && (lsSet("patreonAccess", a.access), lsSet("patreonRefresh", a.refresh), lsSet("patreonAccessTime", Date.now())) | |
| } | |
| function requestPatreonPledgeData() { | |
| "" === localStorage.patreonAccess || void 0 === localStorage.patreonAccess ? resetPatreonPledgedData() : simpleRequest("http://patreon.splix.io/requestPledge.php?accessToken=" + localStorage.patreonAccess, function(a) { | |
| a = JSON.parse(a), "pledged" in a && "splixCode" in a ? (lsSet("patreonLastPledgedValue", a.pledged), lsSet("patreonLastSplixCode", a.splixCode)) : resetPatreonPledgedData(); | |
| var b = localStorage.patreonAccessTime; | |
| void 0 === b && (b = 0), Date.now() - b > 1296e6 && refreshPatreonAccessCode() | |
| }) | |
| } | |
| function resetPatreonPledgedData() { | |
| lsSet("patreonLastPledgedValue", 0), lsSet("patreonLastSplixCode", "") | |
| } | |
| function refreshPatreonAccessCode() { | |
| simpleRequest("http://patreon.splix.io/login.php?code=" + localStorage.patreonAccess + "&refresh=" + localStorage.patreonRefresh, function(a) { | |
| parsePatreonAuths(a) | |
| }) | |
| } | |
| function testPatreonAdsAllowed() { | |
| return !(localStorage.patreonLastPledgedValue > 0) | |
| } | |
| function removeBlocksOutsideViewport(a) { | |
| for(i = blocks.length - 1; i >= 0; i--) { | |
| var b = blocks[i]; | |
| (b.x < a[0] - 2 * VIEWPORT_RADIUS || b.x > a[0] + 2 * VIEWPORT_RADIUS || b.y < a[1] - 2 * VIEWPORT_RADIUS || b.y > a[1] + 2 * VIEWPORT_RADIUS) && blocks.splice(i, 1) | |
| } | |
| } | |
| function getColorForBlockSkinId(a) { | |
| switch(a) { | |
| case 0: | |
| return colors.red; | |
| case 1: | |
| return colors.red2; | |
| case 2: | |
| return colors.pink; | |
| case 3: | |
| return colors.pink2; | |
| case 4: | |
| return colors.purple; | |
| case 5: | |
| return colors.blue; | |
| case 6: | |
| return colors.blue2; | |
| case 7: | |
| return colors.green; | |
| case 8: | |
| return colors.green2; | |
| case 9: | |
| return colors.leaf; | |
| case 10: | |
| return colors.yellow; | |
| case 11: | |
| return colors.orange; | |
| case 12: | |
| return colors.gold; | |
| default: | |
| return { | |
| brighter: "#000000", | |
| darker: "#000000", | |
| slightlyBrighter: "#000000" | |
| } | |
| } | |
| } | |
| function ctxCanvasSize(a, b) { | |
| var c = window.innerWidth, | |
| d = window.innerHeight; | |
| canvasTransformType == canvasTransformTypes.TUTORIAL && (c = d = 300), canvasTransformType == canvasTransformTypes.SKIN_BUTTON && (c = d = 30), canvasTransformType == canvasTransformTypes.LIFE && (c = d = 60), canvasTransformType == canvasTransformTypes.TITLE && (c = 520, d = 180); | |
| var e = b ? 1 : canvasQuality, | |
| f = a.canvas; | |
| f.width = c * MAX_PIXEL_RATIO * e, f.height = d * MAX_PIXEL_RATIO * e; | |
| var g = 1; | |
| canvasTransformType == canvasTransformTypes.TITLE && (g = Math.min(1, (window.innerWidth - 30) / c)), f.style.width = c * g + "px", f.style.height = d * g + "px" | |
| } | |
| function ctxApplyCamTransform(a, b, c) { | |
| b && ctxCanvasSize(a, c), a.save(); | |
| var d = c ? 1 : canvasQuality; | |
| if(canvasTransformType != canvasTransformTypes.MAIN && canvasTransformType != canvasTransformTypes.SKIN && a.setTransform(MAX_PIXEL_RATIO * d, 0, 0, MAX_PIXEL_RATIO * d, 0, 0), canvasTransformType == canvasTransformTypes.MAIN || canvasTransformType == canvasTransformTypes.SKIN) { | |
| var e = canvasTransformType == canvasTransformTypes.MAIN; | |
| a.translate(mainCanvas.width / 2, mainCanvas.height / 2); | |
| var f = Math.max(mainCanvas.width, mainCanvas.height), | |
| g = f / MAX_ZOOM, | |
| h = mainCanvas.width * mainCanvas.height, | |
| i = h / BLOCKS_ON_SCREEN, | |
| j = Math.sqrt(i) / 10; | |
| zoom = Math.max(j, g), e && a.rotate(camRotOffset), a.scale(zoom, zoom), e ? a.translate(10 * -camPosPrevFrame[0] - camPosOffset[0], 10 * -camPosPrevFrame[1] - camPosOffset[1]) : a.translate(10 * -VIEWPORT_RADIUS, 10 * -VIEWPORT_RADIUS) | |
| } else canvasTransformType != canvasTransformTypes.TUTORIAL && canvasTransformType != canvasTransformTypes.SKIN_BUTTON || a.scale(3, 3) | |
| } | |
| function doCamShake(a, b, c) { | |
| void 0 === c && (c = !0), camShakeForces.push([a, b, 0, !!c]) | |
| } | |
| function doCamShakeDir(a, b, c) { | |
| void 0 === b && (b = 6); | |
| var d = 0, | |
| e = 0; | |
| switch(a) { | |
| case 0: | |
| d = b; | |
| break; | |
| case 1: | |
| e = b; | |
| break; | |
| case 2: | |
| d = -b; | |
| break; | |
| case 3: | |
| e = -b | |
| } | |
| doCamShake(d, e, c) | |
| } | |
| function calcCamOffset() { | |
| camPosOffset = [0, 0], camRotOffset = 0; | |
| for(var a = camShakeForces.length - 1; a >= 0; a--) { | |
| var b = camShakeForces[a]; | |
| b[2] += .003 * deltaTime; | |
| var c = b[2], | |
| d = 0, | |
| e = 0; | |
| c < 1 ? (e = ease.out(c), d = ease.inout(c)) : c < 8 ? (e = ease.inout(iLerp(8, 1, c)), d = ease.in(iLerp(8, 1, c))) : camShakeForces.splice(a, 1), camPosOffset[0] += b[0] * e, camPosOffset[1] += b[1] * e, camPosOffset[0] += b[0] * Math.cos(8 * c) * .04 * d, camPosOffset[1] += b[1] * Math.cos(7 * c) * .04 * d, b[3] && (camRotOffset += .003 * Math.cos(9 * c) * d) | |
| } | |
| var f = 80; | |
| camPosOffset[0] /= f, camPosOffset[1] /= f, camPosOffset[0] = smoothLimit(camPosOffset[0]), camPosOffset[1] = smoothLimit(camPosOffset[1]), camPosOffset[0] *= f, camPosOffset[1] *= f | |
| } | |
| function lerp(a, b, c) { | |
| return a + c * (b - a) | |
| } | |
| function iLerp(a, b, c) { | |
| return(c - a) / (b - a) | |
| } | |
| function lerpt(a, b, c) { | |
| return lerptt(a, b, c, deltaTime / 16.6666) | |
| } | |
| function lerptt(a, b, c, d) { | |
| var e = 1 - Math.pow(1 - c, d); | |
| return lerp(a, b, e) | |
| } | |
| function lerpA(a, b, c) { | |
| for(var d = [], e = 0; e < a.length; e++) d.push(lerp(a[e], b[e], c)); | |
| return d | |
| } | |
| function mod(a, b) { | |
| return(a % b + b) % b | |
| } | |
| function clamp(a, b, c) { | |
| return Math.max(b, Math.min(c, a)) | |
| } | |
| function clamp01(a) { | |
| return clamp(a, 0, 1) | |
| } | |
| function randFromArray(a) { | |
| return a[Math.floor(Math.random() * a.length)] | |
| } | |
| function smoothLimit(a) { | |
| var b = a < 0; | |
| return b && (a *= -1), a = 1 - Math.pow(2, -a), b && (a *= -1), a | |
| } | |
| function updateStats() { | |
| myRank > totalPlayers && myRankSent ? totalPlayers = myRank : (totalPlayers < myRank || 0 === myRank && totalPlayers > 0) && (myRank = totalPlayers), myRankElem.innerHTML = myRank, totalPlayersElem.innerHTML = totalPlayers | |
| } | |
| function drawTrailOnCtx(a, b, c) { | |
| if(b.length > 0) | |
| for(var d = 0; d < a.length; d++) { | |
| var e = a[d], | |
| f = e.ctx; | |
| f.lineCap = "round", f.lineJoin = "round", f.lineWidth = 6, f.strokeStyle = e.color; | |
| var g = e.offset; | |
| f.beginPath(), f.moveTo(10 * b[0][0] + g, 10 * b[0][1] + g); | |
| for(var h = 1; h < b.length; h++) f.lineTo(10 * b[h][0] + g, 10 * b[h][1] + g); | |
| null !== c && f.lineTo(10 * c[0] + g, 10 * c[1] + g), f.stroke() | |
| } | |
| } | |
| function drawDiagonalLines(a, b, c, d, e) { | |
| if(c > 0) { | |
| a.lineCap = "butt", a.strokeStyle = b, a.lineWidth = c; | |
| var f = 20 * VIEWPORT_RADIUS, | |
| g = 0, | |
| h = 0; | |
| null !== camPosPrevFrame && canvasTransformType == canvasTransformTypes.MAIN && (g = Math.round((10 * camPosPrevFrame[0] - f / 2) / d) * d, h = Math.round((10 * camPosPrevFrame[1] - f / 2) / d) * d), g += e % d; | |
| for(var i = -f; i < f; i += d) { | |
| var j = g + i; | |
| a.beginPath(), a.moveTo(j, h), a.lineTo(j + f, h + f), a.stroke() | |
| } | |
| } | |
| } | |
| function drawAnimatedText(a, b, c, d, e, f, g, h, i, j, k) { | |
| var l; | |
| void 0 === g && (g = "white"), a.fillStyle = g, void 0 === h && (h = "Arial, Helvetica, sans-serif"), a.font = h = f + "px " + h, void 0 === k && (k = 0); | |
| for(var m = 0, n = 0; n < transitionText.length; n++) { | |
| var o = rndSeed(n + k); | |
| void 0 === j && (j = 3); | |
| var p = c * j - o * (j - o), | |
| q = transitionText[n], | |
| r = a.measureText(q).width, | |
| s = e - .77 * f; | |
| if(p < .8) tempCanvas.width = r, tempCanvas.height = f, tempCtx.font = h, tempCtx.fillStyle = "white", tempCtx.fillText(q, 0, .77 * f), p < .4 ? (l = p / .4, tempCtx.beginPath(), tempCtx.moveTo(0, lerp(f, 0, l)), tempCtx.lineTo(0, f), tempCtx.lineTo(lerp(0, r, l), f), tempCtx.closePath()) : (l = p / .4 - 1, tempCtx.moveTo(0, 0), tempCtx.lineTo(0, f), tempCtx.lineTo(r, f), tempCtx.lineTo(r, lerp(f, 0, l)), tempCtx.lineTo(lerp(0, r, l), 0)), tempCtx.globalCompositeOperation = "destination-in", tempCtx.fill(), a.drawImage(tempCanvas, d + m, s); | |
| else { | |
| l = Math.min(1, 5 * p - 4); | |
| var t = l * i; | |
| a.fillStyle = colors.green2.darker; | |
| for(var u = 0; u < t; u++) a.fillText(q, d + m - t + u, e - t + u); | |
| a.fillStyle = "white", a.fillText(q, d + m - t, e - t) | |
| } | |
| m += r - .5 | |
| } | |
| } | |
| function orderTwoPos(a, b) { | |
| var c = Math.min(a[0], b[0]), | |
| d = Math.min(a[1], b[1]), | |
| e = Math.max(a[0], b[0]), | |
| f = Math.max(a[1], b[1]); | |
| return [ | |
| [c, d], | |
| [e, f] | |
| ] | |
| } | |
| function fillArea(a, b, c, d, e, f, g) { | |
| var h = void 0 === g; | |
| h && (g = blocks), void 0 === f && (f = 0); | |
| var i = a + c, | |
| j = b + d; | |
| null !== myPos && h && (a = Math.max(a, Math.round(myPos[0]) - VIEWPORT_RADIUS), b = Math.max(b, Math.round(myPos[1]) - VIEWPORT_RADIUS), i = Math.min(i, Math.round(myPos[0]) + VIEWPORT_RADIUS), j = Math.min(j, Math.round(myPos[1]) + VIEWPORT_RADIUS)); | |
| for(var k = a; k < i; k++) | |
| for(var l = b; l < j; l++) { | |
| var m = getBlock(k, l, g), | |
| n = applyPattern(e, f, k, l); | |
| m.setBlockId(n, 400 * Math.random()) | |
| } | |
| } | |
| function applyPattern(a, b, c, d) { | |
| var e, f; | |
| if(a < 2) return a; | |
| var g = !1; | |
| switch(b) { | |
| case 1: | |
| g = c % 2 === 0 && d % 2 === 0; | |
| break; | |
| case 2: | |
| g = c % 2 == (d % 2 === 0 ? 0 : 1); | |
| break; | |
| case 3: | |
| g = d % 3 < 1 ? c % 3 > 0 : c % 3 < 1; | |
| break; | |
| case 4: | |
| g = c % 5 === 0 || d % 5 === 0; | |
| break; | |
| case 5: | |
| g = (c - d) % 5 === 0; | |
| break; | |
| case 6: | |
| g = Math.random() > .5; | |
| break; | |
| case 7: | |
| e = (c + 7) % 100, f = (d + 7) % 100, g = f < 2 && (e < 2 || e > 3 && e < 6) || 2 == f && e > 1 && e < 4 || f > 2 && f < 5 && e > 0 && e < 5 || 5 == f && (1 == e || 4 == e); | |
| break; | |
| case 8: | |
| g = c % 2 == (d % 2 === 0 ? 0 : 1) && c % 4 !== 0 && d % 4 != 1; | |
| break; | |
| case 9: | |
| g = mod(c % 8 < 4 ? c + d : c - d - 4, 8) < 3; | |
| break; | |
| case 10: | |
| g = c % 2 == (d % 2 === 0 ? 0 : 1) && mod(c % 8 < 4 ? c + d : c - d - 4, 8) < 3; | |
| break; | |
| case 11: | |
| e = c % 10, f = d % 10, g = (0 === e || 6 == e) && f < 7 || (2 == e || 4 == e) && f > 1 && f < 5 || (7 == e || 9 == e) && f > 6 || (0 === f || 6 == f) && e < 7 || (2 == f || 4 == f) && e > 1 && e < 5 || (7 == f || 9 == f) && e > 6; | |
| break; | |
| case 12: | |
| e = (d % 12 < 6 ? c + 5 : c) % 10, f = d % 6, g = f < 4 && e > 0 && e < 6 && 3 != e || f > 0 && f < 3 && e < 7 || e > 1 && e < 5 && f > 2 && f < 5 || 3 == e && 5 == f; | |
| break; | |
| case 13: | |
| g = !(!((c + d) % 10 < 1 || mod(c - d, 10) < 1 || (c + 1) % 10 < 3 && (d + 1) % 10 < 3 || (c + 6) % 10 < 3 && (d + 6) % 10 < 3) || c % 10 === 0 && d % 10 === 0 || c % 10 == 5 && d % 10 == 5); | |
| break; | |
| case 14: | |
| e = (d % 10 < 5 ? c + 5 : c) % 10, f = d % 5, g = (1 == e || 4 == e) && f > 1 && f < 4 || (1 == f || 4 == f) && e > 1 && e < 4; | |
| break; | |
| case 15: | |
| g = (c + d) % 6 < 1 || mod(c - d, 6) < 1 && c % 6 < 3; | |
| break; | |
| case 16: | |
| e = c % 6, f = d % 6, g = 1 == e && f > 2 && f < 5 || 4 == e && f > 0 && f < 3 || 4 == f && e > 2 && e < 5 || 1 == f && e > 0 && e < 3; | |
| break; | |
| case 17: | |
| g = Math.random() > .99; | |
| break; | |
| case 18: | |
| case 19: | |
| case 20: | |
| case 21: | |
| case 22: | |
| case 23: | |
| case 24: | |
| case 25: | |
| case 26: | |
| case 27: | |
| var h, i, j, k = 0, | |
| l = 0; | |
| switch(b) { | |
| case 18: | |
| i = 18, j = 18, l = 6, h = [ | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0], | |
| [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], | |
| [0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0], | |
| [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0], | |
| [1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0], | |
| [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0], | |
| [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0], | |
| [1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0], | |
| [1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0], | |
| [1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0], | |
| [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0], | |
| [1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], | |
| [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0], | |
| [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], | |
| [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0] | |
| ]; | |
| break; | |
| case 19: | |
| i = 14, j = 10, k = 7, l = 0, h = [ | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], | |
| [0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0], | |
| [0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0], | |
| [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |
| ]; | |
| break; | |
| case 20: | |
| i = 12, j = 7, k = 6, l = 0, h = [ | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0], | |
| [0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1], | |
| [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0], | |
| [0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1], | |
| [0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1], | |
| [0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0] | |
| ]; | |
| break; | |
| case 21: | |
| i = 17, j = 15, k = 0, l = 5, h = [ | |
| [1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1], | |
| [1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1], | |
| [0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1], | |
| [0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1], | |
| [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], | |
| [1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1], | |
| [1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1], | |
| [1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1], | |
| [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], | |
| [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], | |
| [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], | |
| [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], | |
| [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], | |
| [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], | |
| [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
| ]; | |
| break; | |
| case 22: | |
| i = 10, j = 10, k = 0, l = 0, h = [ | |
| [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [1, 0, 1, 1, 1, 1, 1, 1, 1, 0], | |
| [1, 0, 0, 1, 0, 1, 0, 1, 0, 0], | |
| [1, 0, 1, 0, 0, 1, 0, 0, 1, 0], | |
| [1, 1, 1, 1, 0, 1, 0, 1, 1, 1], | |
| [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], | |
| [1, 1, 1, 1, 0, 1, 0, 1, 1, 1], | |
| [1, 0, 1, 0, 0, 1, 0, 0, 1, 0], | |
| [1, 0, 0, 1, 0, 1, 0, 1, 0, 0], | |
| [1, 0, 1, 1, 1, 1, 1, 1, 1, 0] | |
| ]; | |
| break; | |
| case 23: | |
| i = 12, j = 7, k = 6, l = 0, h = [ | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1], | |
| [0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1], | |
| [0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1], | |
| [0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1], | |
| [0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1], | |
| [0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1] | |
| ]; | |
| break; | |
| case 24: | |
| i = 14, j = 13, k = 7, l = 0, h = [ | |
| [1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1], | |
| [1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1], | |
| [1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1], | |
| [1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1], | |
| [1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0], | |
| [1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0], | |
| [1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0], | |
| [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], | |
| [1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0], | |
| [1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], | |
| [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1], | |
| [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], | |
| [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1] | |
| ]; | |
| break; | |
| case 25: | |
| i = 22, j = 7, k = 11, l = 0, h = [ | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0], | |
| [0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0], | |
| [0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0], | |
| [0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0], | |
| [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0], | |
| [0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0] | |
| ]; | |
| break; | |
| case 26: | |
| i = 15, j = 19, k = 0, l = 6, h = [ | |
| [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], | |
| [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], | |
| [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | |
| [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], | |
| [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], | |
| [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |
| ]; | |
| break; | |
| case 27: | |
| i = 10, j = 10, k = 0, l = 5, h = [ | |
| [0, 1, 1, 1, 1, 1, 0, 0, 0, 0], | |
| [1, 1, 0, 0, 0, 1, 1, 0, 0, 0], | |
| [1, 0, 1, 1, 1, 0, 1, 1, 0, 0], | |
| [1, 0, 1, 1, 1, 1, 0, 1, 0, 0], | |
| [1, 0, 1, 1, 1, 1, 0, 1, 0, 0], | |
| [1, 0, 1, 1, 1, 0, 1, 1, 0, 0], | |
| [1, 0, 1, 0, 0, 1, 1, 0, 0, 0], | |
| [1, 0, 1, 1, 1, 1, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |
| ] | |
| } | |
| k *= Math.floor(d / j), l *= Math.floor(c / i), e = (c + k) % i, f = (d + l) % j, g = 1 == h[f][e] | |
| } | |
| return g && (a += SKIN_BLOCK_COUNT), a | |
| } | |
| function doTopNotification(a) { | |
| var b = { | |
| text: a, | |
| elem: null, | |
| initiate: function() { | |
| var a = document.createElement("div"); | |
| this.elem = a, a.innerHTML = this.text, a.className = "topNotification greenBox", a.style.visibility = "hidden", document.getElementById("topNotifications").appendChild(a); | |
| var b = getColorForBlockSkinId(myColorId), | |
| c = b.brighter, | |
| d = b.darker; | |
| colorBox(a, c, d) | |
| }, | |
| animationTimer: 0, | |
| animationDirection: 1, | |
| update: function(a) { | |
| this.animationTimer += .001 * a * this.animationDirection; | |
| var b = -this.elem.offsetHeight - 10, | |
| c = lerp(b, 10, ease.out(clamp01(this.animationTimer))); | |
| this.elem.style.top = c + "px", this.elem.style.visibility = null, this.animationDirection == -1 && this.animationTimer < 0 && this.destroy() | |
| }, | |
| animateOut: function() { | |
| this.animationDirection = -1, this.animationTimer > 1 && (this.animationTimer = 1) | |
| }, | |
| destroy: function() { | |
| this.elem.parentElement.removeChild(this.elem); | |
| for(var a = currentTopNotifications.length - 1; a >= 0; a--) { | |
| var b = currentTopNotifications[a]; | |
| b == this && currentTopNotifications.splice(a, 1) | |
| } | |
| } | |
| }; | |
| return b.initiate(), currentTopNotifications.push(b), b | |
| } | |
| function bindSwipeEvents() { | |
| touchControlsElem.addEventListener("touchstart", onTouchStart), touchControlsElem.addEventListener("touchmove", onTouchMove), touchControlsElem.addEventListener("touchend", onTouchEnd), touchControlsElem.addEventListener("touchcancel", onTouchEnd) | |
| } | |
| function onTouchStart(a) { | |
| var b = a.touches[a.touches.length - 1]; | |
| currentTouches.push({ | |
| prevPos: [b.pageX, b.pageY], | |
| prevTime: Date.now(), | |
| id: b.identifier | |
| }) | |
| } | |
| function onTouchMove(a) { | |
| for(var b = a.touches, c = 0; c < b.length; c++) { | |
| for(var d = b[c], e = null, f = 0; f < currentTouches.length; f++) | |
| if(currentTouches[f].id == d.identifier) { | |
| e = currentTouches[f]; | |
| break | |
| } | |
| e && calcTouch(e, d) | |
| } | |
| a.preventDefault() | |
| } | |
| function calcTouch(a, b) { | |
| var c = Date.now(), | |
| d = c - a.prevTime, | |
| e = [b.pageX, b.pageY], | |
| f = a.prevPos, | |
| g = f[0] - e[0], | |
| h = f[1] - e[1], | |
| i = Math.sqrt(Math.pow(g, 2) + Math.pow(h, 2)), | |
| j = i / d; | |
| j *= MAX_PIXEL_RATIO * canvasQuality, a.prevTime = c, a.prevPos = e, d > 0 && j > 2 && sendDir(Math.abs(g) > Math.abs(h) ? g > 0 ? 2 : 0 : h > 0 ? 3 : 1) | |
| } | |
| function onTouchEnd(a) { | |
| for(var b = currentTouches.length - 1; b >= 0; b--) | |
| for(var c = 0; c < a.touches.length; c++) currentTouches[b].id == a.touches[c].identifier && (calcTouch(currentTouches[b], a.touches[c]), currentTouches.splice(b, 1)) | |
| } | |
| function doTransition(a, b, c, d, e) { | |
| isTransitioning && !e || (transitionText = a, isTransitioning = !0, transitionDirection = 1, transitionTimer = transitionPrevTimer = 0, transitionCanvas.style.display = null, void 0 === b && (b = !1), transitionReverseOnHalf = b, transitionCallback1 = c, transitionCallback2 = d) | |
| } | |
| function doSkipDeathTransition() { | |
| allowSkipDeathTransition && (null !== deathTransitionTimeout && (window.clearTimeout(deathTransitionTimeout), deathTransitionTimeout = null, onClose(), doTransition("", !1, function() { | |
| window.setTimeout(afterDeath, 700), resetAll() | |
| })), skipDeathTransition = !0) | |
| } | |
| function rndSeed(a) { | |
| var b = 1e4 * Math.sin(a); | |
| return b - Math.floor(b) | |
| } | |
| function drawTitle(a, b, c, d, e) { | |
| a.strokeStyle = c ? colors.red.patternEdge : colors.red.brighter, a.lineWidth = 16, a.lineJoin = "round", a.lineCap = "round", e ? (a.shadowBlur = 40 * MAX_PIXEL_RATIO, a.shadowColor = "rgba(0,0,0,0.4)", a.shadowOffsetX = a.shadowOffsetY = 10 * MAX_PIXEL_RATIO) : a.shadowColor = "rgba(0,0,0,0)"; | |
| for(var f = titleTimer, g = 0; g < titleLines.length; g++) { | |
| var h = titleLines[g], | |
| i = clamp01(f * h.speed - h.offset), | |
| j = clamp01(f); | |
| j *= 5, void 0 !== d && (j = Math.min(j, d)), a.beginPath(); | |
| for(var k = 0; k < h.line.length; k++) { | |
| var l = h.line[k], | |
| m = clamp01(i * (h.line.length - 1) - k + 1); | |
| if(m > 0) | |
| if(1 == m) 0 === k && 2 == l.length ? a.moveTo(l[0] - j, l[1] - j) : 2 == l.length ? a.lineTo(l[0] - j, l[1] - j) : 6 == l.length && a.bezierCurveTo(l[0] - j, l[1] - j, l[2] - j, l[3] - j, l[4] - j, l[5] - j); | |
| else { | |
| var n = h.line[k - 1], | |
| o = [n[n.length - 2], n[n.length - 1]]; | |
| if(2 == l.length) a.lineTo(lerp(o[0], l[0], m) - j, lerp(o[1], l[1], m) - j); | |
| else if(6 == l.length) { | |
| var p = o, | |
| q = [l[0], l[1]], | |
| r = [l[2], l[3]], | |
| s = [l[4], l[5]], | |
| t = lerpA(p, q, m), | |
| u = lerpA(q, r, m), | |
| v = lerpA(r, s, m), | |
| w = lerpA(t, u, m), | |
| x = lerpA(u, v, m), | |
| y = lerpA(w, x, m); | |
| a.bezierCurveTo(t[0] - j, t[1] - j, w[0] - j, w[1] - j, y[0] - j, y[1] - j) | |
| } | |
| } | |
| } | |
| a.stroke() | |
| } | |
| } | |
| function drawBlocks(a, b, c) { | |
| for(var d, e = 0; e < b.length; e++) { | |
| var f = b[e]; | |
| if(c && (f.x < camPos[0] - VIEWPORT_RADIUS || f.x > camPos[0] + VIEWPORT_RADIUS || f.y < camPos[1] - VIEWPORT_RADIUS || f.y > camPos[1] + VIEWPORT_RADIUS)); | |
| else if(f.animDelay > 0 ? f.animDelay -= deltaTime : f.animProgress += deltaTime * f.animDirection * .003, f.animProgress > 1 && (f.animDirection = 0, f.animProgress = 1), f.animProgress < 0) f.currentBlock = f.nextBlock, f.animDirection = 1, f.animProgress = 0; | |
| else { | |
| var g = f.animProgress; | |
| if(0 === f.currentBlock && (a.fillStyle = colors.red.boundsDark, a.fillRect(10 * f.x, 10 * f.y, 10, 10), uglyMode || (linesCtx.fillStyle = colors.grey.diagonalLines, linesCtx.fillRect(10 * f.x, 10 * f.y, 10, 10))), 1 == f.currentBlock && (g > .8 && !uglyMode && (a.fillStyle = colors.grey.darker, a.fillRect(10 * f.x + 2, 10 * f.y + 2, 7, 7)), a.fillStyle = colors.grey.brighter, 1 == g || uglyMode ? a.fillRect(10 * f.x + 1, 10 * f.y + 1, 7, 7) : g < .4 ? (d = 2.5 * g, a.beginPath(), a.moveTo(10 * f.x + 2, 10 * f.y + lerp(9, 2, d)), a.lineTo(10 * f.x + 2, 10 * f.y + 9), a.lineTo(10 * f.x + lerp(2, 9, d), 10 * f.y + 9), a.fill()) : g < .8 ? (d = 2.5 * g - 1, a.beginPath(), a.moveTo(10 * f.x + 2, 10 * f.y + 2), a.lineTo(10 * f.x + 2, 10 * f.y + 9), a.lineTo(10 * f.x + 9, 10 * f.y + 9), a.lineTo(10 * f.x + 9, 10 * f.y + lerp(9, 2, d)), a.lineTo(10 * f.x + lerp(2, 9, d), 10 * f.y + 2), a.fill()) : (d = 5 * g - 4, a.fillRect(10 * f.x + lerp(2, 1, d), 10 * f.y + lerp(2, 1, d), 7, 7))), f.currentBlock >= 2) { | |
| var h = (f.currentBlock - 2) % SKIN_BLOCK_COUNT, | |
| i = getColorForBlockSkinId(h), | |
| j = f.currentBlock > SKIN_BLOCK_COUNT + 1, | |
| k = j ? i.pattern : i.brighter, | |
| l = j ? i.patternEdge : i.darker; | |
| g > .8 && !uglyMode && (a.fillStyle = l, a.fillRect(10 * f.x + 1, 10 * f.y + 1, 9, 9)), a.fillStyle = k, 1 == g || uglyMode ? (a.fillRect(10 * f.x, 10 * f.y, 9, 9), 12 != h || uglyMode || (a.fillStyle = colors.gold.bevelBright, a.fillRect(10 * f.x + 3, 10 * f.y + .1, 6, .1))) : g < .4 ? (d = 2.5 * g, a.beginPath(), a.moveTo(10 * f.x + 1, 10 * f.y + lerp(10, 1, d)), a.lineTo(10 * f.x + 1, 10 * f.y + 10), a.lineTo(10 * f.x + lerp(1, 10, d), 10 * f.y + 10), a.fill()) : g < .8 ? (d = 2.5 * g - 1, a.beginPath(), a.moveTo(10 * f.x + 1, 10 * f.y + 1), a.lineTo(10 * f.x + 1, 10 * f.y + 10), a.lineTo(10 * f.x + 10, 10 * f.y + 10), a.lineTo(10 * f.x + 10, 10 * f.y + lerp(10, 1, d)), a.lineTo(10 * f.x + lerp(1, 10, d), 10 * f.y + 1), a.fill()) : (d = 5 * g - 4, a.fillRect(10 * f.x + lerp(1, 0, d), 10 * f.y + lerp(1, 0, d), 9, 9)) | |
| } | |
| } | |
| } | |
| } | |
| function drawPlayer(a, b, c) { | |
| if(b.hasReceivedPosition) { | |
| var d, e, f = getColorForBlockSkinId(b.skinBlock); | |
| if(b.trails.length > 0) | |
| for(var g = b.trails.length - 1; g >= 0; g--) { | |
| var h = b.trails[g], | |
| i = g == b.trails.length - 1; | |
| if(!i || b.isDead) { | |
| if(uglyMode) h.vanishTimer = 10; | |
| else { | |
| var j = b.isDead && i ? .006 : .02; | |
| h.vanishTimer += deltaTime * j | |
| }!i && h.vanishTimer > 10 && b.trails.splice(g, 1) | |
| } | |
| if(h.trail.length > 0) { | |
| var k = i ? b.drawPos : null; | |
| h.vanishTimer > 0 && !uglyMode ? (ctxApplyCamTransform(tempCtx, !0), drawTrailOnCtx([{ | |
| ctx: tempCtx, | |
| color: f.darker, | |
| offset: 5 | |
| }, { | |
| ctx: tempCtx, | |
| color: f.brighter, | |
| offset: 4 | |
| }], h.trail, k), tempCtx.globalCompositeOperation = "destination-out", drawDiagonalLines(tempCtx, "white", h.vanishTimer, 10, .003 * c), a.restore(), tempCtx.restore(), linesCtx.restore(), a.drawImage(tempCanvas, 0, 0), tempCtx.fillStyle = colors.grey.diagonalLines, tempCtx.globalCompositeOperation = "source-in", tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height), linesCtx.drawImage(tempCanvas, 0, 0), ctxApplyCamTransform(a), ctxApplyCamTransform(linesCtx)) : h.vanishTimer < 10 && (uglyMode ? drawTrailOnCtx([{ | |
| ctx: a, | |
| color: f.darker, | |
| offset: 5 | |
| }, { | |
| ctx: a, | |
| color: f.brighter, | |
| offset: 4 | |
| }], h.trail, k) : drawTrailOnCtx([{ | |
| ctx: a, | |
| color: f.darker, | |
| offset: 5 | |
| }, { | |
| ctx: a, | |
| color: f.brighter, | |
| offset: 4 | |
| }, { | |
| ctx: linesCtx, | |
| color: colors.grey.diagonalLines, | |
| offset: 4 | |
| }], h.trail, k)) | |
| } | |
| } | |
| var l = [10 * b.drawPos[0] + 4.5, 10 * b.drawPos[1] + 4.5], | |
| m = 6, | |
| n = .3, | |
| o = a.createRadialGradient(l[0] - 3, l[1] - 3, 0, l[0], l[1], m); | |
| if(o.addColorStop(0, f.slightlyBrighter), o.addColorStop(1, f.brighter), linesCtx.fillStyle = "white", b.isDead) { | |
| b.isDeadTimer += .003 * deltaTime, a.fillStyle = o; | |
| for(var p = 0; p < b.deadAnimParts.length - 1; p++) { | |
| var q = b.deadAnimParts[p], | |
| r = b.deadAnimParts[p + 1], | |
| s = lerp(q, r, .5), | |
| t = b.dir * Math.PI / 2 - Math.PI, | |
| u = Math.min(Math.abs(t - s), Math.abs(t - 2 * Math.PI - s), Math.abs(t + 2 * Math.PI - s)), | |
| v = b.deadAnimPartsRandDist[p], | |
| x = (1 - Math.pow(2, -2 * b.isDeadTimer)) * u * 5 * (v + 1), | |
| y = [Math.cos(s) * x, Math.sin(s) * x]; | |
| a.globalAlpha = linesCtx.globalAlpha = Math.max(0, 1 - .2 * b.isDeadTimer), a.beginPath(), a.arc(l[0] - n + y[0], l[1] - n + y[1], m, q, r, !1), a.lineTo(l[0] - n + y[0], l[1] - n + y[1]), a.fill(), uglyMode || (linesCtx.beginPath(), linesCtx.arc(l[0] - n + y[0], l[1] - n + y[1], m, q, r, !1), linesCtx.lineTo(l[0] - n + y[0], l[1] - n + y[1]), linesCtx.fill()) | |
| } | |
| a.globalAlpha = linesCtx.globalAlpha = 1 | |
| } else a.fillStyle = f.darker, a.beginPath(), a.arc(l[0] + n, l[1] + n, m, 0, 2 * Math.PI, !1), a.fill(), a.fillStyle = o, a.beginPath(), a.arc(l[0] - n, l[1] - n, m, 0, 2 * Math.PI, !1), a.fill(), b.isMyPlayer && "true" == localStorage.drawWhiteDot && (a.fillStyle = "white", a.beginPath(), a.arc(l[0] - n, l[1] - n, 1, 0, 2 * Math.PI, !1), a.fill()), uglyMode || (linesCtx.beginPath(), linesCtx.arc(l[0] + n, l[1] + n, m, 0, 2 * Math.PI, !1), linesCtx.fill(), linesCtx.beginPath(), linesCtx.arc(l[0] - n, l[1] - n, m, 0, 2 * Math.PI, !1), linesCtx.fill()); | |
| if(b.isMyPlayer && "true" == localStorage.drawActualPlayerPos && (a.fillStyle = "#FF0000", a.beginPath(), a.arc(10 * b.serverPos[0] + 5, 10 * b.serverPos[1] + 5, m, 0, 2 * Math.PI, !1), a.fill()), b.hitLines.length > 0) | |
| for(var z = b.hitLines.length - 1; z >= 0; z--) { | |
| var A = b.hitLines[z]; | |
| A.vanishTimer += .004 * deltaTime; | |
| var B = A.vanishTimer; | |
| if(B > 4 && b.hitLines.splice(z, 1), d = 10 * A.pos[0] + 5, e = 10 * A.pos[1] + 5, B < 2) { | |
| var C = Math.max(0, 18 * ease.out(iLerp(0, 2, B))), | |
| D = Math.max(0, 18 * ease.out(iLerp(.5, 2, B))); | |
| a.fillStyle = f.brighter, a.beginPath(), a.arc(d, e, C, 0, 2 * Math.PI, !1), a.arc(d, e, D, 0, 2 * Math.PI, !1), a.fill("evenodd"), uglyMode || (linesCtx.beginPath(), linesCtx.arc(d, e, C, 0, 2 * Math.PI, !1), linesCtx.arc(d, e, D, 0, 2 * Math.PI, !1), linesCtx.fill("evenodd")) | |
| } | |
| if(void 0 !== A.color && b.isMyPlayer) { | |
| a.save(), a.font = linesCtx.font = "6px Arial, Helvetica, sans-serif", a.fillStyle = A.color.brighter, a.shadowColor = A.color.darker, a.shadowOffsetX = a.shadowOffsetY = .4 * MAX_PIXEL_RATIO * zoom * canvasQuality, w = a.measureText("+500").width; | |
| var E, F; | |
| F = B < .5 ? iLerp(0, .5, B) : B < 3.5 ? 1 : iLerp(4, 3.5, B), F = clamp01(F), E = B < 2 ? 20 * ease.out(B / 2) : 20, a.globalAlpha = F, a.fillText("+500", d - w / 2, e - E), a.restore() | |
| } | |
| } | |
| if(b.honkTimer < b.honkMaxTime && (b.honkTimer += .255 * deltaTime, a.fillStyle = f.brighter, a.globalAlpha = clamp01(iLerp(b.honkMaxTime, 0, b.honkTimer)), a.beginPath(), a.arc(10 * b.drawPos[0] + 4.5 + n, 10 * b.drawPos[1] + 4.5 + n, m + .1 * b.honkTimer, 0, 2 * Math.PI, !1), a.fill(), a.globalAlpha = 1, uglyMode || (linesCtx.globalAlpha = clamp01(iLerp(b.honkMaxTime, 0, b.honkTimer)), linesCtx.beginPath(), linesCtx.arc(10 * b.drawPos[0] + 4.5 + n, 10 * b.drawPos[1] + 4.5 + n, m + .1 * b.honkTimer, 0, 2 * Math.PI, !1), linesCtx.fill(), linesCtx.globalAlpha = 1)), "true" != localStorage.hidePlayerNames && (myNameAlphaTimer += .001 * deltaTime, a.font = linesCtx.font = USERNAME_SIZE + "px Arial, Helvetica, sans-serif", b.name)) { | |
| var G = 1, | |
| H = 1; | |
| b.isMyPlayer && (H = 9 - myNameAlphaTimer), b.isDead && (G = 1 - b.isDeadTimer); | |
| var I = Math.min(G, H); | |
| if(I > 0) { | |
| a.save(), uglyMode || linesCtx.save(), a.globalAlpha = clamp01(I); | |
| var J = a.measureText(b.name).width; | |
| J = Math.min(100, J), d = 10 * b.drawPos[0] + 5 - J / 2, e = 10 * b.drawPos[1] - 5, a.rect(d - 4, e - 1.2 * USERNAME_SIZE, J + 8, 2 * USERNAME_SIZE), a.clip(), uglyMode || (linesCtx.rect(d - 4, e - 1.2 * USERNAME_SIZE, J + 8, 2 * USERNAME_SIZE), linesCtx.clip(), linesCtx.fillText(b.name, d, e)), a.shadowColor = "rgba(0,0,0,0.9)", a.shadowBlur = 10, a.shadowOffsetX = a.shadowOffsetY = 2, a.fillStyle = f.brighter, a.fillText(b.name, d, e), a.shadowColor = f.darker, a.shadowBlur = 0, a.shadowOffsetX = a.shadowOffsetY = .8, a.fillText(b.name, d, e), a.restore(), uglyMode || linesCtx.restore() | |
| } | |
| } | |
| } | |
| } | |
| function moveDrawPosToPos(a) { | |
| var b = null; | |
| b = a.isDead && !a.deathWasCertain ? a.uncertainDeathPosition : a.pos, a.drawPos[0] = lerpt(a.drawPos[0], b[0], .23), a.drawPos[1] = lerpt(a.drawPos[1], b[1], .23) | |
| } | |
| function movePos(a, b, c) { | |
| switch(b) { | |
| case 0: | |
| a[0] += c; | |
| break; | |
| case 1: | |
| a[1] += c; | |
| break; | |
| case 2: | |
| a[0] -= c; | |
| break; | |
| case 3: | |
| a[1] -= c | |
| } | |
| } | |
| function getDtCap(a) { | |
| return dtCaps[clamp(a, 0, dtCaps.length - 1)] | |
| } | |
| function toggleQuality() { | |
| switch(localStorage.quality) { | |
| case "auto": | |
| lsSet("quality", "0.4"); | |
| break; | |
| case "0.4": | |
| lsSet("quality", "0.7"); | |
| break; | |
| case "0.7": | |
| lsSet("quality", "1"); | |
| break; | |
| case "1": | |
| lsSet("quality", "auto") | |
| } | |
| setQuality() | |
| } | |
| function setQuality() { | |
| null === localStorage.getItem("quality") && lsSet("quality", "1"), "auto" != localStorage.quality ? (canvasQuality = parseFloat(localStorage.quality), qualityText.innerHTML = "Quality: " + { | |
| .4: "low", | |
| .7: "medium", | |
| 1: "high" | |
| }[localStorage.quality]) : qualityText.innerHTML = "Quality: auto" | |
| } | |
| function loop(a) { | |
| var b, c, d, e, f = a - prevTimeStamp; | |
| if(lerpedDeltaTime = f > lerpedDeltaTime ? f : lerpt(lerpedDeltaTime, f, .05), "auto" != localStorage.quality && null !== localStorage.getItem("quality") || (lerpedDeltaTime > 33 ? canvasQuality -= .01 : lerpedDeltaTime < 28 && (canvasQuality += .01), canvasQuality = Math.min(1, Math.max(.4, canvasQuality))), f < lerp(getDtCap(currentDtCap), getDtCap(currentDtCap - 1), .9)) | |
| for(gainedFrames.push(Date.now()); gainedFrames.length > 190;) { | |
| if(!(Date.now() - gainedFrames[0] > 1e4)) { | |
| currentDtCap--, gainedFrames = [], currentDtCap = clamp(currentDtCap, 0, dtCaps.length - 1); | |
| break | |
| } | |
| gainedFrames.splice(0, 1) | |
| } | |
| if(f > lerp(getDtCap(currentDtCap), getDtCap(currentDtCap + 1), .05)) | |
| for(missedFrames.push(Date.now()), gainedFrames = []; missedFrames.length > 5;) { | |
| if(!(Date.now() - missedFrames[0] > 5e3)) { | |
| currentDtCap++, missedFrames = [], currentDtCap = clamp(currentDtCap, 0, dtCaps.length - 1); | |
| break | |
| } | |
| missedFrames.splice(0, 1) | |
| } | |
| if(deltaTime = f + totalDeltaTimeFromCap, prevTimeStamp = a, deltaTime < getDtCap(currentDtCap) && "true" != localStorage.dontCapFps) totalDeltaTimeFromCap += f; | |
| else { | |
| totalDeltaTimeFromCap = 0, uglyMode = "true" == localStorage.uglyMode, canvasTransformType = canvasTransformTypes.MAIN, ctxCanvasSize(ctx), uglyMode || ctxCanvasSize(linesCtx), ctx.fillStyle = colors.grey.BG, ctx.fillRect(0, 0, mainCanvas.width, mainCanvas.height), uglyMode || (linesCtx.fillStyle = "white", linesCtx.fillRect(0, 0, linesCanvas.width, linesCanvas.height)), camPosPrevFrame = [camPos[0], camPos[1]], calcCamOffset(), ctxApplyCamTransform(ctx), uglyMode || ctxApplyCamTransform(linesCtx), drawBlocks(ctx, blocks, !0); | |
| for(var g = deltaTime * GLOBAL_SPEED, h = 0; h < players.length; h++) { | |
| var i = players[h]; | |
| if(!i.isDead || !i.deathWasCertain) { | |
| if(i.moveRelativeToServerPosNextFrame && (g = (Date.now() - i.lastServerPosSentTime) * GLOBAL_SPEED), i.isMyPlayer && (movePos(i.serverPos, i.serverDir, g), i.serverDir == i.dir)) { | |
| var j = 0; | |
| "true" != localStorage.dontSlowPlayersDown && (0 === i.dir || 2 == i.dir ? i.pos.y == i.serverPos.y && (j = 0 === i.dir ? i.pos[0] - i.serverPos[0] : i.serverPos[0] - i.pos[0]) : i.pos.x == i.serverPos.x && (j = 1 == i.dir ? i.pos[1] - i.serverPos[1] : i.serverPos[1] - i.pos[1])), j = Math.max(0, j), g *= lerp(.5, 1, iLerp(5, 0, j)) | |
| } | |
| movePos(i.pos, i.dir, g) | |
| } | |
| i.moveRelativeToServerPosNextFrame = !1, moveDrawPosToPos(i); | |
| var k = !1; | |
| if(i.drawPos[0] <= 0 || i.drawPos[1] <= 0 || i.drawPos[0] >= mapSize - 1 || i.drawPos[1] >= mapSize - 1) k = !0; | |
| else if(i.trails.length > 0) { | |
| c = i.trails[i.trails.length - 1].trail; | |
| var l = [Math.round(i.drawPos[0]), Math.round(i.drawPos[1])]; | |
| if(Math.abs(l[0] - i.drawPos[0]) < .2 && Math.abs(l[1] - i.drawPos[1]) < .2) { | |
| var m = !0; | |
| for(b = c.length - 3; b >= 0; b--) { | |
| var n = [Math.round(c[b][0]), Math.round(c[b][1])], | |
| o = [Math.round(c[b + 1][0]), Math.round(c[b + 1][1])], | |
| p = orderTwoPos(n, o); | |
| l[0] >= p[0][0] && l[0] <= p[1][0] && l[1] >= p[0][1] && l[1] <= p[1][1] ? (m || (k = !0), m = !0) : m = !1 | |
| } | |
| } | |
| } | |
| if(k ? i.isDead || i.die() : i.didUncertainDeathLastTick = !1, i.isDead && !i.deathWasCertain && i.isDeadTimer > 1.5 && (i.isDead = !1, i.trails.length > 0 && (c = i.trails[i.trails.length - 1], c.vanishTimer = 0)), i.isMyPlayer && (myPos = [i.pos[0], i.pos[1]], miniMapPlayer.style.left = myPos[0] / mapSize * 160 + 1.5 + "px", miniMapPlayer.style.top = myPos[1] / mapSize * 160 + 1.5 + "px", camPosSet ? (camPos[0] = lerpt(camPos[0], i.pos[0], .03), camPos[1] = lerpt(camPos[1], i.pos[1], .03)) : (camPos = [i.pos[0], i.pos[1]], camPosSet = !0), myNextDir != i.dir)) { | |
| var q = 0 === i.dir || 2 == i.dir; | |
| if(changeDirAtIsHorizontal != q) { | |
| var r = !1, | |
| s = i.pos[q ? 0 : 1]; | |
| if(0 === i.dir || 1 == i.dir ? changeDirAt < s && (r = !0) : changeDirAt > s && (r = !0), r) { | |
| var t = [i.pos[0], i.pos[1]], | |
| u = Math.abs(changeDirAt - s); | |
| t[q ? 0 : 1] = changeDirAt, changeMyDir(myNextDir, t), movePos(i.pos, i.dir, u) | |
| } | |
| } | |
| } | |
| drawPlayer(ctx, i, a) | |
| } | |
| if(sendDirQueue.length > 0) { | |
| var v = sendDirQueue[0]; | |
| (Date.now() - v.addTime > 1.2 / GLOBAL_SPEED || sendDir(v.dir, !0)) && sendDirQueue.shift() | |
| } | |
| if(uglyMode || drawDiagonalLines(linesCtx, "white", 5, 10, .008 * a), ctx.restore(), uglyMode || (linesCtx.restore(), ctx.globalCompositeOperation = "multiply", ctx.drawImage(linesCanvas, 0, 0), ctx.globalCompositeOperation = "source-over"), scoreStat = lerpt(scoreStat, scoreStatTarget, .1), myScoreElem.innerHTML = Math.round(scoreStat), realScoreStat = lerpt(realScoreStat, realScoreStatTarget, .1), myRealScoreElem.innerHTML = Math.round(realScoreStat), isTransitioning) { | |
| var w = 10, | |
| x = 60, | |
| y = 2, | |
| z = 10, | |
| A = 5; | |
| if(x *= MAX_PIXEL_RATIO, A *= MAX_PIXEL_RATIO, transitionTimer += deltaTime * transitionDirection * .001, 1 == transitionDirection && null !== transitionCallback1 && transitionTimer >= .5 && transitionPrevTimer < .5 && (transitionTimer = .5, transitionCallback1()), transitionDirection == -1 && null !== transitionCallback2 && transitionTimer <= .5 && transitionPrevTimer > .5 && (transitionTimer = .5, transitionCallback2()), transitionReverseOnHalf && 1 == transitionDirection && transitionTimer >= 1 + y && transitionPrevTimer < 1 + y && (transitionDirection = -1, transitionTimer = 1), transitionPrevTimer = transitionTimer, transitionTimer <= 0 && transitionReverseOnHalf || transitionTimer >= y + 1.5 && !transitionReverseOnHalf) transitionDirection = 0, isTransitioning = !1, transitionCanvas.style.display = "none"; | |
| else { | |
| ctxCanvasSize(tCtx, !0); | |
| var B = transitionCanvas.width, | |
| C = transitionCanvas.height; | |
| if(d = transitionTimer, d < .5 ? (e = 2 * d, e = ease.in(e), tCtx.fillStyle = colors.green2.darker, tCtx.fillRect(0, lerp(-w, C / 2, e), B, w), tCtx.fillStyle = colors.green2.brighter, tCtx.fillRect(0, -w, B, lerp(0, C / 2 + w, e)), tCtx.fillRect(0, lerp(C, C / 2, e), B, C)) : d < 1 ? (e = 2 * d - 1, e = ease.out(e), transitionText ? (tCtx.fillStyle = colors.green2.darker, tCtx.fillRect(0, lerp(0, C / 2 - x / 2, e), B, lerp(C, x + w, e)), tCtx.fillStyle = colors.green2.brighter, tCtx.fillRect(0, lerp(0, C / 2 - x / 2, e), B, lerp(C, x, e))) : (tCtx.fillStyle = colors.green2.darker, tCtx.fillRect(0, lerp(0, C / 2, e), B, lerp(C, w, e)), tCtx.fillStyle = colors.green2.brighter, tCtx.fillRect(0, lerp(0, C / 2, e), B, lerp(C, 0, e)))) : d < 1 + y ? transitionText ? (tCtx.fillStyle = colors.green2.darker, tCtx.fillRect(0, C / 2, B, x / 2 + w), tCtx.fillStyle = colors.green2.brighter, tCtx.fillRect(0, C / 2 - x / 2, B, x)) : transitionTimer = y + 1.5 : d < y + 1.5 && (e = 2 * (d - y - 1), e = ease.in(e), tCtx.fillStyle = colors.green2.darker, tCtx.fillRect(0, C / 2, B, lerp(x / 2 + w, w, e)), tCtx.fillStyle = colors.green2.brighter, tCtx.fillRect(0, lerp(C / 2 - x / 2, C / 2, e), B, lerp(x, 0, e))), d > .5 && d < 3.5) { | |
| var D = x - 2 * z; | |
| tCtx.font = D + "px Arial, Helvetica, sans-serif"; | |
| var E = tCtx.measureText(transitionText).width, | |
| F = B / 2 - E / 2 + A / 2, | |
| G = C / 2 + .37 * D + A / 2; | |
| e = d, e = d < 1.1 ? iLerp(.5, 1.1, d) : d < 2.9 ? 1 : iLerp(3.5, 2.9, d), drawAnimatedText(tCtx, transitionText, e, F, G, D, "white", "Arial, Helvetica, sans-serif", A, 3, 16842438) | |
| } | |
| tCtx.restore() | |
| } | |
| skipDeathTransition && "GAME OVER" == transitionText && transitionTimer > 1 && (transitionTimer = 1.1, transitionDirection = -1, allowSkipDeathTransition = !1, skipDeathTransition = !1) | |
| } | |
| renderAllLives(deltaTime); | |
| for(var H = currentTopNotifications.length - 1; H >= 0; H--) { | |
| var I = currentTopNotifications[H]; | |
| I.update(deltaTime) | |
| } | |
| if(engagementSetIsPlaying(playingAndReady && Date.now() - lastSendDirTime < 2e4), beginScreenVisible && a - titleLastRender > 49 && (resetTitleNextFrame && (resetTitleNextFrame = !1, titleTimer = -1, titleLastRender = a), titleTimer += .002 * (a - titleLastRender), titleLastRender = a, canvasTransformType = canvasTransformTypes.TITLE, ctxCanvasSize(titCtx, !0), ctxApplyCamTransform(titCtx, !1, !0), drawTitle(titCtx, titleTimer, !0, 0, !0), drawTitle(titCtx, titleTimer, !0, 2.5), drawTitle(titCtx, titleTimer), titCtx.restore()), beginScreenVisible) { | |
| tutorialTimer += deltaTime * GLOBAL_SPEED * .7, canvasTransformType = canvasTransformTypes.TUTORIAL, ctxCanvasSize(tutCtx), uglyMode || ctxCanvasSize(linesCtx), tutCtx.fillStyle = colors.grey.BG, tutCtx.fillRect(0, 0, tutorialCanvas.width, tutorialCanvas.height), uglyMode || (linesCtx.fillStyle = "white", linesCtx.fillRect(0, 0, linesCanvas.width, linesCanvas.height)), ctxApplyCamTransform(tutCtx), uglyMode || ctxApplyCamTransform(linesCtx), d = tutorialTimer, drawBlocks(tutCtx, tutorialBlocks); | |
| var J = getPlayer(1, tutorialPlayers), | |
| K = getPlayer(2, tutorialPlayers); | |
| d < 10 ? J.pos = [2, 2] : d < 15 ? J.pos = [d - 8, 2] : d < 18 ? J.pos = [7, d - 13] : d < 23 ? J.pos = [25 - d, 5] : d < 26 ? J.pos = [2, 28 - d] : d < 30 || (d < 36 ? J.pos = [2, d - 28] : d < 39 && (J.pos = [d - 34, 8])), d < 12 || (d < 15 ? J.trails = [{ | |
| trail: [ | |
| [4, 2] | |
| ], | |
| vanishTimer: 0 | |
| }] : d < 18 ? J.trails = [{ | |
| trail: [ | |
| [4, 2], | |
| [7, 2] | |
| ], | |
| vanishTimer: 0 | |
| }] : d < 23 ? J.trails = [{ | |
| trail: [ | |
| [4, 2], | |
| [7, 2], | |
| [7, 5] | |
| ], | |
| vanishTimer: 0 | |
| }] : d < 24 && (J.trails = [{ | |
| trail: [ | |
| [4, 2], | |
| [7, 2], | |
| [7, 5], | |
| [2, 5] | |
| ], | |
| vanishTimer: 0 | |
| }])), d > 24 && tutorialPrevTimer < 24 && (J.trails = [{ | |
| trail: [ | |
| [4, 2], | |
| [7, 2], | |
| [7, 5], | |
| [2, 5], | |
| [2, 4] | |
| ], | |
| vanishTimer: 0 | |
| }, { | |
| trail: [], | |
| vanishTimer: 0 | |
| }]), d < 34 || (d < 36 ? J.trails = [{ | |
| trail: [ | |
| [2, 6] | |
| ], | |
| vanishTimer: 0 | |
| }] : d < 39 && (J.trails = [{ | |
| trail: [ | |
| [2, 6], | |
| [2, 8] | |
| ], | |
| vanishTimer: 0 | |
| }])), d < 34 || d < 50 && (K.pos = [d - 37, 7], K.trails = [{ | |
| trail: [ | |
| [-2, 7] | |
| ], | |
| vanishTimer: 0 | |
| }]), d > 25 && tutorialPrevTimer < 25 && fillArea(2, 2, 6, 4, 10, 0, tutorialBlocks), d > 39 && tutorialPrevTimer < 39 && (J.die(!0), fillArea(1, 1, 7, 5, 1, 0, tutorialBlocks), K.addHitLine([2, 7])), d > 50 && (tutorialTimer = tutorialPrevTimer = 0, fillArea(1, 1, 3, 3, 10, 0, tutorialBlocks), J.isDeadTimer = 0, J.isDead = !1, J.trails = [], J.pos = [100, 100], K.trails = [{ | |
| trail: [ | |
| [-2, 7], | |
| [12, 7] | |
| ], | |
| vanishTimer: 0 | |
| }, { | |
| trail: [], | |
| vanishTimer: 0 | |
| }], K.pos = K.drawPos = [-2, 7]), d > 1 && tutorialPrevTimer < 1 && (tutorialText.innerHTML = "Close an area to fill it with your color."), d > 30 && tutorialPrevTimer < 30 && (tutorialText.innerHTML = "Don't get hit by other players."); | |
| var L = clamp01(5 - Math.abs(.5 * (d - 20))); | |
| L += clamp01(4 - Math.abs(.5 * (d - 40))), tutorialText.style.opacity = clamp(L, 0, .9), moveDrawPosToPos(J), moveDrawPosToPos(K), tutCtx.globalAlpha = Math.min(1, Math.max(0, .3 * d - 1)), drawPlayer(tutCtx, J, a), drawPlayer(tutCtx, K, a), tutCtx.globalAlpha = 1, tutorialPrevTimer = d, uglyMode || drawDiagonalLines(linesCtx, "white", 5, 10, .008 * a), tutCtx.restore(), uglyMode || (linesCtx.restore(), tutCtx.globalCompositeOperation = "multiply", tutCtx.drawImage(linesCanvas, 0, 0), tutCtx.globalCompositeOperation = "source-over") | |
| } | |
| if(beginScreenVisible && (canvasTransformType = canvasTransformTypes.SKIN_BUTTON, ctxApplyCamTransform(skinButtonCtx, !0, !0), drawBlocks(skinButtonCtx, skinButtonBlocks), skinButtonCtx.restore()), skinScreenVisible && (canvasTransformType = canvasTransformTypes.SKIN, ctxApplyCamTransform(skinCtx, !0), drawBlocks(skinCtx, skinScreenBlocks), skinCtx.restore()), beginScreenVisible && (socialOpacity = lerpt(socialOpacity, socialOTarget, .1), socialElem.style.opacity = Math.min(1, socialOpacity), animateAppLinks && (appLinksTimer += .003 * deltaTime, appLinksElem.style.opacity = Math.min(1, Math.max(0, appLinksTimer)), appLinksTimer > 1 && (animateAppLinks = !1))), beginScreenVisible) { | |
| if(lastStatTimer += deltaTime, d = lastStatTimer / 2e3, d > 1) { | |
| if(lastStatTimer = 0, lastStatCounter++, lastStatCounter > 5 && (lastStatCounter = 0), 0 === lastStatCounter && (lastStatNo1Time <= 0 && bestStatNo1Time <= 0 ? lastStatCounter++ : (lastStatValueElem.innerHTML = parseTimeToString(lastStatNo1Time) + " on #1", bestStatValueElem.innerHTML = parseTimeToString(bestStatNo1Time) + " on #1")), 1 == lastStatCounter && ("" === lastStatKiller && lastStatKiller.replace(/\s/g, "").length > 0 ? lastStatCounter++ : (lastStatValueElem.innerHTML = "killed by " + filter(htmlEscape(lastStatKiller)), bestStatValueElem.innerHTML = "")), 2 == lastStatCounter) | |
| if(lastStatKills <= 0 && bestStatKills <= 0) lastStatCounter++; | |
| else { | |
| var M = 1 == lastStatKills ? "" : "s"; | |
| lastStatValueElem.innerHTML = lastStatKills + " player" + M + " killed"; | |
| var N = 1 == bestStatKills ? "" : "s"; | |
| bestStatValueElem.innerHTML = bestStatKills + " player" + N + " killed" | |
| } | |
| if(3 == lastStatCounter && (lastStatValueElem.innerHTML = parseTimeToString(lastStatAlive) + " alive", bestStatValueElem.innerHTML = parseTimeToString(Math.max(lastStatAlive, localStorage.getItem("bestStatAlive"))) + " alive"), 4 == lastStatCounter) | |
| if(lastStatBlocks <= 0 && bestStatBlocks <= 0) lastStatCounter++; | |
| else { | |
| var O = 1 == lastStatBlocks ? "" : "s"; | |
| lastStatValueElem.innerHTML = lastStatBlocks + " block" + O + " captured"; | |
| var P = 1 == bestStatBlocks ? "" : "s"; | |
| bestStatValueElem.innerHTML = bestStatBlocks + " block" + P + " captured" | |
| } | |
| 5 == lastStatCounter && (lastStatLbRank <= 0 && bestStatLbRank <= 0 ? lastStatCounter = 0 : (lastStatValueElem.innerHTML = 0 == lastStatLbRank ? "" : "#" + lastStatLbRank + " highest rank", bestStatValueElem.innerHTML = 0 == bestStatLbRank ? "" : "#" + bestStatLbRank + " highest rank")) | |
| } | |
| var Q = 5; | |
| lastStatValueElem.style.opacity = bestStatValueElem.style.opacity = Q - Math.abs((d - .5) * Q * 2) | |
| } | |
| if(beginScreenVisible && Date.now() - lastNameChangeCheck > 1e3 && (lastNameValue != nameInput.value && (nameInputOnChange(), lastNameValue = nameInput.value), lastTeamNameValue != teamNameInput.value && (teamNameInputOnChange(), lastTeamNameValue = teamNameInput.value), lastNameChangeCheck = Date.now()), "true" == localStorage.drawDebug) { | |
| var R = Math.round(thisServerAvgPing), | |
| S = Math.round(thisServerLastPing), | |
| T = Math.round(thisServerDiffPing), | |
| U = "avg:" + R + " last:" + S + " diff:" + T; | |
| ctx.font = "14px Arial, Helvetica, sans-serif", ctx.fillStyle = colors.red.brighter; | |
| var V = ctx.measureText(U).width; | |
| ctx.fillText(U, ctx.canvas.width - V - 10, ctx.canvas.height - 10) | |
| } | |
| loopRetentionSamples(deltaTime) | |
| } | |
| donePing || pingServers(); | |
| var W = Date.now() - lastMyPosSetClientSideTime, | |
| X = Date.now() - lastMyPosSetValidClientSideTime, | |
| Y = Date.now() - lastMyPosServerSideTime; | |
| X > WAIT_FOR_DISCONNECTED_MS && Y - W > WAIT_FOR_DISCONNECTED_MS && !myPlayer.isDead ? connectionLostNotification || (connectionLostNotification = doTopNotification("It seems like you're disconnected. Please check your connection.")) : connectionLostNotification && (connectionLostNotification.animateOut(), connectionLostNotification = null); | |
| var Z = waitingForPing ? 1e4 : 5e3; | |
| null !== ws && Date.now() - lastPingTime > Z && (lastPingTime = Date.now(), wsSendMsg(sendAction.PING) && (waitingForPing = !0)), parseGamepads(), window.requestAnimationFrame(loop) | |
| } | |
| function getButton(a) { | |
| if(currentGamepad && currentGamepad.buttons) { | |
| var b = currentGamepad.buttons[currentMap.buttonMap[a]]; | |
| if(b) return b.pressed | |
| } | |
| return !1 | |
| } | |
| function getAxis(a) { | |
| if(currentGamepad && currentGamepad.axes) { | |
| var b = currentGamepad.axes[currentMap.axesMap[a]]; | |
| if(void 0 !== b) return b | |
| } | |
| return 0 | |
| } | |
| function parseGamepads() { | |
| if("getGamepads" in navigator) { | |
| for(var a = navigator.getGamepads(), b = !1, c = 0; c < a.length; c++) | |
| if(currentGamepad = a[c], void 0 !== currentGamepad && null !== currentGamepad) { | |
| var d = !1; | |
| if("standard" == currentGamepad.mapping) currentMap = { | |
| buttonMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 2, | |
| 3: 3, | |
| 4: 4, | |
| 5: 5, | |
| 6: 6, | |
| 7: 7, | |
| 8: 8, | |
| 9: 9, | |
| 10: 10, | |
| 11: 11, | |
| 12: 12, | |
| 13: 13, | |
| 14: 14, | |
| 15: 15 | |
| }, | |
| axesMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 2, | |
| 3: 3 | |
| } | |
| }, d = !0; | |
| else | |
| for(var e = 0; e < customMappings.length; e++) currentGamepad.id.indexOf(customMappings[e].name) >= 0 && (d = !0, currentMap = customMappings[e]); | |
| d && (getButton(12) && sendDir(3), getButton(13) && sendDir(1), getButton(14) && sendDir(2), getButton(15) && sendDir(0), getButton(0) && (b = !0), getButton(1) && doSkipDeathTransition(), (getAxis(0) < -.9 || getAxis(2) < -.9) && sendDir(2), (getAxis(0) > .9 || getAxis(2) > .9) && sendDir(0), (getAxis(1) < -.9 || getAxis(3) < -.9) && sendDir(3), (getAxis(1) > .9 || getAxis(3) > .9) && sendDir(1)) | |
| } | |
| b ? beginScreenVisible ? connectWithTransition() : gamePadIsHonking || (gamePadIsHonking = !0, honkStart()) : gamePadIsHonking && (gamePadIsHonking = !1, honkEnd()) | |
| } | |
| } | |
| function toUTF8Array(a) { | |
| for(var b = [], c = 0; c < a.length; c++) { | |
| var d = a.charCodeAt(c); | |
| d < 128 ? b.push(d) : d < 2048 ? b.push(192 | d >> 6, 128 | 63 & d) : d < 55296 || d >= 57344 ? b.push(224 | d >> 12, 128 | d >> 6 & 63, 128 | 63 & d) : (c++, d = 65536 + ((1023 & d) << 10 | 1023 & a.charCodeAt(c)), b.push(240 | d >> 18, 128 | d >> 12 & 63, 128 | d >> 6 & 63, 128 | 63 & d)) | |
| } | |
| return b | |
| } | |
| function htmlEscape(a) { | |
| return String(a).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">") | |
| } | |
| function filter(a) { | |
| for(var b = a.split(" "), c = 0; c < b.length; c++) { | |
| for(var d = b[c], e = d.toUpperCase() == d, f = 0; f < swearArr.length; f++) { | |
| var g = swearArr[f]; | |
| d.toLowerCase().indexOf(g) >= 0 && (d = d.length < g.length + 2 ? swearRepl : d.toLowerCase().replace(g, swearRepl)) | |
| } | |
| e && (d = d.toUpperCase()), b[c] = d | |
| } | |
| return b.join(" ") | |
| } | |
| function Utf8ArrayToStr(a) { | |
| var b, c, d, e, f, g; | |
| for(b = "", d = a.length, c = 0; c < d;) switch(e = a[c++], e >> 4) { | |
| case 0: | |
| case 1: | |
| case 2: | |
| case 3: | |
| case 4: | |
| case 5: | |
| case 6: | |
| case 7: | |
| b += String.fromCharCode(e); | |
| break; | |
| case 12: | |
| case 13: | |
| f = a[c++], b += String.fromCharCode((31 & e) << 6 | 63 & f); | |
| break; | |
| case 14: | |
| f = a[c++], g = a[c++], b += String.fromCharCode((15 & e) << 12 | (63 & f) << 6 | (63 & g) << 0) | |
| } | |
| return b | |
| } | |
| function bytesToInt() { | |
| for(var a = 0, b = 0, c = arguments.length - 1; c >= 0; c--) { | |
| var d = arguments[c]; | |
| a = (a | (255 & d) << b >>> 0) >>> 0, b += 8 | |
| } | |
| return a | |
| } | |
| function intToBytes(a, b) { | |
| for(var c = [], d = 0; d < b; d++) { | |
| var e = 255 & a; | |
| c[b - d - 1] = e, a = (a - e) / 256 | |
| } | |
| return c | |
| } | |
| function parseTimeToString(a) { | |
| var b = Math.floor(a / 3600), | |
| c = Math.floor((a - 3600 * b) / 60); | |
| if(a = a - 3600 * b - 60 * c, b <= 0) { | |
| var d = 1 == a ? "" : "s"; | |
| if(c <= 0) return a + " second" + d; | |
| var e = 1 == c ? "" : "s"; | |
| return c + " minute" + e + " and " + a + " second" + d | |
| } | |
| return b < 10 && (b = "0" + b), c < 10 && (c = "0" + c), a < 10 && (a = "0" + a), b + ":" + c + ":" + a | |
| } | |
| function parseQuery(a) { | |
| var b = a.indexOf("?"); | |
| if(b < 0) return {}; | |
| for(var c = a.substr(b + 1), d = c.split("&"), e = {}, f = 0; f < d.length; f++) { | |
| var g = d[f].split("="); | |
| 2 == g.length && (e[g[0]] = g[1]) | |
| } | |
| return e | |
| } | |
| var GLOBAL_SPEED = .006, | |
| VIEWPORT_RADIUS = 30, | |
| MAX_ZOOM = 430, | |
| BLOCKS_ON_SCREEN = 1100, | |
| WAIT_FOR_DISCONNECTED_MS = 1e3, | |
| USERNAME_SIZE = 6, | |
| COMPATIBLE_CLIENT_VERSION = 1, | |
| CLIENT_VERSION = 28, | |
| JS_VERSION = 80, | |
| IS_DEV_BUILD = !1; | |
| ! function() { | |
| for(var a = "x", b = document.getElementsByTagName("script"), c = 0; c < b.length; c++) { | |
| var d = b[c].src; | |
| d.indexOf("//splix.io/js/") > 0 && (a = d.substring(d.indexOf("splix.io/js/") + 12, d.length - 3)) | |
| } | |
| a = parseInt(a), isNaN(a) ? IS_DEV_BUILD = !0 : JS_VERSION = a | |
| }(); | |
| var MAX_PIXEL_RATIO = function() { | |
| var a = document.createElement("canvas").getContext("2d"), | |
| b = window.devicePixelRatio || 1, | |
| c = a.webkitBackingStorePixelRatio || a.mozBackingStorePixelRatio || a.msBackingStorePixelRatio || a.oBackingStorePixelRatio || a.backingStorePixelRatio || 1; | |
| return b / c | |
| }(), | |
| SKIN_BLOCK_COUNT = 13, | |
| SKIN_PATTERN_COUNT = 28, | |
| ws = null, | |
| mainCanvas, ctx, prevTimeStamp = null, | |
| blocks = [], | |
| players = [], | |
| camPos = [0, 0], | |
| camPosSet = !1, | |
| camPosPrevFrame = [0, 0], | |
| myNameAlphaTimer = 0, | |
| myPos = null, | |
| myPlayer = null, | |
| changeDirAt = null, | |
| changeDirAtIsHorizontal = !1, | |
| myNextDir = 0, | |
| lastChangedDirPos = null, | |
| lastClientsideMoves = [], | |
| trailPushesDuringRequest = [], | |
| isRequestingMyTrail = !1, | |
| skipTrailRequestResponse = !1, | |
| mapSize = 2e3, | |
| closedBecauseOfDeath = !1, | |
| minimapCtx, beginScreenVisible = !0, | |
| wsOnOpenTime, minimapCanvas, canvasQuality = 1, | |
| currentDtCap = 0, | |
| totalDeltaTimeFromCap = 0, | |
| deltaTime = 16.66, | |
| lerpedDeltaTime = 16.66, | |
| missedFrames = [], | |
| gainedFrames = [], | |
| myScoreElem, myKillsElem, myRealScoreElem, myRankElem, myRank = 0, | |
| myRankSent = !1, | |
| totalPlayersElem, totalPlayers = 0, | |
| leaderboardElem, miniMapPlayer, playUI, beginScreen, notificationElem, formElem, appLinksElem, nameInput, lastNameValue = "", | |
| lastTeamNameValue = "", | |
| lastNameChangeCheck = 0, | |
| scoreStatTarget = 25, | |
| scoreStat = 25, | |
| realScoreStatTarget = 25, | |
| realScoreStat = 25, | |
| linesCanvas, linesCtx, tempCanvas, tempCtx, showCouldntConnectAfterTransition = !1, | |
| playingAndReady = !1, | |
| canRunAds = !1, | |
| transitionCanvas, tCtx, transitionTimer = 0, | |
| transitionPrevTimer = 0, | |
| transitionDirection = 1, | |
| transitionText = "GAME OVER", | |
| isTransitioning = !1, | |
| transitionCallback1 = null, | |
| transitionCallback2 = null, | |
| transitionReverseOnHalf = !1, | |
| tutorialCanvas, tutCtx, tutorialTimer = 0, | |
| tutorialPrevTimer = 0, | |
| tutorialBlocks, tutorialPlayers, tutorialText, skinButtonCanvas, skinButtonCtx, skinButtonBlocks = [], | |
| skinButtonShadow, shareToUnlock, skinCanvas, skinCtx, skinScreen, skinScreenVisible = !1, | |
| skinScreenBlocks, shareTw, shareFb, titCanvas, titCtx, titleTimer = -1, | |
| resetTitleNextFrame = !0, | |
| titleLastRender = 0, | |
| currentTouches = [], | |
| doRefreshAfterDie = !1, | |
| pressedKeys = [], | |
| camPosOffset = [0, 0], | |
| camRotOffset = 0, | |
| camShakeForces = [], | |
| socialOpacity = 0, | |
| socialOTarget = 0, | |
| socialElem, socialIsReady = !1, | |
| socialHovering = !1, | |
| honkStartTime, lastHonkTime = 0, | |
| skipDeathTransition = !1, | |
| allowSkipDeathTransition = !1, | |
| deathTransitionTimeout = null, | |
| servers = [], | |
| donePing = !1, | |
| serversRequestDone = !1, | |
| doConnectAfterServersGet = !1, | |
| thisServerAvgPing = 0, | |
| thisServerDiffPing = 0, | |
| thisServerLastPing = 0, | |
| lastPingTime = 0, | |
| waitingForPing = !1, | |
| serversJsonGetTime = 0, | |
| closeNotification = null, | |
| connectionLostNotification = null, | |
| lastMyPosSetClientSideTime = 0, | |
| lastMyPosServerSideTime = 0, | |
| lastMyPosSetValidClientSideTime = 0, | |
| lastMyPosHasBeenConfirmed = !1, | |
| uiElems = [], | |
| zoom, myColorId, uglyMode = !1, | |
| hasReceivedChunkThisGame = !1, | |
| didSendSecondReady = !1, | |
| lastStatBlocks = 0, | |
| lastStatKills = 0, | |
| lastStatLbRank = 0, | |
| lastStatAlive = 0, | |
| lastStatNo1Time = 0, | |
| lastStatDeathType = 0, | |
| lastStatKiller = "", | |
| bestStatBlocks = 0, | |
| bestStatKills = 0, | |
| bestStatLbRank = 0, | |
| bestStatAlive = 0, | |
| bestStatNo1Time = 0, | |
| lastStatTimer = 0, | |
| lastStatCounter = 0, | |
| lastStatValueElem, bestStatValueElem, lastMousePos = [0, 0], | |
| mouseHidePos = [0, 0], | |
| joinButton, teamBox, teamBoxLoading, teamBoxLoaded, teamShareCopyBtn, gamemodeDropDownEl, teamPlayersList, preventTeamServerConnection = !1, | |
| teamNameH, teamNameInput, googletag = {}, | |
| adBox, receiveAction = { | |
| UPDATE_BLOCKS: 1, | |
| PLAYER_POS: 2, | |
| FILL_AREA: 3, | |
| SET_TRAIL: 4, | |
| PLAYER_DIE: 5, | |
| CHUNK_OF_BLOCKS: 6, | |
| REMOVE_PLAYER: 7, | |
| PLAYER_NAME: 8, | |
| MY_SCORE: 9, | |
| MY_RANK: 10, | |
| LEADERBOARD: 11, | |
| MAP_SIZE: 12, | |
| YOU_DED: 13, | |
| MINIMAP: 14, | |
| PLAYER_SKIN: 15, | |
| EMPTY_TRAIL_WITH_LAST_POS: 16, | |
| READY: 17, | |
| PLAYER_HIT_LINE: 18, | |
| REFRESH_AFTER_DIE: 19, | |
| PLAYER_HONK: 20, | |
| PONG: 21, | |
| UNDO_PLAYER_DIE: 22, | |
| TEAM_LIFE_COUNT: 23 | |
| }, | |
| sendAction = { | |
| UPDATE_DIR: 1, | |
| SET_USERNAME: 2, | |
| SKIN: 3, | |
| READY: 4, | |
| REQUEST_CLOSE: 5, | |
| HONK: 6, | |
| PING: 7, | |
| REQUEST_MY_TRAIL: 8, | |
| MY_TEAM_URL: 9, | |
| SET_TEAM_USERNAME: 10, | |
| VERSION: 11, | |
| PATREON_CODE: 12 | |
| }, | |
| teamSendAction = { | |
| REQUEST_TEAM_ID: 1, | |
| MY_USERNAME: 2, | |
| START_GAME: 3, | |
| PING_DATA: 4, | |
| SEND_IPS: 5, | |
| SET_TEAM_USERNAME: 6 | |
| }, | |
| teamReceiveAction = { | |
| URL: 1, | |
| BECOME_HOST: 2, | |
| ADD_PLAYER: 3, | |
| REMOVE_PLAYER: 4, | |
| REQUEST_IPS: 5, | |
| GAME_START: 6, | |
| TEAM_IS_FULL: 7, | |
| SET_TEAM_USERNAME: 8 | |
| }, | |
| colors = { | |
| grey: { | |
| BG: "#3a342f", | |
| brighter: "#4e463f", | |
| darker: "#2d2926", | |
| diagonalLines: "#c7c7c7" | |
| }, | |
| red: { | |
| brighter: "#a22929", | |
| darker: "#7b1e1e", | |
| slightlyBrighter: "#af2c2c", | |
| pattern: "#8c2222", | |
| patternEdge: "#631717", | |
| boundsDark: "#420707", | |
| boundsBright: "#4c0808" | |
| }, | |
| red2: { | |
| brighter: "#E3295E", | |
| darker: "#B3224B", | |
| slightlyBrighter: "#F02B63", | |
| pattern: "#CC2554", | |
| patternEdge: "#9C1C40" | |
| }, | |
| pink: { | |
| brighter: "#A22974", | |
| darker: "#7A1F57", | |
| pattern: "#8A2262", | |
| patternEdge: "#5E1743", | |
| slightlyBrighter: "#B02C7E" | |
| }, | |
| pink2: { | |
| brighter: "#7D26EF", | |
| darker: "#5E1DBA", | |
| pattern: "#6A21D1", | |
| patternEdge: "#4C1896", | |
| slightlyBrighter: "#882DFF" | |
| }, | |
| purple: { | |
| brighter: "#531880", | |
| darker: "#391058", | |
| pattern: "#4b1573", | |
| patternEdge: "#3b115a", | |
| slightlyBrighter: "#5a198c" | |
| }, | |
| blue: { | |
| brighter: "#27409c", | |
| darker: "#1d3179", | |
| pattern: "#213786", | |
| patternEdge: "#1b2b67", | |
| slightlyBrighter: "#2a44a9" | |
| }, | |
| blue2: { | |
| brighter: "#3873E0", | |
| darker: "#2754A3", | |
| pattern: "#2F64BF", | |
| patternEdge: "#1F4587", | |
| slightlyBrighter: "#3B79ED" | |
| }, | |
| green: { | |
| brighter: "#2ACC38", | |
| darker: "#1C9626", | |
| pattern: "#24AF30", | |
| patternEdge: "#178220", | |
| slightlyBrighter: "#2FD63D" | |
| }, | |
| green2: { | |
| brighter: "#1e7d29", | |
| darker: "#18561f", | |
| pattern: "#1a6d24", | |
| patternEdge: "#14541c", | |
| slightlyBrighter: "#21882c" | |
| }, | |
| leaf: { | |
| brighter: "#6a792c", | |
| darker: "#576325", | |
| pattern: "#5A6625", | |
| patternEdge: "#454F1C", | |
| slightlyBrighter: "#738430" | |
| }, | |
| yellow: { | |
| brighter: "#d2b732", | |
| darker: "#af992b", | |
| pattern: "#D1A932", | |
| patternEdge: "#B5922B", | |
| slightlyBrighter: "#e6c938" | |
| }, | |
| orange: { | |
| brighter: "#d06c18", | |
| darker: "#ab5a15", | |
| pattern: "#AF5B16", | |
| patternEdge: "#914A0F", | |
| slightlyBrighter: "#da7119" | |
| }, | |
| gold: { | |
| brighter: "#F6B62C", | |
| darker: "#F7981B", | |
| pattern: "#DC821E", | |
| patternEdge: "#BD6B0E", | |
| slightlyBrighter: "#FBDF78", | |
| bevelBright: "#F9D485" | |
| } | |
| }, | |
| titleLines = [{ | |
| line: [ | |
| [86, 82], | |
| [50, 57, 25, 99, 65, 105], | |
| [110, 110, 80, 158, 42, 129] | |
| ], | |
| speed: 1, | |
| offset: 0, | |
| posOffset: [16, 0] | |
| }, { | |
| line: [ | |
| [129, 74], | |
| [129, 169] | |
| ], | |
| speed: 1, | |
| offset: .7, | |
| posOffset: [10, 0] | |
| }, { | |
| line: [ | |
| [129, 106], | |
| [129, 63, 191, 63, 191, 106], | |
| [191, 149, 129, 149, 129, 106] | |
| ], | |
| speed: 1, | |
| offset: 1.2, | |
| posOffset: [10, 0] | |
| }, { | |
| line: [ | |
| [236, 41], | |
| [236, 138] | |
| ], | |
| speed: 2, | |
| offset: .7, | |
| posOffset: [0, 0] | |
| }, { | |
| line: [ | |
| [276, 41], | |
| [276, 45] | |
| ], | |
| speed: 3, | |
| offset: .4, | |
| posOffset: [0, 0] | |
| }, { | |
| line: [ | |
| [276, 74], | |
| [276, 138] | |
| ], | |
| speed: 2, | |
| offset: 0, | |
| posOffset: [0, 0] | |
| }, { | |
| line: [ | |
| [318, 74], | |
| [366, 138] | |
| ], | |
| speed: 2, | |
| offset: .5, | |
| posOffset: [-5, 0] | |
| }, { | |
| line: [ | |
| [318, 138], | |
| [366, 74] | |
| ], | |
| speed: 4, | |
| offset: 0, | |
| posOffset: [-5, 0] | |
| }, { | |
| line: [ | |
| [415, 136], | |
| [415, 134, 419, 134, 419, 136], | |
| [419, 138, 415, 138, 415, 136] | |
| ], | |
| speed: 1, | |
| offset: 0, | |
| posOffset: [-25, 0] | |
| }, { | |
| line: [ | |
| [454, 41], | |
| [454, 45] | |
| ], | |
| speed: 3, | |
| offset: .8, | |
| posOffset: [-25, 0] | |
| }, { | |
| line: [ | |
| [454, 74], | |
| [454, 138] | |
| ], | |
| speed: 2, | |
| offset: .5, | |
| posOffset: [-25, 0] | |
| }, { | |
| line: [ | |
| [500, 106], | |
| [500, 63, 562, 63, 562, 106], | |
| [562, 149, 500, 149, 500, 106] | |
| ], | |
| speed: 1, | |
| offset: .2, | |
| posOffset: [-38, 0] | |
| }]; | |
| addSocketWrapper(), getServers(); | |
| var lastSendDir = -1, | |
| lastSendDirTime = 0, | |
| sendDirQueue = []; | |
| window.onload = function() { | |
| var a = location.href.indexOf("#"), | |
| b = location.href.indexOf("?"); | |
| if(b >= 0 && (a == -1 || b < a)) return void(location.href = location.href.split("?")[0]); | |
| mainCanvas = document.getElementById("mainCanvas"), ctx = mainCanvas.getContext("2d"), minimapCanvas = document.getElementById("minimapCanvas"), minimapCtx = minimapCanvas.getContext("2d"), linesCanvas = document.createElement("canvas"), linesCtx = linesCanvas.getContext("2d"), tempCanvas = document.createElement("canvas"), tempCtx = tempCanvas.getContext("2d"), transitionCanvas = document.getElementById("transitionCanvas"), tCtx = transitionCanvas.getContext("2d"), tutorialCanvas = document.getElementById("tutorialCanvas"), tutCtx = tutorialCanvas.getContext("2d"), tutorialText = document.getElementById("tutorialText"), touchControlsElem = document.getElementById("touchControls"), notificationElem = document.getElementById("notification"), skinScreen = document.getElementById("skinScreen"), skinCanvas = document.getElementById("skinScreenCanvas"), skinCtx = skinCanvas.getContext("2d"), lastStatValueElem = document.getElementById("lastStatsRight"), bestStatValueElem = document.getElementById("bestStatsRight"), joinButton = document.getElementById("joinButton"), teamBox = document.getElementById("teamBox"), teamBoxLoading = document.getElementById("teamBoxLoading"), teamBoxLoaded = document.getElementById("teamBoxLoaded"), teamShareLink = document.getElementById("teamShareLink"), teamShareCopyBtn = document.getElementById("teamShareCopyBtn"), qualityText = document.getElementById("qualityText"), teamPlayersList = document.getElementById("teamPlayersList"), teamNameH = document.getElementById("teamNameH"), teamNameInput = document.getElementById("teamNameInput"), lifeBox = document.getElementById("lifeBox"), adBox = document.getElementById("adbox"), window.onkeydown = function(a) { | |
| var b = a.keyCode; | |
| if(pressedKeys.indexOf(b) < 0) { | |
| pressedKeys.push(b); | |
| var c = !1; | |
| 38 != b && 87 != b && 56 != b && 73 != b || (sendDir(3), c = !0), 37 != b && 65 != b && 52 != b && 74 != b || (sendDir(2), c = !0), 39 != b && 68 != b && 54 != b && 76 != b || (sendDir(0), c = !0), 40 != b && 83 != b && 50 != b && 75 != b || (sendDir(1), c = !0), 80 == b && (sendDir(4), c = !0), 32 != b && 53 != b || (honkStart(), c = !0), 13 == b && (doSkipDeathTransition(), c = !0), c && playingAndReady && a.preventDefault() | |
| } | |
| }, window.onkeyup = function(a) { | |
| var b = a.keyCode, | |
| c = pressedKeys.indexOf(b); | |
| pressedKeys.splice(c, 1), 32 != b && 53 != b || honkEnd() | |
| }, bindSwipeEvents(), window.oncontextmenu = function(a) { | |
| return "embed" == a.target.nodeName.toLowerCase() || (a.preventDefault(), !1) | |
| }, myScoreElem = document.getElementById("blockCaptureCount"), myRealScoreElem = document.getElementById("score"), myKillsElem = document.getElementById("myKills"), myRankElem = document.getElementById("myRank"), totalPlayersElem = document.getElementById("totalPlayers"), leaderboardElem = document.createElement("tbody"); | |
| var c = document.createElement("table"); | |
| c.appendChild(leaderboardElem); | |
| var d = document.getElementById("leaderboard"); | |
| d.appendChild(c), uiElems.push(d), miniMapPlayer = document.getElementById("miniMapPlayer"), beginScreen = document.getElementById("beginScreen"), playUI = document.getElementById("playUI"), uiElems.push(document.getElementById("scoreBlock")), uiElems.push(document.getElementById("miniMap")), prerollElem = document.getElementById("preroll"), appLinksElem = document.getElementById("appLinks"), appLinksElem.style.opacity = 0, nameInput = document.getElementById("nameInput"), localStorage.name && (nameInput.value = localStorage.name), localStorage.teamName && (teamNameInput.value = localStorage.teamName), nameInput.focus(), localStorage.autoConnect && doConnect(), formElem = document.getElementById("nameForm"), formElem.onsubmit = function() { | |
| if("Teams" == selectedGamemode) teamWsSendMsg(teamSendAction.START_GAME); | |
| else try { | |
| connectWithTransition() | |
| } catch(a) { | |
| console.log("Error", a.stack), console.log("Error", a.name), console.log("Error", a.message), setNotification("An error occurred :/") | |
| } | |
| return !1 | |
| }, window.addEventListener("click", showCursor), window.addEventListener("mousemove", function(a) { | |
| lastMousePos = [a.screenX, a.screenY]; | |
| var b = lastMousePos[0] - mouseHidePos[0], | |
| c = lastMousePos[1] - mouseHidePos[1], | |
| d = Math.sqrt(Math.pow(b, 2) + Math.pow(c, 2)); | |
| d > 15 && showCursor() | |
| }), qualityText.onclick = toggleQuality, setQuality(), initTutorial(), initSkinScreen(), initTitle(), initGameModeUI(); | |
| var e = parseQuery(document.referrer); | |
| if("code" in e && "true" == localStorage.clickedLoginWithPatreonButton && simpleRequest("http://patreon.splix.io/login.php?code=" + e.code, function(a) { | |
| parsePatreonAuths(a), requestPatreonPledgeData() | |
| }), lsSet("clickedLoginWithPatreonButton", "false"), 0 === location.hash.indexOf("#pledged")) { | |
| var f = parseQuery(location.href); | |
| "action" in f && ["update", "create"].indexOf(f.action) == -1 || (document.getElementById("patreonOverlay").style.display = null) | |
| } | |
| if(requestPatreonPledgeData(), localStorage.refreshDuringAd && (initAipScript(), requestCanRunAds()), testPatreonAdsAllowed()) { | |
| googletag.cmd = []; | |
| var g = document.createElement("script"); | |
| g.type = "text/javascript", g.src = "https://www.googletagservices.com/tag/js/gpt.js", document.getElementsByTagName("head")[0].appendChild(g), googletag.cmd.push(function() { | |
| var a = [{ | |
| id: "/421469808/JTE_splix.io_300x250", | |
| size: [300, 250] | |
| }, { | |
| id: "/421469808/JTE_splix.io_336x280", | |
| size: [336, 280] | |
| }], | |
| b = randFromArray(a); | |
| googletag.defineSlot(b.id, b.size, "gpt-banner-1").addService(googletag.pubads()), googletag.pubads().enableSingleRequest(), googletag.pubads().addEventListener("slotOnload", function() { | |
| showBanner(), setAdBoxLeft() | |
| }), googletag.enableServices() | |
| }), googletag.cmd.push(function() { | |
| googletag.display("gpt-banner-1") | |
| }) | |
| } | |
| socialElem = document.getElementById("social"), socialElem.addEventListener("mouseenter", function() { | |
| socialHovering = !0, testSocialTarget() | |
| }), socialElem.addEventListener("mouseleave", function() { | |
| socialHovering = !1, testSocialTarget() | |
| }), bestStatBlocks = Math.max(bestStatBlocks, localStorage.getItem("bestStatBlocks")), bestStatKills = Math.max(bestStatKills, localStorage.getItem("bestStatKills")), bestStatLbRank = Math.max(bestStatLbRank, localStorage.getItem("bestStatLbRank")), bestStatAlive = Math.max(bestStatAlive, localStorage.getItem("bestStatAlive")), bestStatNo1Time = Math.max(bestStatNo1Time, localStorage.getItem("bestStatNo1Time")), window.requestAnimationFrame(loop); | |
| var h = IS_DEV_BUILD ? " (dev build)" : ""; | |
| console.log("%c splix.io %c\n\n\nversion " + JS_VERSION + " loaded" + h, "color: #a22929; font-size: 50px; font-family: arial; text-shadow: 1px 1px #7b1e1e, 2px 2px #7b1e1e;", "") | |
| }; | |
| var isConnectingWithTransition = !1, | |
| isConnecting = !1, | |
| selectedGamemode = "Normal", | |
| teamBeginUIIsHost = !1, | |
| teamWs4 = null, | |
| teamWs6 = null, | |
| teamWs = null, | |
| teamWs4Failed = !1, | |
| teamWs6Failed = !1, | |
| teamWsCloseWasIntended = !1, | |
| teamWsWasConnected = !1, | |
| teamShareUrl = "", | |
| teamServers = [], | |
| activeTeamServers = [], | |
| teamDoConnectAfterServersGet = !1, | |
| connectedTeamServerLetter = "", | |
| lastTeamLostConnShareUrl = "", | |
| lastTeamLostConnTime = 0, | |
| skipChangeToNormalOnce = !1, | |
| canRunAdsRequested = !1, | |
| initAipCalled = !1, | |
| prerollElem, isWaitingForAd = !1, | |
| prerollIsVisible = !1, | |
| afterDeathCounter = 0, | |
| doneAppLinksReady = !1, | |
| animateAppLinks = !1, | |
| appLinksTimer = -3, | |
| androidImgIsInit = !1, | |
| appleImgIsInit = !1, | |
| doneOnSocialReady = !1, | |
| twttrIsInit = !1, | |
| fbIsInit = !1, | |
| ytIsInit = !1, | |
| discordIsInit = !1, | |
| redditIsInit = !1, | |
| patreonCornerButtonIsInit = !1, | |
| lives = [], | |
| lifeBox, engagementIsPlaying = "true" == localStorage.engagementIsPlaying, | |
| engagementLastPlayTime = localStorage.engagementLastPlayTime; | |
| void 0 === engagementLastPlayTime && (engagementLastPlayTime = Date.now()); | |
| var engagementLastNoPlayTime = 0, | |
| engagementLastChangeTime = localStorage.engagementLastChangeTime; | |
| void 0 === engagementLastChangeTime && (engagementLastChangeTime = Date.now()); | |
| var engagementValue = localStorage.engagementValue; | |
| engagementValue = void 0 === engagementValue ? .5 : parseFloat(engagementValue); | |
| var retentionSamples = [], | |
| sentRetentionSamples = []; | |
| loadSentRetentionSamples(); | |
| var canvasTransformTypes = { | |
| MAIN: 1, | |
| TUTORIAL: 2, | |
| SKIN: 3, | |
| SKIN_BUTTON: 4, | |
| TITLE: 5, | |
| LIFE: 6 | |
| }, | |
| canvasTransformType = canvasTransformTypes.MAIN, | |
| currentTopNotifications = [], | |
| ease = { in : function(a) { | |
| return a * a * a * a | |
| }, | |
| out: function(a) { | |
| return 1 - Math.pow(1 - a, 4) | |
| }, | |
| inout: function(a) { | |
| return a < .5 ? 8 * a * a * a * a : 1 - Math.pow(-2 * a + 2, 4) / 2 | |
| } | |
| }, | |
| dtCaps = [0, 6.5, 16, 33, 49, 99], | |
| qualityText, gamePadIsHonking = !1, | |
| customMappings = [{ | |
| name: "Generic USB Joystick", | |
| buttonMap: { | |
| 0: 2, | |
| 1: 1, | |
| 2: 3, | |
| 3: 0, | |
| 4: 4, | |
| 5: 5, | |
| 6: 6, | |
| 7: 7, | |
| 8: 8, | |
| 9: 9, | |
| 10: 10, | |
| 11: 11, | |
| 12: 13, | |
| 13: 14, | |
| 14: 15, | |
| 15: 16 | |
| }, | |
| axesMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 2, | |
| 3: 4 | |
| } | |
| }, { | |
| name: "Bluetooth Gamepad", | |
| buttonMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 3, | |
| 3: 4, | |
| 4: 6, | |
| 5: 7, | |
| 6: 8, | |
| 7: 9, | |
| 8: 10, | |
| 9: 11, | |
| 10: 13, | |
| 11: 14, | |
| 12: 12, | |
| 13: 13, | |
| 14: 14, | |
| 15: 15 | |
| }, | |
| axesMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 2, | |
| 3: 5 | |
| } | |
| }], | |
| currentGamepad, currentMap = { | |
| buttonMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 2, | |
| 3: 3, | |
| 4: 4, | |
| 5: 5, | |
| 6: 6, | |
| 7: 7, | |
| 8: 8, | |
| 9: 9, | |
| 10: 10, | |
| 11: 11, | |
| 12: 12, | |
| 13: 13, | |
| 14: 14, | |
| 15: 15 | |
| }, | |
| axesMap: { | |
| 0: 0, | |
| 1: 1, | |
| 2: 2, | |
| 3: 3 | |
| } | |
| }, | |
| swearArr = "penis;fuck;anal;anus;shit;asshole;bitch;butthole;slut;bitch;gay;nigger;n1gger;nlgger;xhamster;cock;cunt;dick;porn;horny;pussy".split(";"), | |
| swearRepl = "balaboo"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment