// ==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
};
}
}
Donate for the site OpenUserJS
Are you sure you want to go to an external site to donate a monetary value?
WARNING: Some countries laws may supersede the payment processors policy such as the GDPR and PayPal. While it is highly appreciated to donate, please check with your countries privacy and identity laws regarding privacy of information first. Use at your utmost discretion.