Skip to content

Instantly share code, notes, and snippets.

@Pan-Maciek
Created December 25, 2016 21:30
Show Gist options
  • Select an option

  • Save Pan-Maciek/3dce2c9363e2410fd3d9d904bfa2f34f to your computer and use it in GitHub Desktop.

Select an option

Save Pan-Maciek/3dce2c9363e2410fd3d9d904bfa2f34f to your computer and use it in GitHub Desktop.
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&amp;url=http://splix.io&amp;hashtags=splixio&amp;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, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
}
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