NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Craftnite Utils
// @version 1.3
// @description Manual Server Selection and Water Spawn Fix for Craftnite
// @author Temm
// @license GPL-3.0-or-later
// @run-at document-end
// @match http*://*.craftnite.io/*
// @downloadURL https://openuserjs.org/install/Temm/Craftnite_Utils.user.js
// @updateURL https://openuserjs.org/meta/Temm/Craftnite_Utils.meta.js
// @icon https://www.google.com/s2/favicons?domain=craftnite.io
// @grant none
// ==/UserScript==
{
if (!window.temmMods) {
window.temmMods = [];
playGame = new Proxy(playGame, {
apply: (tar, that, args) => {
window.dispatchEvent(new Event("temm.playGame"))
return tar.apply(that, args);
}
});
G.Game.prototype.postLoad = new Proxy(G.Game.prototype.postLoad, {
apply: (tar, that, args) => {
let val = tar.apply(that, args);
window.dispatchEvent(new Event("temm.loadFinish"))
G.socket.addEventListener("connect", () => {
window.dispatchEvent(new Event("temm.connected"))
})
let onMsg = (m) => {
if (new DataView(m.data).getUint8(0) == G.a823.a174) {
G.socket.removeEventListener("message", onMsg);
setTimeout(() => {
let c = new a201;
let mods = window.temmMods.filter(m => m.announce).map(m => m.name).join(", ");
c.msg = "[Joined with Temm's " + mods + " (from OpenUserJS)]"
G.socket.send(c.a614());
window.dispatchEvent(new Event("temm.joined"))
}, 500)
}
}
G.socket.addEventListener("message", onMsg)
return val;
}
})
}
window.temmMods.push({ "name": "Craftnite Utils [Fix Water Spawn & Place Lag]", "announce": true })
function htmlToElement(html) {
var template = document.createElement('template');
template.innerHTML = html.trim();
return template.content.firstChild;
}
let elem = document.createElement("input");
elem.style.height = "50px";
elem.style.width = "100%"
elem.style.background = "white"
elem.style.borderRadius = "2px"
elem.style.border = "0px"
elem.style.textAlign = "center"
elem.style.fontSize = "15px"
elem.style.fontFamily = "Madera"
elem.placeholder = "Server Address (Empty for Random)"
document.getElementById("middlewrap").appendChild(elem)
// Set Server
let officialServer = true;
requestServerName = new Proxy(requestServerName, {
apply: tar => {
let v = elem.value.trim();
if (v != "") {
let addr;
if (v.includes(".")) {
addr = v;
officialServer = !v.endsWith(craftnite.io)
} else {
addr = v + ".craftnite.io"
}
Object.defineProperty(G, "gameServerAddress", {
value: addr,
writable: false
})
}
tar();
}
})
let first = true;
window.addEventListener("temm.playGame", () => {
a234.prototype.a614 = new Proxy(a234.prototype.a614, {
apply: function (target, that, args) {
let res = target.apply(that, args);
let { i: cx, e: cy, o: cz, v: locs, u: ids } = that;
if (new Set(cx).size != 1 || new Set(cy).size != 1 || new Set(cz).size != 1) {
console.log("Multi-place crosses chunk borders... skipping.");
return res;
}
console.log(JSON.stringify({ cx, cy, cz, locs, ids }));
// Set changed blocks in chunks
let chunks = new Set();
for (let i = 0; i < that.i.length; i++) {
try {
chunks.add(GAME.a865.a643s[cx[i]][cy[i]][cz[i]]);
GAME.a865.a643s[cx[i]][cy[i]][cz[i]].volume[locs[i]] = ids[i];
} catch (e) {
return res;
}
}
let compressed = []
for (let chunk of chunks) {
compressed.push(compressChunk(chunk.volume));
}
// Write to Packet buffer
let chunkByteTotal = compressed.reduce((acc, curr) => {
return acc + 4 * 4 + 4 * curr.blockTypes.length;
}, 0)
let buf = new ArrayBuffer(1 + chunkByteTotal);
let view = new DataView(buf);
let idx = 0;
view.setUint8(idx++, G.a823.a120); // Packet ID
for (let i in compressed) {
// Write Chunk Coordinates
view.setUint32(idx, cx[i], true);
idx += 4;
view.setUint32(idx, cy[i], true);
idx += 4;
view.setUint32(idx, cz[i], true);
idx += 4;
view.setUint32(idx, compressed[i].blockTypes.length, true);
idx += 4;
for (let j in compressed[i].blockTypes) {
view.setUint16(idx, compressed[i].blockTypes[j], true);
idx += 2;
view.setUint16(idx, compressed[i].blockAmounts[j], true); // Block Amount
idx += 2;
}
}
console.log("Finished writing " + compressed.length + " chunks at " + idx + "/" + buf.byteLength, cx, cy, cz);
GAME.firstChunkWorker.postMessage({
ao: G.a813.ao,
buffer: view,
first: true
});
return res;
}
})
if (first) {
first = false;
// Draw current Server
document.getElementById("gameContainer").appendChild(htmlToElement('<canvas id="temm-utils" style="background-color: rgba(0, 0, 0, 0); z-index: 11;"></canvas>'))
let cvs = document.getElementById("temm-utils");
cvs.width = window.innerWidth;
cvs.height = window.innerHeight;
let ctx = cvs.getContext("2d");
ctx.fillStyle = "#02149c";
ctx.font = "25px Madera"
if (!officialServer) {
ctx.fillText("Server: " + G.gameServerAddress, 270, cvs.height - 36);
} else {
let server = G.gameServerAddress.split(".")[0];
let w = ctx.measureText("Server: " + server).width;
ctx.fillText("Server: " + server, 270, cvs.height - 36);
ctx.font = "13px Madera"
ctx.fillText(".craftnite.io", 270 + w, cvs.height - 36);
}
// No Water/NAN spawn
G.a822er.prototype.respawned = new Proxy(G.a822er.prototype.respawned, {
apply: (tar, that, args) => {
if (isNaN(args[0])) {
console.log("[Temm-Utils] Protected you from spawning in the water!")
setTimeout(() => G.socket.send((new a192).a614()), 2000)
}
return tar.apply(that, args);
}
})
}
})
function compressChunk(blocks) {
let blockAmounts = [];
let blockTypes = [];
for (let i = 0; i < blocks.length; i++) {
if (blockAmounts.length === 0 || blockTypes[blockAmounts.length - 1] !== blocks[i]) {
blockTypes.push(blocks[i]);
blockAmounts.push(1);
} else {
blockAmounts[blockAmounts.length - 1]++;
}
}
return {
blockTypes,
blockAmounts
};
}
}