diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/delayUtils.js | 29 | ||||
-rw-r--r-- | src/utils/networkUtils.js | 185 | ||||
-rw-r--r-- | src/utils/nonPooledThread.js | 14 | ||||
-rw-r--r-- | src/utils/numberUtils.js | 102 | ||||
-rw-r--r-- | src/utils/renderJavaUtils.js | 413 | ||||
-rw-r--r-- | src/utils/renderLib2d.js | 172 | ||||
-rw-r--r-- | src/utils/renderUtils.js | 407 | ||||
-rw-r--r-- | src/utils/statUtils.js | 1204 | ||||
-rw-r--r-- | src/utils/stringUtils.js | 15 | ||||
-rw-r--r-- | src/utils/utils.js | 141 |
10 files changed, 2682 insertions, 0 deletions
diff --git a/src/utils/delayUtils.js b/src/utils/delayUtils.js new file mode 100644 index 0000000..3ec6d95 --- /dev/null +++ b/src/utils/delayUtils.js @@ -0,0 +1,29 @@ +const { default: FlatQueue } = require("../datastructures/flatqueue") + +if (!global.delayThingSoopy) { + + let functionQueue = new FlatQueue() + let functions = new Map() + let functionId = 0 + + function delay(time, callback) { + let id = functionId++ + functions.set(id, callback) + functionQueue.push(id, Date.now() + time) + } + + register("tick", () => { + while (functionQueue.length > 0 && Date.now() > functionQueue.peekValue()) { + let id = functionQueue.pop() + + functions.get(id)() + functions.delete(id) + } + }) + + global.delayThingSoopy = { + delay: delay + } +} + +module.exports = global.delayThingSoopy diff --git a/src/utils/networkUtils.js b/src/utils/networkUtils.js new file mode 100644 index 0000000..ca3270a --- /dev/null +++ b/src/utils/networkUtils.js @@ -0,0 +1,185 @@ +if (!global.networkUtilsThingSoopyPromise) { + + let jURL = Java.type("java.net.URL") + let jStandardCharsets = Java.type("java.nio.charset.StandardCharsets") + let jCollectors = Java.type("java.util.stream.Collectors") + let jBufferedReader = Java.type("java.io.BufferedReader") + let jInputStreamReader = Java.type("java.io.InputStreamReader") + let jString = Java.type("java.lang.String") + + function getUrlContent(theUrl, { userAgent = "Mozilla/5.0", includeConnection = false, postData = undefined } = {}) { + + if (global.soopyv2loggerthing) { + global.soopyv2loggerthing.logMessage("Loading API: " + theUrl, 4) + } + + // if(theUrl.includes("soopy.dev")){ + // throw new Error("Testing to ensure the module works when my server is down") + // } + // Thread.sleep(1000) //simulating high ping + + let conn = new jURL(theUrl).openConnection() + conn.setRequestProperty("User-Agent", userAgent) + + if (postData) { + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/json"); + conn.setDoOutput(true); + + let jsonInputString = new jString(JSON.stringify(postData)) + + let os + try { + os = conn.getOutputStream() + input = jsonInputString.getBytes("utf-8"); + os.write(input, 0, input.length); + } finally { + os.close() + } + } + + let stringData + + if (conn.getResponseCode() < 400) { + stringData = new jBufferedReader( + new jInputStreamReader(conn.getInputStream(), jStandardCharsets.UTF_8)) + .lines() + .collect(jCollectors.joining("\n")); + + conn.getInputStream().close() + } else { + stringData = new jBufferedReader( + new jInputStreamReader(conn.getErrorStream(), jStandardCharsets.UTF_8)) + .lines() + .collect(jCollectors.joining("\n")); + + conn.getErrorStream().close() + } + + if (includeConnection) { + return { stringData, connection: conn } + } + + return stringData + } + + function fetch(url, options = { userAgent: "Mozilla/5.0" }) { + let loadedConnection = undefined + let loadedString = undefined + let loadedJSON = undefined + + let ret = { + loadSync() { + if (loadedString === undefined) { + options.includeConnection = true + + try { + let data = getUrlContent(url, options) + loadedString = data.stringData + loadedConnection = data.connection + } catch (e) { + errorData = e + loadedString = null + } + } + + return ret + }, + async load(_ifError = false) { + if (loadedString === undefined) { + options.includeConnection = true + + await new Promise((res, rej) => { + pendingRequests.push({ + callback: (data) => { + loadedString = data.stringData + loadedConnection = data.connection + res() + }, + errcallback: (e) => { + rej(e) + }, + url: url, + options: options + }) + }) + } + }, + textSync() { + ret.loadSync() + + return loadedString + }, + async text() { + await ret.load() + + return loadedString + }, + jsonSync() { + if (loadedJSON === undefined) { + let str = ret.textSync() + + loadedJSON = JSON.parse(str) + } + + return loadedJSON + }, + async json() { + if (loadedJSON === undefined) { + let str = await ret.text() + + loadedJSON = JSON.parse(str) + } + + return loadedJSON + }, + responseCode() { + return loadedConnection?.getResponseCode() || -1 + } + } + return ret + } + + let pendingRequests = [] + let pendingResolves = [] + let runningThread = false + + register("tick", () => { + try { + while (pendingResolves.length > 0) { + let [callback, data] = pendingResolves.shift() + + callback(data) + } + } catch (e) { + console.log(JSON.stringify(e, undefined, 2)) + console.log(e.stack) + } + + if (pendingRequests.length > 0 && !runningThread) { + runningThread = true + new Thread(() => { + while (pendingRequests.length > 0) { + let req = pendingRequests.shift() + + try { + let data = getUrlContent(req.url, req.options) + + pendingResolves.push([req.callback, data]) + } catch (e) { + pendingResolves.push([req.errcallback, e]) + } + } + + runningThread = false + }).start() + } + }) + + global.networkUtilsThingSoopyPromise = { + getUrlContent: getUrlContent, + fetch: fetch + } +} + +module.exports = global.networkUtilsThingSoopyPromise diff --git a/src/utils/nonPooledThread.js b/src/utils/nonPooledThread.js new file mode 100644 index 0000000..4720700 --- /dev/null +++ b/src/utils/nonPooledThread.js @@ -0,0 +1,14 @@ +let Executors = Java.type("java.util.concurrent.Executors") + +class NonPooledThread { + constructor(fun) { + this.fun = fun + this.executor = Executors.newSingleThreadExecutor() + } + + start() { + this.executor.execute(this.fun) + } +} + +export default NonPooledThread
\ No newline at end of file diff --git a/src/utils/numberUtils.js b/src/utils/numberUtils.js new file mode 100644 index 0000000..8d5e7c3 --- /dev/null +++ b/src/utils/numberUtils.js @@ -0,0 +1,102 @@ +let utils = { + numberWithCommas: function (x) { + if (x === undefined) { return "" } + var parts = x.toString().split("."); + parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); + return parts.join("."); + }, + addNotation: function (type, value, joiner = "") { + let returnVal = value; + let notList = []; + if (type === "shortScale") { + //notation type + //do notation stuff here + notList = [ + " Thousand", + " Million", + " Billion", + " Trillion", + " Quadrillion", + " Quintillion" + ]; + } + + if (type === "oneLetters") { + notList = [" K", " M", " B", " T"]; + } + + let checkNum = 1000; + + if (type !== "none" && type !== "commas") { + let notValue = notList[notList.length - 1]; + for (let u = notList.length; u >= 1; u--) { + notValue = notList.shift(); + for (let o = 3; o >= 1; o--) { + if (value >= checkNum) { + returnVal = value / (checkNum / 100); + returnVal = Math.floor(returnVal); + returnVal = (returnVal / Math.pow(10, o)) * 10; + returnVal = +returnVal.toFixed(o - 1) + joiner + notValue; + } + checkNum *= 10; + } + } + } else { + returnVal = this.numberWithCommas(value.toFixed(0)); + } + + return returnVal; + }, + timeSince: function (date) { + if (typeof date !== 'object') { + date = new Date(date); + } + + var seconds = Math.floor((new Date() - date) / 1000); + var intervalType; + + var interval = Math.floor(seconds / 31536000); + interval = Math.floor(seconds / 86400); + if (interval >= 1) { + intervalType = 'd'; + } else { + interval = Math.floor(seconds / 3600); + if (interval >= 1) { + intervalType = "h"; + } else { + interval = Math.floor(seconds / 60); + if (interval >= 1) { + intervalType = "m"; + } else { + interval = seconds; + intervalType = "s"; + } + } + } + + return interval + '' + intervalType; + }, + timeSince2: (date) => { + let time = Date.now() - date + + if (time > 30 * 60000) { + return utils.timeNumber2(time) + } + return utils.timeNumber(time) + }, + timeNumber: (time, secondDecimals = 0) => { + let mins = Math.floor(time / 1000 / 60) + let secs = (time / 1000) % 60 + + if (mins === 0) return `${secs.toFixed(secondDecimals)}s` + return `${mins}m ${secs.toFixed(secondDecimals)}s` + }, + timeNumber2: (time) => { + let hours = Math.floor(time / 1000 / 60 / 60) + let mins = Math.floor(time / 1000 / 60) % 60 + + if (hours === 0) return mins + "m" + return `${hours}h ${mins}m` + } +} +module.exports = utils diff --git a/src/utils/renderJavaUtils.js b/src/utils/renderJavaUtils.js new file mode 100644 index 0000000..6a16cda --- /dev/null +++ b/src/utils/renderJavaUtils.js @@ -0,0 +1,413 @@ +import { m } from "../../mappings/mappings" +import { numberWithCommas } from "./numberUtils" + +let SoopyV2Forge = Java.type("me.soopyboo32.soopyv2forge.SoopyV2Forge").INSTANCE + +let LASTEST_SOOPYFORGE_VER = "1.1" // uncomment out on new soopyv2forge version +let canUseForgeRendering = net.minecraftforge.fml.common.Loader.isModLoaded("soopyv2forge")// && SoopyV2Forge.getVersion() === LASTEST_SOOPYFORGE_VER + +let ArrayList = Java.type("java.util.ArrayList") + +let Vec3 = Java.type("net.minecraft.util.Vec3") +let Vector2f = Java.type("javax.vecmath.Vector2f") +let RenderPointsC = Java.type("me.soopyboo32.soopyv2forge.RenderTypes.Points") +let RenderWorldTextC = Java.type("me.soopyboo32.soopyv2forge.RenderTypes.WorldText") +let RenderBeaconC = Java.type("me.soopyboo32.soopyv2forge.RenderTypes.Beacon") +let HudPointsC = Java.type("me.soopyboo32.soopyv2forge.RenderTypes.HudPoints") +let HudTextC = Java.type("me.soopyboo32.soopyv2forge.RenderTypes.HudText") + +let addFix = false +if (!global.soopyv2RenderWorldThings) { + global.soopyv2RenderWorldThings = new Set() + addFix = true +} +if (!global.soopyv2RenderHudThings) global.soopyv2RenderHudThings = new Set() + +register("gameUnload", () => { + global.soopyv2RenderWorldThings.clear() + SoopyV2Forge.setRenderWorldList(new ArrayList([])) + global.soopyv2RenderHudThings.clear() + SoopyV2Forge.setRenderHudList(new ArrayList([])) +}) + +let currentlyRendering = true +export function setRendering(rendering) { + if (!rendering) { + setRenderWorldList(new ArrayList([])) + setRenderHudList(new ArrayList([])) + } + currentlyRendering = rendering + if (rendering) { + setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings])) + setRenderHudList(new ArrayList([...global.soopyv2RenderHudThings])) + } +} + +function setRenderWorldList(data) { + if (currentlyRendering) SoopyV2Forge.setRenderWorldList(data) +} +function setRenderHudList(data) { + if (currentlyRendering) SoopyV2Forge.setRenderHudList(data) +} + +class RenderWorldAble { + startRender(isBatched) { + if (!canUseForgeRendering) return + if (global.soopyv2RenderWorldThings.has(this.javaObj)) return this + global.soopyv2RenderWorldThings.add(this.javaObj) + if (!isBatched) setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings])) + return this + } + stopRender(isBatched) { + if (!canUseForgeRendering) return + if (!global.soopyv2RenderWorldThings.has(this.javaObj)) return this + global.soopyv2RenderWorldThings.delete(this.javaObj) + if (!isBatched) setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings])) + return this + } +} +class RenderHudAble { + startRender() { + if (!canUseForgeRendering) return + if (global.soopyv2RenderHudThings.has(this.javaObj)) return this + global.soopyv2RenderHudThings.add(this.javaObj) + setRenderHudList(new ArrayList([...global.soopyv2RenderHudThings])) + return this + } + stopRender() { + if (!canUseForgeRendering) return + if (!global.soopyv2RenderHudThings.has(this.javaObj)) return this + global.soopyv2RenderHudThings.delete(this.javaObj) + setRenderHudList(new ArrayList([...global.soopyv2RenderHudThings])) + return this + } +} + +export class Points extends RenderWorldAble { + constructor(points, r, g, b, a, thickness, depth) { + this.javaObj = new RenderPointsC(new ArrayList(points.map(a => new Vec3(...a))), r, g, b, a, thickness, depth) + } + + setPoints(points) { + this.javaObj.points = new ArrayList(points.map(a => new Vec3(...a))) + return this + } + setRGBA(r, g, b, a) { + this.javaObj.red = r + this.javaObj.green = g + this.javaObj.blue = b + this.javaObj.alpha = a + return this + } + setThickness(thickness) { + this.javaObj.thickness = thickness + return this + } + setDepth(depth) { + this.javaObj.depthtest = depth + return this + } + setDisableCullFace(disable) { + this.javaObj.disableCullFace = disable + return this + } + setGLMode(glMode) { + this.javaObj.glmode = glMode + return this + } +} +export class FilledPoints extends Points { + constructor(points, r, g, b, a, thickness, depth) { + super(points, r, g, b, a, thickness, depth) + + this.setGLMode(GL11.GL_QUADS) + this.setDisableCullFace(true) + } +} +export class Box extends Points { + constructor(location, size, r, g, b, a, thickness, depth) { + super(Box.getPointsFromLocationSize(location, size), r, g, b, a, thickness, depth) + } + + setLocationSize(location, size) { + this.setPoints(Box.getPointsFromLocationSize(location, size)) + return this + } + + static getPointsFromLocationSize(location, size) { + let [x, y, z] = location + let [width, height, width2] = size + + return [[x + width, y + height, z + width2], + [x + width, y + height, z], + [x, y + height, z], + [x, y + height, z + width2], + [x + width, y + height, z + width2], + [x + width, y, z + width2], + [x + width, y, z], + [x, y, z], + [x, y, z + width2], + [x, y, z], + [x, y + height, z], + [x, y, z], + [x + width, y, z], + [x + width, y + height, z], + [x + width, y, z], + [x + width, y, z + width2], + [x, y, z + width2], + [x, y + height, z + width2], + [x + width, y + height, z + width2]] + } +} +export class FilledBox extends FilledPoints { + constructor(location, size, r, g, b, a, thickness, depth) { + super(FilledBox.getPointsFromLocationSize(location, size), r, g, b, a, thickness, depth) + } + + setLocationSize(location, size) { + this.setPoints(FilledBox.getPointsFromLocationSize(location, size)) + return this + } + + static getPointsFromLocationSize(location, size) { + let [x, y, z] = location + let [w, h, w2] = size + + return [ + [x + w, y + 0, z + w2], + [x + w, y + 0, z], + [x, y + 0, z], + [x, y + 0, z + w2], + + [x + w, y + h, z + w2], + [x + w, y + h, z], + [x, y + h, z], + [x, y + h, z + w2], + + [x, y + h, z + w2], + [x, y + h, z], + [x, y + 0, z], + [x, y + 0, z + w2], + + [x + w, y + h, z + w2], + [x + w, y + h, z], + [x + w, y + 0, z], + [x + w, y + 0, z + w2], + + [x + w, y + h, z], + [x, y + h, z], + [x, y + 0, z], + [x + w, y + 0, z], + + [x, y + h, z + w2], + [x + w, y + h, z + w2], + [x + w, y + 0, z + w2], + [x, y + 0, z + w2] + ] + } +} +export class WorldText extends RenderWorldAble { + constructor(location, text, depth, scale) { + this.javaObj = new RenderWorldTextC(new Vec3(...location), text, depth, scale) + } + + setLocation(location) { + this.javaObj.location = new Vec3(...location) + return this + } + setText(text) { + this.javaObj.text = text + return this + } + setDepthtest(depthtest) { + this.javaObj.depthtest = depthtest + return this + } + setScale(scale) { + this.javaObj.scale = scale + return this + } + setShadow(shadow) { + this.javaObj.shadow = shadow + return this + } +} + +export class Beacon extends RenderWorldAble { + constructor(location, r, g, b, a, depth) { + this.javaObj = new RenderBeaconC(new Vec3(...location), r, g, b, a, depth) + } + + setLocation(location) { + this.javaObj.location = new Vec3(...location) + return this + } + setRGBA(r, g, b, a) { + this.javaObj.red = r + this.javaObj.green = g + this.javaObj.blue = b + this.javaObj.alpha = a + return this + } + setDepthtest(depthtest) { + this.javaObj.depthtest = depthtest + return this + } + +} +export class HudPoints extends RenderHudAble { + constructor(points, r, g, b, a, thickness) { + this.javaObj = new HudPointsC(new ArrayList(points.map(a => new Vector2f(...a))), r, g, b, a, thickness) + } + + setPoints(points) { + this.javaObj.points = new ArrayList(points.map(a => new Vec3(...a))) + return this + } + setRGBA(r, g, b, a) { + this.javaObj.colorR = r + this.javaObj.colorG = g + this.javaObj.colorB = b + this.javaObj.colorA = a + return this + } + setThickness(thickness) { + this.javaObj.thickness = thickness + return this + } + setGlmode(glmode) { + this.javaObj.glmode = glmode + return this + } +} +export class HudText extends RenderHudAble { + constructor(text, x, y, shadow) { + this.javaObj = new HudTextC(text, x, y, shadow) + } + + setText(text) { + this.javaObj.textLines = text + return this + } + setX(x) { + this.javaObj.x = x + return this + } + setY(y) { + this.javaObj.y = y + return this + } + setScale(scale) { + this.javaObj.scale = scale + return this + } + setShadow(shadow) { + this.javaObj.shadow = shadow + return this + } +} + +export class Waypoint extends FilledBox { + constructor(x, y, z, r, g, b, { name = "", showDist = !!name, phase = false }) { + this.rendering = false + + let distToPlayerSq = (x - Player.getRenderX()) ** 2 + (y - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) ** 2 + (z - Player.getRenderZ()) ** 2 + + let alpha = Math.min(1, Math.max(0, 1 - (distToPlayerSq - 10000) / 12500)) + + super([x - 0.001, y - 0.001, z - 0.001], [1.002, 1.002, 1.002], r, g, b, 0.25 * alpha, 1, !phase) + + this.params = { x, y, z, r, g, b, name, showDist, phase } + + this.outLine = new Box([x - 0.002, y - 0.002, z - 0.002], [1.004, 1.004, 1.004], r, g, b, alpha, 3, !phase) + this.beam = new Beacon([x, y + 1, z], r, g, b, Math.min(1, Math.max(0, (distToPlayerSq - 25) / 100)) * alpha, true) + + let distToPlayer = Math.sqrt(distToPlayerSq) + + let distRender = Math.min(distToPlayer, 50) + + let loc5 = [Player.getRenderX() + (x + 0.5 - Player.getRenderX()) / (distToPlayer / distRender), (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]()) + (y + 2 + 20 * distToPlayer / 300 - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) / (distToPlayer / distRender), Player.getRenderZ() + (z + 0.5 - Player.getRenderZ()) / (distToPlayer / distRender)] + let loc6 = [Player.getRenderX() + (x + 0.5 - Player.getRenderX()) / (distToPlayer / distRender), (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]()) + (y + 2 + 20 * distToPlayer / 300 - 10 * distToPlayer / 300 - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) / (distToPlayer / distRender), Player.getRenderZ() + (z + 0.5 - Player.getRenderZ()) / (distToPlayer / distRender)] + + this.textLine1 = new WorldText([loc5[0], loc5[1], loc5[2]], "§a" + name, false, distRender / 12) + this.textLine2 = new WorldText([(name ? loc6[0] : loc5[0]), (name ? loc6[1] : loc5[1]), (name ? loc6[2] : loc5[2])], "§b(" + numberWithCommas(Math.round(distToPlayer)) + "m)", false, distRender / 12) + } + + update() { + let { x, y, z, r, g, b, name, showDist } = this.params + + let distToPlayerSq = (x - Player.getRenderX()) ** 2 + (y - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) ** 2 + (z - Player.getRenderZ()) ** 2 + + let alpha = Math.min(1, Math.max(0, 1 - (distToPlayerSq - 10000) / 12500)) + + this.setRGBA(r, g, b, 0.25 * alpha) + this.outLine.setRGBA(r, g, b, alpha) + this.beam.setRGBA(r, g, b, Math.min(1, Math.max(0, (distToPlayerSq - 25) / 100)) * alpha) + + if (name || showDist) { + let distToPlayer = Math.sqrt(distToPlayerSq) + + let distRender = Math.min(distToPlayer, 100) + + let loc5 = [Player.getRenderX() + (x + 0.5 - Player.getRenderX()) / (distToPlayer / distRender), (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]()) + (y + 2 + 20 * distToPlayer / 300 - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) / (distToPlayer / distRender), Player.getRenderZ() + (z + 0.5 - Player.getRenderZ()) / (distToPlayer / distRender)] + let loc6 = [Player.getRenderX() + (x + 0.5 - Player.getRenderX()) / (distToPlayer / distRender), (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]()) + (y + 2 + 20 * distToPlayer / 300 - 10 * distToPlayer / 300 - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) / (distToPlayer / distRender), Player.getRenderZ() + (z + 0.5 - Player.getRenderZ()) / (distToPlayer / distRender)] + + this.textLine1.setLocation([loc5[0], loc5[1], loc5[2]]).setScale(distRender / 12) + this.textLine2.setLocation([(name ? loc6[0] : loc5[0]), (name ? loc6[1] : loc5[1]), (name ? loc6[2] : loc5[2])]).setScale(distRender / 12).setText("§b(" + numberWithCommas(Math.round(distToPlayer)) + "m)") + } + } + + startRender(isBatched) { + if (this.rendering) return this + this.rendering = true + + super.startRender(true) + this.outLine.startRender(true) + this.beam.startRender(true) + if (this.params.name) this.textLine1.startRender(true) + if (this.params.showDist) this.textLine2.startRender(true) + + if (!isBatched) setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings])) + return this + } + + stopRender(isBatched) { + if (!this.rendering) return this + this.rendering = false + + super.stopRender(true) + this.outLine.stopRender(true) + this.beam.stopRender(true) + this.textLine1.stopRender(true) + this.textLine2.stopRender(true) + + if (!isBatched) setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings])) + return this + } +} + +register("worldLoad", () => { + if (!net.minecraftforge.fml.common.Loader.isModLoaded("soopyv2forge")) { + ChatLib.chat("&1" + ChatLib.getChatBreak("-").trim()) + ChatLib.chat("§cWARNING: You dont have the forge mod for soopyv2 installed") + ChatLib.chat("§cWARNING: -> almost nothing can be rendered") + new TextComponent(" &e[CLICK] &7- Download").setHover("show_text", "&2Download").setClick("open_url", "https://github.com/Soopyboo32/SoopyV2Forge/releases").chat() + ChatLib.chat("Or if u want to remove soopyv2 run /ct delete soopyv2") + ChatLib.chat("&1" + ChatLib.getChatBreak("-").trim()) + } + if (SoopyV2Forge.getVersion() !== LASTEST_SOOPYFORGE_VER) { + ChatLib.chat("&1" + ChatLib.getChatBreak("-").trim()) + ChatLib.chat("§cWARNING: Your forge version of soopyv2 is outdated") + if (LASTEST_SOOPYFORGE_VER === "1.1") { + ChatLib.chat("§cWARNING: this does not affect much at the moment, but has an incorect download url") + } else { + ChatLib.chat("§cWARNING: -> almost nothing can be rendered") + } + new TextComponent(" &e[CLICK] &7- Download").setHover("show_text", "&2Download update").setClick("open_url", "https://github.com/Soopyboo32/SoopyV2Forge/releases").chat() + ChatLib.chat("&1" + ChatLib.getChatBreak("-").trim()) + } +}) + +if (addFix) { + new Box([-1000000000, 0, 0], 0, 0, 0, 0, 0, 1, false).startRender() +}
\ No newline at end of file diff --git a/src/utils/renderLib2d.js b/src/utils/renderLib2d.js new file mode 100644 index 0000000..30ac28f --- /dev/null +++ b/src/utils/renderLib2d.js @@ -0,0 +1,172 @@ + +//-------------------------------------------------------------------------- +// CODE BY DJtheRedstoner +// IM COPYING THIS BECAUSE THE UPLOADED VERSION IS FOR +// CT 2.0.0 ONLY +// +// Edit: iv added some features to this so might keep as is +//-------------------------------------------------------------------------- + +import { f, m } from "../../mappings/mappings"; + + +const BufferUtils = org.lwjgl.BufferUtils; +const Project = org.lwjgl.util.glu.Project; + +const modelViewMatrix = BufferUtils.createFloatBuffer(16); +const projectionMatrix = BufferUtils.createFloatBuffer(16); +const viewportDims = BufferUtils.createIntBuffer(16); + +if(!GlStateManager){ + var GL11 = Java.type("org.lwjgl.opengl.GL11"); //using var so it goes to global scope + var GlStateManager = Java.type("net.minecraft.client.renderer.GlStateManager"); +} + +const ScaledResolution = net.minecraft.client.gui.ScaledResolution; + +const AxisAlignedBB = Java.type("net.minecraft.util.AxisAlignedBB") + +register('renderWorld', () => { + GlStateManager[m.pushMatrix](); + + let x = Player.getX(); + let y = Player.getY(); + let z = Player.getZ(); + + Tessellator.translate(-x, -y, -z); + + GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelViewMatrix); + GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrix); + + GlStateManager[m.popMatrix](); + + GL11.glGetInteger(GL11.GL_VIEWPORT, viewportDims); +}); + +export default class RenderLib2D { + // Utils + + // Original made by DJtheRedstoner + static projectPoint = (posX, posY, posZ) => { + const coords = BufferUtils.createFloatBuffer(3); + const success = Project.gluProject( + posX, + posY, + posZ, + modelViewMatrix, + projectionMatrix, + viewportDims, + coords + ); + + const z = coords.get(2); + if (!success || !(z > 0 && z < 1)) return null; + + const sr = new ScaledResolution(Client.getMinecraft()); + + const x = coords.get(0) / sr[m.getScaleFactor](); // getScaleFactor + let y = coords.get(1) / sr[m.getScaleFactor](); // getScaleFactor + // OpenGL starts at bottom left, mc starts at top left + y = sr[m.getScaledHeight]() - y; // getScaledHeight + + return { x, y, z }; + } + + static drawLine(x1, y1, z1, x2, y2, z2, color, thickness=1) { + let pos1 = RenderLib2D.projectPoint(x1, y1, z1); + let pos2 = RenderLib2D.projectPoint(x2, y2, z2); + + if(!pos1 || !pos2) return; + + let {x, y} = pos1 + let {x:ox, y:oy} = pos2 + + // console.log(x, y, ox, oy, thickness) + Renderer.drawLine(color, x, y, ox, oy, thickness); + } + + // Original made by DJtheRedstoner + static calculateBoundingBox = (box) => { + let vertices = RenderLib2D.getVertices(box); + + let x1 = java.lang.Float.MAX_VALUE; + let x2 = 0; + let y1 = java.lang.Float.MAX_VALUE; + let y2 = 0; + + vertices.forEach(vertex => { + let vec = RenderLib2D.projectPoint(vertex.x, vertex.y, vertex.z); + if (vec == null) return null; + + let x = vec.x; + let y = vec.y; + + if (x < x1) x1 = x; + if (x > x2) x2 = x; + if (y < y1) y1 = y; + if (y > y2) y2 = y; + }); + + return { x1, y1, x2, y2 }; + } + + static getVertices = (box) => { + let list = []; + + list.push({ x: box[f.minX.AxisAlignedBB], y: box[f.minY.AxisAlignedBB], z: box[f.minZ.AxisAlignedBB] }); + list.push({ x: box[f.maxX.AxisAlignedBB], y: box[f.minY.AxisAlignedBB], z: box[f.minZ.AxisAlignedBB] }); + list.push({ x: box[f.maxX.AxisAlignedBB], y: box[f.maxY.AxisAlignedBB], z: box[f.minZ.AxisAlignedBB] }); + list.push({ x: box[f.minX.AxisAlignedBB], y: box[f.maxY.AxisAlignedBB], z: box[f.minZ.AxisAlignedBB] }); + list.push({ x: box[f.minX.AxisAlignedBB], y: box[f.minY.AxisAlignedBB], z: box[f.maxZ.AxisAlignedBB] }); + list.push({ x: box[f.maxX.AxisAlignedBB], y: box[f.minY.AxisAlignedBB], z: box[f.maxZ.AxisAlignedBB] }); + list.push({ x: box[f.maxX.AxisAlignedBB], y: box[f.maxY.AxisAlignedBB], z: box[f.maxZ.AxisAlignedBB] }); + list.push({ x: box[f.minX.AxisAlignedBB], y: box[f.maxY.AxisAlignedBB], z: box[f.maxZ.AxisAlignedBB] }); + + return list; + } + + // Rendering Functions + + static drawNameTag = (vec, string) => { + if (vec === null) return; + + Renderer.drawStringWithShadow(string, vec.x - Renderer.getStringWidth(string) / 2, vec.y); + } + + static draw2DESP = (aabb, color, thickness) => { + let bb = RenderLib2D.calculateBoundingBox(aabb); + + Renderer.drawLine(color, bb.x1, bb.y1, bb.x1, bb.y2, thickness); + Renderer.drawLine(color, bb.x1, bb.y1, bb.x2, bb.y1, thickness); + Renderer.drawLine(color, bb.x2, bb.y2, bb.x2, bb.y1, thickness); + Renderer.drawLine(color, bb.x2, bb.y2, bb.x1, bb.y2, thickness); + } + + static draw3DESP = (aabb, color, thickness) => { + let vertices = RenderLib2D.getVertices(aabb); + let projected = []; + + vertices.forEach(vertex => { + let vec = RenderLib2D.projectPoint(vertex.x, vertex.y, vertex.z); + if (vec == null) return null; + projected.push(vec); + }); + + if (projected[0] && projected[1]) Renderer.drawLine(color, projected[0].x, projected[0].y, projected[1].x, projected[1].y, thickness); + if (projected[0] && projected[4]) Renderer.drawLine(color, projected[0].x, projected[0].y, projected[4].x, projected[4].y, thickness); + if (projected[5] && projected[1]) Renderer.drawLine(color, projected[5].x, projected[5].y, projected[1].x, projected[1].y, thickness); + if (projected[5] && projected[4]) Renderer.drawLine(color, projected[5].x, projected[5].y, projected[4].x, projected[4].y, thickness); + if (projected[3] && projected[2]) Renderer.drawLine(color, projected[3].x, projected[3].y, projected[2].x, projected[2].y, thickness); + if (projected[3] && projected[7]) Renderer.drawLine(color, projected[3].x, projected[3].y, projected[7].x, projected[7].y, thickness); + if (projected[6] && projected[2]) Renderer.drawLine(color, projected[6].x, projected[6].y, projected[2].x, projected[2].y, thickness); + if (projected[6] && projected[7]) Renderer.drawLine(color, projected[6].x, projected[6].y, projected[7].x, projected[7].y, thickness); + if (projected[1] && projected[2]) Renderer.drawLine(color, projected[1].x, projected[1].y, projected[2].x, projected[2].y, thickness); + if (projected[0] && projected[3]) Renderer.drawLine(color, projected[0].x, projected[0].y, projected[3].x, projected[3].y, thickness); + if (projected[4] && projected[7]) Renderer.drawLine(color, projected[4].x, projected[4].y, projected[7].x, projected[7].y, thickness); + if (projected[5] && projected[6]) Renderer.drawLine(color, projected[5].x, projected[5].y, projected[6].x, projected[6].y, thickness); + } + + static getBlockAABB = (x, y, z) => { + return new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1); + } +} diff --git a/src/utils/renderUtils.js b/src/utils/renderUtils.js new file mode 100644 index 0000000..321e821 --- /dev/null +++ b/src/utils/renderUtils.js @@ -0,0 +1,407 @@ +const { f, m } = require("../../mappings/mappings"); + +const { default: renderBeaconBeam2 } = require("../../BeaconBeam/index"); +const numberUtils = require("./numberUtils"); +const { default: RenderLib2D } = require("./renderLib2d"); + +if (!GlStateManager) { + var GL11 = Java.type("org.lwjgl.opengl.GL11"); //using var so it goes to global scope + var GlStateManager = Java.type("net.minecraft.client.renderer.GlStateManager"); +} +let ret = { + + /* accepts parameters + * h Object = {h:x, s:y, v:z} + * OR + * h, s, v + */ + HSVtoRGB: function (h, s, v) { + var r, g, b, i, f, p, q, t; + if (arguments.length === 1) { + s = h.s, v = h.v, h = h.h; + } + i = Math.floor(h * 6); + f = h * 6 - i; + p = v * (1 - s); + q = v * (1 - f * s); + t = v * (1 - (1 - f) * s); + switch (i % 6) { + case 0: r = v, g = t, b = p; break; + case 1: r = q, g = v, b = p; break; + case 2: r = p, g = v, b = t; break; + case 3: r = p, g = q, b = v; break; + case 4: r = t, g = p, b = v; break; + case 5: r = v, g = p, b = q; break; + } + return { + r: r * 255, + g: g * 255, + b: b * 255 + }; + }, + drawLine: function (x, y, z, x2, y2, z2, r, g, b, thickness = 1) { + + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(thickness); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(false); + GlStateManager.func_179094_E(); + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(r, g, b); + + Tessellator.pos(x, y, z); + Tessellator.pos(x2, y2, z2); + + Tessellator.draw(); + + + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + }, + drawLineWithDepth: function (x, y, z, x2, y2, z2, r, g, b, t = 1) { + + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(t); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDepthMask(false); + GlStateManager.func_179094_E(); + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(r, g, b); + + Tessellator.pos(x, y, z); + Tessellator.pos(x2, y2, z2); + + Tessellator.draw(); + + + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + }, + setupLineSmall: function (width) { + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(width); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDepthMask(false); + GlStateManager.func_179094_E(); + }, + endLineSmall: function () { + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + }, + drawLineSmall: function (x, y, z, x2, y2, z2, r, g, b) { + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(r, g, b); + + Tessellator.pos(x, y, z); + Tessellator.pos(x2, y2, z2); + + Tessellator.draw(); + }, + drawLinePoints: function (locations, r, g, b, thickness = 1, phase = false) { + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(thickness); + GL11.glDisable(GL11.GL_TEXTURE_2D); + if (phase) GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(false); + GlStateManager.func_179094_E(); + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(r, g, b); + + locations.forEach(loc => { + Tessellator.pos(...loc); + }); + + Tessellator.draw(); + + + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDepthMask(true); + if (phase) GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDisable(GL11.GL_BLEND); + }, + drawBoxAtBlockNotVisThruWalls: function (x, y, z, colorR, colorG, colorB, w = 1, h = 1, a = 1) { + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(3); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GlStateManager.func_179094_E(); + + x -= 0.005 + y -= 0.005 + z -= 0.005 + w += 0.01 + h += 0.01 + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(colorR, colorG, colorB, a); + + Tessellator.pos(x + w, y + h, z + w); + Tessellator.pos(x + w, y + h, z); + Tessellator.pos(x, y + h, z); + Tessellator.pos(x, y + h, z + w); + Tessellator.pos(x + w, y + h, z + w); + Tessellator.pos(x + w, y, z + w); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x, y, z); + Tessellator.pos(x, y, z + w); + Tessellator.pos(x, y, z); + Tessellator.pos(x, y + h, z); + Tessellator.pos(x, y, z); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x + w, y + h, z); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x + w, y, z + w); + Tessellator.pos(x, y, z + w); + Tessellator.pos(x, y + h, z + w); + Tessellator.pos(x + w, y + h, z + w); + + Tessellator.draw(); + + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + }, + drawBoxAtBlock: function (x, y, z, colorR, colorG, colorB, w = 1, h = 1, a = 1) { + + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(3); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(false); + GlStateManager[m.pushMatrix]() + + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(colorR, colorG, colorB, a); + + Tessellator.pos(x + w, y + h, z + w); + Tessellator.pos(x + w, y + h, z); + Tessellator.pos(x, y + h, z); + Tessellator.pos(x, y + h, z + w); + Tessellator.pos(x + w, y + h, z + w); + Tessellator.pos(x + w, y, z + w); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x, y, z); + Tessellator.pos(x, y, z + w); + Tessellator.pos(x, y, z); + Tessellator.pos(x, y + h, z); + Tessellator.pos(x, y, z); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x + w, y + h, z); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x + w, y, z + w); + Tessellator.pos(x, y, z + w); + Tessellator.pos(x, y + h, z + w); + Tessellator.pos(x + w, y + h, z + w); + + Tessellator.draw(); + + GlStateManager[m.popMatrix]() + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + }, + drawBoxAtBlock2: function (x, y, z, colorR, colorG, colorB, w = 1, h = 1, a = 1) { + + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(3); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(false); + GlStateManager[m.pushMatrix]() + + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(colorR, colorG, colorB, a); + + x -= w / 2 + z -= w / 2 + + Tessellator.pos(x + w, y + h, z + w); + Tessellator.pos(x + w, y + h, z); + Tessellator.pos(x, y + h, z); + Tessellator.pos(x, y + h, z + w); + Tessellator.pos(x + w, y + h, z + w); + Tessellator.pos(x + w, y, z + w); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x, y, z); + Tessellator.pos(x, y, z + w); + Tessellator.pos(x, y, z); + Tessellator.pos(x, y + h, z); + Tessellator.pos(x, y, z); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x + w, y + h, z); + Tessellator.pos(x + w, y, z); + Tessellator.pos(x + w, y, z + w); + Tessellator.pos(x, y, z + w); + Tessellator.pos(x, y + h, z + w); + Tessellator.pos(x + w, y + h, z + w); + + Tessellator.draw(); + + GlStateManager[m.popMatrix]() + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + }, + drawBoxAtEntity: function (entity, colorR, colorG, colorB, width, height, partialTicks, lineWidth = 2, phase = false) { + let x = entity.getX() + ((entity.getX() - entity.getLastX()) * partialTicks) + let y = entity.getY() + ((entity.getY() - entity.getLastY()) * partialTicks) + let z = entity.getZ() + ((entity.getZ() - entity.getLastZ()) * partialTicks) + + if (width === null) { + width = entity.getWidth() / 2 + height = entity.getHeight() + } else { + width = width / 2 + } + + + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(lineWidth); + if (phase) GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GlStateManager.func_179094_E(); + + + Tessellator.begin(GL11.GL_LINE_STRIP).colorize(colorR, colorG, colorB, 1); + + Tessellator.pos(x + width, y + height, z + width); + Tessellator.pos(x + width, y + height, z - width); + Tessellator.pos(x - width, y + height, z - width); + Tessellator.pos(x - width, y + height, z + width); + Tessellator.pos(x + width, y + height, z + width); + Tessellator.pos(x + width, y, z + width); + Tessellator.pos(x + width, y, z - width); + Tessellator.pos(x - width, y, z - width); + Tessellator.pos(x - width, y, z + width); + Tessellator.pos(x - width, y, z - width); + Tessellator.pos(x - width, y + height, z - width); + Tessellator.pos(x - width, y, z - width); + Tessellator.pos(x + width, y, z - width); + Tessellator.pos(x + width, y + height, z - width); + Tessellator.pos(x + width, y, z - width); + Tessellator.pos(x + width, y, z + width); + Tessellator.pos(x - width, y, z + width); + Tessellator.pos(x - width, y + height, z + width); + Tessellator.pos(x + width, y + height, z + width); + + Tessellator.draw(); + + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + if (phase) GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDisable(GL11.GL_BLEND); + }, + drawFilledBox: function (x, y, z, w, h, red, green, blue, alpha, phase) { //FROM RENDERUTILS + GL11.glDisable(GL11.GL_CULL_FACE); + if (phase) { + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(2.0); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(false); + GlStateManager.func_179094_E(); + } else { + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glBlendFunc(770, 771); + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(2.0); + GL11.glDepthMask(false); + GlStateManager.func_179094_E(); + } + + w /= 2; + + Tessellator.begin(GL11.GL_QUADS, false); + Tessellator.colorize(red, green, blue, alpha); + + Tessellator.translate(x, y, z) + .pos(w, 0, w) + .pos(w, 0, -w) + .pos(-w, 0, -w) + .pos(-w, 0, w) + + .pos(w, h, w) + .pos(w, h, -w) + .pos(-w, h, -w) + .pos(-w, h, w) + + .pos(-w, h, w) + .pos(-w, h, -w) + .pos(-w, 0, -w) + .pos(-w, 0, w) + + .pos(w, h, w) + .pos(w, h, -w) + .pos(w, 0, -w) + .pos(w, 0, w) + + .pos(w, h, -w) + .pos(-w, h, -w) + .pos(-w, 0, -w) + .pos(w, 0, -w) + + .pos(-w, h, w) + .pos(w, h, w) + .pos(w, 0, w) + .pos(-w, 0, w) + .draw(); + + GL11.glEnable(GL11.GL_CULL_FACE); + if (phase) { + GlStateManager.func_179121_F(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + } else { + GL11.glEnable(GL11.GL_TEXTURE_2D); + GlStateManager.func_179121_F(); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + } + }, + renderBeaconBeam(x, y, z, r, g, b, alpha, phase) { + renderBeaconBeam2(x, y, z, r, g, b, alpha, !phase) + }, + drawCoolWaypoint(x, y, z, r, g, b, { name = "", showDist = !!name, phase = false }) { + let distToPlayerSq = (x - Player.getRenderX()) ** 2 + (y - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) ** 2 + (z - Player.getRenderZ()) ** 2 + + let alpha = Math.min(1, Math.max(0, 1 - (distToPlayerSq - 10000) / 12500)) + + ret[phase ? "drawBoxAtBlock" : "drawBoxAtBlockNotVisThruWalls"](x - 0.005, y - 0.005, z - 0.005, r, g, b, 1.01, 1.01, alpha) + ret.drawFilledBox(x + 0.5, y, z + 0.5, 1.02, 1.01, r, g, b, 0.25 * alpha, phase) + renderBeaconBeam2(x, y + 1, z, r, g, b, Math.min(1, Math.max(0, (distToPlayerSq - 25) / 100)) * alpha, !phase) + + if (name || showDist) { + let distToPlayer = Math.sqrt(distToPlayerSq) + + let distRender = Math.min(distToPlayer, 50) + + let loc5 = [Player.getRenderX() + (x + 0.5 - Player.getRenderX()) / (distToPlayer / distRender), (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]()) + (y + 2 + 20 * distToPlayer / 300 - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) / (distToPlayer / distRender), Player.getRenderZ() + (z + 0.5 - Player.getRenderZ()) / (distToPlayer / distRender)] + let loc6 = [Player.getRenderX() + (x + 0.5 - Player.getRenderX()) / (distToPlayer / distRender), (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]()) + (y + 2 + 20 * distToPlayer / 300 - 10 * distToPlayer / 300 - (Player.getRenderY() + Player.getPlayer()[m.getEyeHeight]())) / (distToPlayer / distRender), Player.getRenderZ() + (z + 0.5 - Player.getRenderZ()) / (distToPlayer / distRender)] + + if (name) Tessellator.drawString("§a" + name, loc5[0], loc5[1], loc5[2], 0, true, distRender / 300, false) + if (showDist) Tessellator.drawString("§b(" + numberUtils.numberWithCommas(Math.round(distToPlayer)) + "m)", (name ? loc6[0] : loc5[0]), (name ? loc6[1] : loc5[1]), (name ? loc6[2] : loc5[2]), 0, false, distRender / 300, false) + } + } +} + +module.exports = ret
\ No newline at end of file diff --git a/src/utils/statUtils.js b/src/utils/statUtils.js new file mode 100644 index 0000000..89b467d --- /dev/null +++ b/src/utils/statUtils.js @@ -0,0 +1,1204 @@ +let utils = { + getHotmLevel: getHotmLevel, + getDungeoneeringLevel: getDungeoneeringLevel, + getPetLevel: getPetLevel, + getLevelByXp: getLevelByXp, +} + +module.exports = utils + + +let someData = { + leveling_xp: { + 1: 50, + 2: 125, + 3: 200, + 4: 300, + 5: 500, + 6: 750, + 7: 1000, + 8: 1500, + 9: 2000, + 10: 3500, + 11: 5000, + 12: 7500, + 13: 10000, + 14: 15000, + 15: 20000, + 16: 30000, + 17: 50000, + 18: 75000, + 19: 100000, + 20: 200000, + 21: 300000, + 22: 400000, + 23: 500000, + 24: 600000, + 25: 700000, + 26: 800000, + 27: 900000, + 28: 1000000, + 29: 1100000, + 30: 1200000, + 31: 1300000, + 32: 1400000, + 33: 1500000, + 34: 1600000, + 35: 1700000, + 36: 1800000, + 37: 1900000, + 38: 2000000, + 39: 2100000, + 40: 2200000, + 41: 2300000, + 42: 2400000, + 43: 2500000, + 44: 2600000, + 45: 2750000, + 46: 2900000, + 47: 3100000, + 48: 3400000, + 49: 3700000, + 50: 4000000, + 51: 4300000, + 52: 4600000, + 53: 4900000, + 54: 5200000, + 55: 5500000, + 56: 5800000, + 57: 6100000, + 58: 6400000, + 59: 6700000, + 60: 7000000 + }, + + // XP required for each level of Runecrafting + runecrafting_xp: { + 1: 50, + 2: 100, + 3: 125, + 4: 160, + 5: 200, + 6: 250, + 7: 315, + 8: 400, + 9: 500, + 10: 625, + 11: 785, + 12: 1000, + 13: 1250, + 14: 1600, + 15: 2000, + 16: 2465, + 17: 3125, + 18: 4000, + 19: 5000, + 20: 6200, + 21: 7800, + 22: 9800, + 23: 12200, + 24: 15300, + 25: 19050, + }, + + dungeoneering_xp: { + 1: 50, + 2: 75, + 3: 110, + 4: 160, + 5: 230, + 6: 330, + 7: 470, + 8: 670, + 9: 950, + 10: 1340, + 11: 1890, + 12: 2665, + 13: 3760, + 14: 5260, + 15: 7380, + 16: 10300, + 17: 14400, + 18: 20000, + 19: 27600, + 20: 38000, + 21: 52500, + 22: 71500, + 23: 97000, + 24: 132000, + 25: 180000, + 26: 243000, + 27: 328000, + 28: 445000, + 29: 600000, + 30: 800000, + 31: 1065000, + 32: 1410000, + 33: 1900000, + 34: 2500000, + 35: 3300000, + 36: 4300000, + 37: 5600000, + 38: 7200000, + 39: 9200000, + 40: 12000000, + 41: 15000000, + 42: 19000000, + 43: 24000000, + 44: 30000000, + 45: 38000000, + 46: 48000000, + 47: 60000000, + 48: 75000000, + 49: 93000000, + 50: 116250000, + }, + + guild_xp: [ + 100000, + 150000, + 250000, + 500000, + 750000, + 1000000, + 1250000, + 1500000, + 2000000, + 2500000, + 2500000, + 2500000, + 2500000, + 2500000, + 3000000, + ], + + // total XP required for level of Slayer + slayer_xp: { + zombie: { + 1: 5, + 2: 15, + 3: 200, + 4: 1000, + 5: 5000, + 6: 20000, + 7: 100000, + 8: 400000, + 9: 1000000, + }, + spider: { + 1: 5, + 2: 15, + 3: 200, + 4: 1000, + 5: 5000, + 6: 20000, + 7: 100000, + 8: 400000, + 9: 1000000, + }, + wolf: { + 1: 5, + 2: 15, + 3: 200, + 4: 1500, + 5: 5000, + 6: 20000, + 7: 100000, + 8: 400000, + 9: 1000000, + }, + enderman: { + 1: 5, + 2: 15, + 3: 200, + 4: 1500, + 5: 5000, + 6: 20000, + 7: 100000, + 8: 400000, + 9: 1000000, + } + }, + + slayer_boss_xp: { + 1: 5, + 2: 25, + 3: 100, + 4: 500, + }, +}; + + +function getLevelByXp(xp, type, levelCap) { + let xp_table = + type == 1 ? + someData.runecrafting_xp : + type == 2 ? + someData.dungeoneering_xp : + someData.leveling_xp; + + if (isNaN(xp)) { + return { + xp: 0, + level: 0, + xpCurrent: 0, + xpForNext: xp_table[1], + progress: 0, + }; + } + + let xpTotal = 0; + let level = 0; + + let xpForNext = Infinity; + + let maxLevel = Math.min(levelCap, Object.keys(xp_table) + .sort((a, b) => Number(a) - Number(b)) + .map((a) => Number(a)) + .pop()) + + for (let x = 1; x <= maxLevel; x++) { + xpTotal += xp_table[x]; + + if (xpTotal > xp) { + xpTotal -= xp_table[x]; + break; + } else { + level = x; + } + } + + let xpCurrent = Math.floor(xp - xpTotal); + + if (level < maxLevel) xpForNext = Math.ceil(xp_table[level + 1]); + + let progress = Math.max(0, Math.min(xpCurrent / xpForNext, 1)); + + + if (type === 2 && level === 50) { + while (level < levelCap && xpCurrent > 200000000) { + level++ + xpCurrent -= 200000000 + } + if (level < levelCap) { + progress = xpCurrent / 200000000 + xpForNext = 200000000 + } else { + progress = 0 + xpForNext = NaN + } + } + if (type === 0 && level === 60 && levelCap === Infinity) { + maxLevel = Infinity + let slope = 600000 + let xpForCurr = 7000000 + slope + while (xpCurrent > xpForCurr) { + level++ + xpCurrent -= xpForCurr + xpForCurr += slope + if (level % 10 === 0) slope *= 2 + } + + progress = xpCurrent / xpForCurr + xpForNext = xpForCurr + } + return { + xp, + level, + maxLevel, + xpCurrent, + xpForNext, + progress, + }; +} + +function getSlayerLevel(xp) { + let levelR = 0; + + Object.keys(someData.slayer_xp.zombie).forEach(level => { + if (someData.slayer_xp.zombie[level] < xp && parseInt(level) > levelR) { + levelR = parseInt(level) + } + }) + + return levelR; +} +function getSlayerLevelClaimed(slayer) { + let { + claimed_levels + } = slayer; + + let level = 0; + + for (let level_name in claimed_levels) { + let _level = parseInt(level_name.split("_").pop()); + + if (_level > level) level = _level; + } + + return level; +} + +function getDungeoneeringLevel(xp, isCata) { + let a = getLevelByXp(xp, 2, isCata ? Infinity : 50); + + return a.level + a.progress; +} + + +function firstLetterCapital(string) { + return string.substr(0, 1).toUpperCase() + string.substr(1) +} + +function firstLetterWordCapital(string) { + return string.split(" ").map(firstLetterCapital).join(" ") +} + +function getPetLevel(pet) { + let maxLevel = (pet.type === "GOLDEN_DRAGON") ? 200 : 100 + const rarityOffset = constants.pet_rarity_offset[pet.tier.toLowerCase()]; + const levels = constants.pet_levels.slice(rarityOffset, rarityOffset + maxLevel - 1); + + const xpMaxLevel = levels.reduce((a, b) => a + b, 0); + let xpTotal = 0; + let level = 1; + + let xpForNext = Infinity; + + for (let i = 0; i < maxLevel; i++) { + xpTotal += levels[i]; + + if (xpTotal > pet.exp) { + xpTotal -= levels[i]; + break; + } else { + level++; + } + } + + let xpCurrent = Math.floor(pet.exp - xpTotal); + let progress; + + if (level < maxLevel) { + xpForNext = Math.ceil(levels[level - 1]); + progress = Math.max(0, Math.min(xpCurrent / xpForNext, 1)); + } else { + level = maxLevel; + xpCurrent = pet.exp - levels[maxLevel - 1]; + xpForNext = 0; + progress = 1; + } + + return { + level, + xpCurrent, + xpForNext, + progress, + xpMaxLevel, + }; +} + +let constants = { + pet_rarity_offset: { + common: 0, + uncommon: 6, + rare: 11, + epic: 16, + legendary: 20, + mythic: 20, + }, + + pet_levels: [ + 100, 110, 120, 130, 145, 160, 175, 190, 210, 230, 250, 275, 300, 330, 360, 400, 440, 490, 540, 600, 660, 730, 800, + 880, 960, 1050, 1150, 1260, 1380, 1510, 1650, 1800, 1960, 2130, 2310, 2500, 2700, 2920, 3160, 3420, 3700, 4000, 4350, + 4750, 5200, 5700, 6300, 7000, 7800, 8700, 9700, 10800, 12000, 13300, 14700, 16200, 17800, 19500, 21300, 23200, 25200, + 27400, 29800, 32400, 35200, 38200, 41400, 44800, 48400, 52200, 56200, 60400, 64800, 69400, 74200, 79200, 84700, 90700, + 97200, 104200, 111700, 119700, 128200, 137200, 146700, 156700, 167700, 179700, 192700, 206700, 221700, 237700, 254700, + 272700, 291700, 311700, 333700, 357700, 383700, 411700, 441700, 476700, 516700, 561700, 611700, 666700, 726700, + 791700, 861700, 936700, 1016700, 1101700, 1191700, 1286700, 1386700, 1496700, 1616700, 1746700, 1886700, + // Values below for above level 100 (legendary) are just guessed + 0, 1, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, + ], + + pet_levels_accum: [ + 100, + 110, + 120, + 130, + 145, + 160, + 175, + 190, + 210, + 230, + 250, + 275, + 300, + 330, + 360, + 400, + 440, + 490, + 540, + 600, + 660, + 730, + 800, + 880, + 960, + 1050, + 1150, + 1260, + 1380, + 1510, + 1650, + 1800, + 1960, + 2130, + 2310, + 2500, + 2700, + 2920, + 3160, + 3420, + 3700, + 4000, + 4350, + 4750, + 5200, + 5700, + 6300, + 7000, + 7800, + 8700, + 9700, + 10800, + 12000, + 13300, + 14700, + 16200, + 17800, + 19500, + 21300, + 23200, + 25200, + 27400, + 29800, + 32400, + 35200, + 38200, + 41400, + 44800, + 48400, + 52200, + 56200, + 60400, + 64800, + 69400, + 74200, + 79200, + 84700, + 90700, + 97200, + 104200, + 111700, + 119700, + 128200, + 137200, + 146700, + 156700, + 167700, + 179700, + 192700, + 206700, + 221700, + 237700, + 254700, + 272700, + 291700, + 311700, + 333700, + 357700, + 383700, + 411700, + 441700, + 476700, + 516700, + 561700, + 611700, + 666700, + 726700, + 791700, + 861700, + 936700, + 1016700, + 1101700, + 1191700, + 1286700, + 1386700, + 1496700, + 1616700, + 1746700, + 1886700 + ], + + pet_data: { + "BAT": { + head: "/head/382fc3f71b41769376a9e92fe3adbaac3772b999b219c9d6b4680ba9983e527", + type: "mining", + emoji: "🦇" + }, + "BLAZE": { + head: "/head/b78ef2e4cf2c41a2d14bfde9caff10219f5b1bf5b35a49eb51c6467882cb5f0", + type: "combat", + emoji: "🔥" + }, + "CHICKEN": { + head: "/head/7f37d524c3eed171ce149887ea1dee4ed399904727d521865688ece3bac75e", + type: "farming", + emoji: "🐔" + }, + "HORSE": { + head: "/head/36fcd3ec3bc84bafb4123ea479471f9d2f42d8fb9c5f11cf5f4e0d93226", + type: "combat", + emoji: "🐴" + }, + "JERRY": { + head: "/head/822d8e751c8f2fd4c8942c44bdb2f5ca4d8ae8e575ed3eb34c18a86e93b", + type: "combat", + emoji: "🧑" + }, + "OCELOT": { + head: "/head/5657cd5c2989ff97570fec4ddcdc6926a68a3393250c1be1f0b114a1db1", + type: "foraging", + emoji: "🐈" + }, + "PIGMAN": { + head: "/head/63d9cb6513f2072e5d4e426d70a5557bc398554c880d4e7b7ec8ef4945eb02f2", + type: "combat", + emoji: "🐷" + }, + "RABBIT": { + head: "/head/117bffc1972acd7f3b4a8f43b5b6c7534695b8fd62677e0306b2831574b", + type: "farming", + emoji: "🐇" + }, + "SHEEP": { + head: "/head/64e22a46047d272e89a1cfa13e9734b7e12827e235c2012c1a95962874da0", + type: "alchemy", + emoji: "🐑" + }, + "SILVERFISH": { + head: "/head/da91dab8391af5fda54acd2c0b18fbd819b865e1a8f1d623813fa761e924540", + type: "mining", + emoji: "🐛" + }, + "WITHER_SKELETON": { + head: "/head/f5ec964645a8efac76be2f160d7c9956362f32b6517390c59c3085034f050cff", + type: "mining", + emoji: "💀" + }, + "SKELETON_HORSE": { + head: "/head/47effce35132c86ff72bcae77dfbb1d22587e94df3cbc2570ed17cf8973a", + type: "combat", + emoji: "🐴" + }, + "WOLF": { + head: "/head/dc3dd984bb659849bd52994046964c22725f717e986b12d548fd169367d494", + type: "combat", + emoji: "🐺" + }, + "ENDERMAN": { + head: "/head/6eab75eaa5c9f2c43a0d23cfdce35f4df632e9815001850377385f7b2f039ce1", + type: "combat", + emoji: "🔮" + }, + "PHOENIX": { + head: "/head/23aaf7b1a778949696cb99d4f04ad1aa518ceee256c72e5ed65bfa5c2d88d9e", + type: "combat", + emoji: "🐦" + }, + "MAGMA_CUBE": { + head: "/head/38957d5023c937c4c41aa2412d43410bda23cf79a9f6ab36b76fef2d7c429", + type: "combat", + emoji: "🌋" + }, + "FLYING_FISH": { + head: "/head/40cd71fbbbbb66c7baf7881f415c64fa84f6504958a57ccdb8589252647ea", + type: "fishing", + emoji: "🐟" + }, + "BLUE_WHALE": { + head: "/head/dab779bbccc849f88273d844e8ca2f3a67a1699cb216c0a11b44326ce2cc20", + type: "fishing", + emoji: "🐋" + }, + "TIGER": { + head: "/head/fc42638744922b5fcf62cd9bf27eeab91b2e72d6c70e86cc5aa3883993e9d84", + type: "combat", + emoji: "🐯" + }, + "LION": { + head: "/head/38ff473bd52b4db2c06f1ac87fe1367bce7574fac330ffac7956229f82efba1", + type: "foraging", + emoji: "🦁" + }, + "PARROT": { + head: "/head/5df4b3401a4d06ad66ac8b5c4d189618ae617f9c143071c8ac39a563cf4e4208", + type: "alchemy", + emoji: "🦜" + }, + "SNOWMAN": { + head: "/head/11136616d8c4a87a54ce78a97b551610c2b2c8f6d410bc38b858f974b113b208", + type: "combat", + emoji: "⛄" + }, + "TURTLE": { + head: "/head/212b58c841b394863dbcc54de1c2ad2648af8f03e648988c1f9cef0bc20ee23c", + type: "combat", + emoji: "🐢" + }, + "BEE": { + head: "/head/7e941987e825a24ea7baafab9819344b6c247c75c54a691987cd296bc163c263", + type: "farming", + emoji: "🐝" + }, + "ENDER_DRAGON": { + head: "/head/aec3ff563290b13ff3bcc36898af7eaa988b6cc18dc254147f58374afe9b21b9", + type: "combat", + emoji: "🐲" + }, + "GUARDIAN": { + head: "/head/221025434045bda7025b3e514b316a4b770c6faa4ba9adb4be3809526db77f9d", + type: "combat", + emoji: "🐡" + }, + "SQUID": { + head: "/head/01433be242366af126da434b8735df1eb5b3cb2cede39145974e9c483607bac", + type: "fishing", + emoji: "🦑" + }, + "GIRAFFE": { + head: "/head/176b4e390f2ecdb8a78dc611789ca0af1e7e09229319c3a7aa8209b63b9", + type: "foraging", + emoji: "🦒" + }, + "ELEPHANT": { + head: "/head/7071a76f669db5ed6d32b48bb2dba55d5317d7f45225cb3267ec435cfa514", + type: "farming", + emoji: "🐘" + }, + "MONKEY": { + head: "/head/13cf8db84807c471d7c6922302261ac1b5a179f96d1191156ecf3e1b1d3ca", + type: "foraging", + emoji: "🐒" + }, + "SPIDER": { + head: "/head/cd541541daaff50896cd258bdbdd4cf80c3ba816735726078bfe393927e57f1", + type: "combat", + emoji: "🕷️" + }, + "ENDERMITE": { + head: "/head/5a1a0831aa03afb4212adcbb24e5dfaa7f476a1173fce259ef75a85855", + type: "mining", + emoji: "🐛" + }, + "GHOUL": { + head: "/head/87934565bf522f6f4726cdfe127137be11d37c310db34d8c70253392b5ff5b", + type: "combat", + emoji: "🧟" + }, + "JELLYFISH": { + head: "/head/913f086ccb56323f238ba3489ff2a1a34c0fdceeafc483acff0e5488cfd6c2f1", + type: "alchemy", + emoji: "🎐" + }, + "PIG": { + head: "/head/621668ef7cb79dd9c22ce3d1f3f4cb6e2559893b6df4a469514e667c16aa4", + type: "farming", + emoji: "🐷" + }, + "ROCK": { + head: "/head/cb2b5d48e57577563aca31735519cb622219bc058b1f34648b67b8e71bc0fa", + type: "mining", + emoji: "🗿" + }, + "SKELETON": { + head: "/head/fca445749251bdd898fb83f667844e38a1dff79a1529f79a42447a0599310ea4", + type: "combat", + emoji: "💀" + }, + "ZOMBIE": { + head: "/head/56fc854bb84cf4b7697297973e02b79bc10698460b51a639c60e5e417734e11", + type: "combat", + emoji: "🧟" + }, + "DOLPHIN": { + head: "/head/cefe7d803a45aa2af1993df2544a28df849a762663719bfefc58bf389ab7f5", + type: "fishing", + emoji: "🐬" + }, + "BABY_YETI": { + head: "/head/ab126814fc3fa846dad934c349628a7a1de5b415021a03ef4211d62514d5", + type: "fishing", + emoji: "❄️" + }, + "GOLEM": { + head: "/head/89091d79ea0f59ef7ef94d7bba6e5f17f2f7d4572c44f90f76c4819a714", + type: "combat", + emoji: "🗿" + }, + "HOUND": { + head: "/head/b7c8bef6beb77e29af8627ecdc38d86aa2fea7ccd163dc73c00f9f258f9a1457", + type: "combat", + emoji: "👹" + }, + "TARANTULA": { + head: "/head/8300986ed0a04ea79904f6ae53f49ed3a0ff5b1df62bba622ecbd3777f156df8", + type: "combat", + emoji: "🕸️" + }, + "BLACK_CAT": { + head: "/head/e4b45cbaa19fe3d68c856cd3846c03b5f59de81a480eec921ab4fa3cd81317", + type: "combat", + emoji: "🐱" + }, + "MEGALODON": { + head: null, + type: "combat", + emoji: "🐬" + } + }, + + pet_value: { + "common": 1, + "uncommon": 2, + "rare": 3, + "epic": 4, + "legendary": 5 + }, + + pet_rewards: { + 0: { + magic_find: 0 + }, + 10: { + magic_find: 1 + }, + 25: { + magic_find: 2 + }, + 50: { + magic_find: 3 + }, + 75: { + magic_find: 4 + }, + 100: { + magic_find: 5 + }, + 130: { + magic_find: 6 + }, + 175: { + magic_find: 7 + } + }, + + pet_items: { + PET_ITEM_ALL_SKILLS_BOOST_COMMON: { + description: "§7Gives +§a10% §7pet exp for all skills", + xpBoost: 0.1, + xpBoostType: "all" + }, + PET_ITEM_BIG_TEETH_COMMON: { + description: "§7Increases §9Crit Chance §7by §a5%", + stats: { + crit_chance: 5 + }, + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_IRON_CLAWS_COMMON: { + description: "§7Increases the pet's §9Crit Damage §7by §a40% §7and §9Crit Chance §7by §a40%", + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_SHARPENED_CLAWS_UNCOMMON: { + description: "§7Increases §9Crit Damage §7by §a15%", + stats: { + crit_damage: 15 + }, + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_HARDENED_SCALES_UNCOMMON: { + description: "§7Increases §aDefense §7by §a25", + stats: { + defense: 25 + }, + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_BUBBLEGUM: { + description: "§7Your pet fuses its power with placed §aOrbs §7to give them §a2x §7duration", + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_LUCKY_CLOVER: { + description: "§7Increases §bMagic Find §7by §a7", + stats: { + magic_find: 7 + }, + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_TEXTBOOK: { + description: "§7Increases the pet's §bIntelligence §7by §a100%", + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_SADDLE: { + description: "§7Increase horse speed by §a50% §7 and jump boost by §a100%", + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_EXP_SHARE: { + description: "§7While unequipped this pet gains §a25% §7of the equipped pet's xp, this is §7split between all pets holding the item.", + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_TIER_BOOST: { + description: "§7Boosts the §ararity §7of your pet by 1 tier!", + xpBoost: 0, + xpBoostType: "all" + }, + PET_ITEM_COMBAT_SKILL_BOOST_COMMON: { + description: "§7Gives +§a20% §7pet exp for Combat", + xpBoost: 0.2, + xpBoostType: "combat" + }, + PET_ITEM_COMBAT_SKILL_BOOST_UNCOMMON: { + description: "§7Gives +§a30% §7pet exp for Combat", + xpBoost: 0.3, + xpBoostType: "combat" + }, + PET_ITEM_COMBAT_SKILL_BOOST_RARE: { + description: "§7Gives +§a40% §7pet exp for Combat", + xpBoost: 0.4, + xpBoostType: "combat" + }, + PET_ITEM_COMBAT_SKILL_BOOST_EPIC: { + description: "§7Gives +§a50% §7pet exp for Combat", + xpBoost: 0.5, + xpBoostType: "combat" + }, + PET_ITEM_FISHING_SKILL_BOOST_COMMON: { + description: "§7Gives +§a20% §7pet exp for Fishing", + xpBoost: 0.2, + xpBoostType: "fishing" + }, + PET_ITEM_FISHING_SKILL_BOOST_UNCOMMON: { + description: "§7Gives +§a30% §7pet exp for Fishing", + xpBoost: 0.3, + xpBoostType: "fishing" + }, + PET_ITEM_FISHING_SKILL_BOOST_RARE: { + description: "§7Gives +§a40% §7pet exp for Fishing", + xpBoost: 0.4, + xpBoostType: "fishing" + }, + PET_ITEM_FISHING_SKILL_BOOST_EPIC: { + description: "§7Gives +§a50% §7pet exp for Fishing", + xpBoost: 0.5, + xpBoostType: "fishing" + }, + PET_ITEM_FORAGING_SKILL_BOOST_COMMON: { + description: "§7Gives +§a20% §7pet exp for Foraging", + xpBoost: 0.2, + xpBoostType: "foraging" + }, + PET_ITEM_FORAGING_SKILL_BOOST_UNCOMMON: { + description: "§7Gives +§a30% §7pet exp for Foraging", + xpBoost: 0.3, + xpBoostType: "foraging" + }, + PET_ITEM_FORAGING_SKILL_BOOST_RARE: { + description: "§7Gives +§a40% §7pet exp for Foraging", + xpBoost: 0.4, + xpBoostType: "foraging" + }, + PET_ITEM_FORAGING_SKILL_BOOST_EPIC: { + description: "§7Gives +§a50% §7pet exp for Foraging", + xpBoost: 0.5, + xpBoostType: "foraging" + }, + PET_ITEM_MINING_SKILL_BOOST_COMMON: { + description: "§7Gives +§a20% §7pet exp for Mining", + xpBoost: 0.2, + xpBoostType: "mining" + }, + PET_ITEM_MINING_SKILL_BOOST_UNCOMMON: { + description: "§7Gives +§a30% §7pet exp for Mining", + xpBoost: 0.3, + xpBoostType: "mining" + }, + PET_ITEM_MINING_SKILL_BOOST_RARE: { + description: "§7Gives +§a40% §7pet exp for Mining", + xpBoost: 0.4, + xpBoostType: "mining" + }, + PET_ITEM_MINING_SKILL_BOOST_EPIC: { + description: "§7Gives +§a50% §7pet exp for Mining", + xpBoost: 0.5, + xpBoostType: "mining" + }, + PET_ITEM_FARMING_SKILL_BOOST_COMMON: { + description: "§7Gives +§a20% §7pet exp for Farming", + xpBoost: 0.2, + xpBoostType: "farming" + }, + PET_ITEM_FARMING_SKILL_BOOST_UNCOMMON: { + description: "§7Gives +§a30% §7pet exp for Farming", + xpBoost: 0.3, + xpBoostType: "farming" + }, + PET_ITEM_FARMING_SKILL_BOOST_RARE: { + description: "§7Gives +§a40% §7pet exp for Farming", + xpBoost: 0.4, + xpBoostType: "farming" + }, + PET_ITEM_FARMING_SKILL_BOOST_EPIC: { + description: "§7Gives +§a50% §7pet exp for Farming", + xpBoost: 0.5, + xpBoostType: "farming" + } + } +} + +let weightData = { + /* + All weight calculations are provided by Senither(https://github.com/Senither/) + */ + skillWeight: { + // Maxes out mining at 1,750 points at 60. + mining: { + exponent: 1.18207448, + divider: 259634, + maxLevel: 60, + }, + // Maxes out foraging at 850 points at level 50. + foraging: { + exponent: 1.232826, + divider: 259634, + maxLevel: 50, + }, + // Maxes out enchanting at 450 points at level 60. + enchanting: { + exponent: 0.96976583, + divider: 882758, + maxLevel: 60, + }, + // Maxes out farming at 2,200 points at level 60. + farming: { + exponent: 1.217848139, + divider: 220689, + maxLevel: 60, + }, + // Maxes out combat at 1,500 points at level 60. + combat: { + exponent: 1.15797687265, + divider: 275862, + maxLevel: 60, + }, + // Maxes out fishing at 2,500 points at level 50. + fishing: { + exponent: 1.406418, + divider: 88274, + maxLevel: 50, + }, + // Maxes out alchemy at 200 points at level 50. + alchemy: { + exponent: 1.0, + divider: 1103448, + maxLevel: 50, + }, + // Maxes out taming at 500 points at level 50. + taming: { + exponent: 1.14744, + divider: 441379, + maxLevel: 50, + }, + // Sets up carpentry and runecrafting without any weight components. + carpentry: { + maxLevel: 50, + }, + runecrafting: { + maxLevel: 25, + }, + }, + dungeonsWeight: { + catacombs: 0.0002149604615, + healer: 0.0000045254834, + mage: 0.0000045254834, + berserk: 0.0000045254834, + archer: 0.0000045254834, + tank: 0.0000045254834, + }, + slayerWeight: { + zombie: { + divider: 2208, + modifier: 0.15, + }, + spider: { + divider: 2118, + modifier: 0.08, + }, + wolf: { + divider: 1962, + modifier: 0.015, + }, + enderman: { + divider: 1430, + modifier: 0.017, + }, + }, +} + + +const level50SkillExp = 55172425; +const level60SkillExp = 111672425; +function calcSkillWeight(skillGroup, level, experience) { + if (skillGroup.exponent == undefined || skillGroup.divider == undefined) { + return { + weight: 0, + weight_overflow: 0, + }; + } + + let maxSkillLevelXP = skillGroup.maxLevel == 60 ? level60SkillExp : level50SkillExp; + + let base = Math.pow(level * 10, 0.5 + skillGroup.exponent + level / 100) / 1250; + if (experience > maxSkillLevelXP) { + base = Math.round(base); + } + + if (experience <= maxSkillLevelXP) { + return { + weight: base, + weight_overflow: 0, + }; + } + + return { + weight: base, + weight_overflow: Math.pow((experience - maxSkillLevelXP) / skillGroup.divider, 0.968), + }; +} + +function calcSlayerWeight(type, experience) { + const slayerWeight = weightData.slayerWeight[type]; + + if (!experience || experience <= 1000000) { + return { + weight: !experience ? 0 : experience / slayerWeight.divider, // for some reason experience can be undefined + weight_overflow: 0, + }; + } + + let base = 1000000 / slayerWeight.divider; + let remaining = experience - 1000000; + + let modifier = slayerWeight.modifier; + let overflow = 0; + + while (remaining > 0) { + let left = Math.min(remaining, 1000000); + + overflow += Math.pow(left / (slayerWeight.divider * (1.5 + modifier)), 0.942); + modifier += slayerWeight.modifier; + remaining -= left; + } + + return { + weight: base, + weight_overflow: overflow, + }; +} + + +function calcDungeonsWeight(type, level, experience) { + if (type.startsWith("master_")) { + return { + weight: 0, + weight_overflow: 0, + }; + } + + let percentageModifier = weightData.dungeonsWeight[type]; + let level50Experience = 569809640; + + let base = Math.pow(level, 4.5) * percentageModifier; + + if (experience <= level50Experience) { + return { + weight: base, + weight_overflow: 0, + }; + } + + let remaining = experience - level50Experience; + let splitter = (4 * level50Experience) / base; + + return { + weight: Math.floor(base), + weight_overflow: Math.pow(remaining / splitter, 0.968), + }; +} + +let hotmExps = [ + 0, + 3000, + 9000, + 25000, + 60000, + 100000, + 150000 +] +function getHotmLevel(exp) { + let level = 0 + let expLeft = exp + let res = undefined + hotmExps.forEach((needed) => { + if (expLeft > needed) { + expLeft -= needed + level++ + } else if (!res) { + res = { + level: level, + expLeft: expLeft, + expToNext: needed - expLeft, + progress: expLeft / needed, + totalExp: exp + } + } + }) + if (!res) { + res = { + level: level, + expLeft: undefined, + expToNext: undefined, + progress: 0, + totalExp: exp + } + } + + return res +}
\ No newline at end of file diff --git a/src/utils/stringUtils.js b/src/utils/stringUtils.js new file mode 100644 index 0000000..f28841c --- /dev/null +++ b/src/utils/stringUtils.js @@ -0,0 +1,15 @@ +module.exports = { + + firstLetterCapital: firstLetterCapital, + + firstLetterWordCapital: firstLetterWordCapital + +} + +function firstLetterCapital(string) { + return string.substr(0, 1).toUpperCase() + string.substr(1) +} + +function firstLetterWordCapital(string) { + return string.split(" ").map(firstLetterCapital).join(" ") +}
\ No newline at end of file diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 0000000..1f6cd6e --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,141 @@ +const NBTTagString = Java.type('net.minecraft.nbt.NBTTagString'); + +let utils = { + addLore: function (item, prefix, value) { + + const list = item + .getNBT() + .getCompoundTag("tag") + .getCompoundTag("display") + .getTagMap() + .get("Lore") + + let done = false + // Gets the current lore lines + for (let i = 0; i < list.func_74745_c(); i++) { + if (String(list.func_150307_f(i)).startsWith(prefix)) { + list.func_150304_a(i, new NBTTagString(prefix + value)); + done = true + } + } + if (!done) { + list.func_74742_a(new NBTTagString(prefix + value)) + } + + item + .getNBT() + .getCompoundTag("tag") + .getCompoundTag("display") + .getRawNBT() + .func_74782_a("Lore", list); + }, + getSBID: function (item) { + return item?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getString("id") || null + }, + getSBUUID: function (item) { + return item?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getString("uuid") || null + }, + getSBEnchant: function (item, enchant) { + return item?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getCompoundTag("enchantments")?.getInteger(enchant) || null + }, + calculateDistance: function (p1, p2) { + var a = p2[0] - p1[0]; + var b = p2[1] - p1[1]; + var c = p2[2] - p1[2]; + + let ret = Math.hypot(a, b, c) + + if (ret < 0) { + ret *= -1 + } + return ret; + }, + calculateDistanceQuick: function (p1, p2) { + var a = p2[0] - p1[0]; + var b = p2[1] - p1[1]; + var c = p2[2] - p1[2]; + + let ret = a * a + b * b + c * c + + if (ret < 0) { + ret *= -1 + } + return ret; + }, + /** + * Please try not to use this + * it has O(n!) + * only use if points < 10 or something + * D: + * @param {*} startPoint + * @param {*} points + * @returns + */ + fastestPathThrough: function (startPoint, points) { + let ret = [] + while (ret.length < points.length) { + ret.push(ret.length) + } + + let allOrders = utils.permutation(ret) + + let lastOrder = [] + let lastOrderLength = Infinity + + for (let i = 0; i < allOrders.length; i++) { + let order = allOrders[i] + let lastPoint = startPoint + let positions = order.map((a) => { + return points[a] + }) + let len = 0 + for (let i = 0; i < positions.length; i++) { + len += utils.calculateDistance(lastPoint, positions[i]) + lastPoint = positions[i] + } + + if (len < lastOrderLength) { + lastOrder = order + lastOrderLength = len + } + } + + return lastOrder; + }, + permutation: function (array) { + function p(array, temp) { + var i, x; + if (!array.length) { + result.push(temp); + } + for (i = 0; i < array.length; i++) { + x = array.splice(i, 1)[0]; + p(array, temp.concat(x)); + array.splice(i, 0, x); + } + } + + var result = []; + p(array, []); + return result; + }, + toMessageWithLinks: function (text, color = "f") { + return text.split(" ").reduce((c, curr) => { + if (curr.match(/(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$])/igm)) { + c.push(curr) + c.push("&" + color) + } else { + c[c.length - 1] += (c[c.length - 1].length === 2 ? "" : " ") + curr + } + return c + }, ["&" + color]).map(a => { + if (a.match(/(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$])/igm)) { + return new TextComponent("&" + color + "&n" + a + "&" + color + ' ').setHover("show_text", "Click to open " + a.trim().replace(/^(?:[&§][0-9a-fmn])+|(?:[&§][0-9a-fmn])+$/g, "")).setClick("open_url", a.trim()) + } else { + return new TextComponent(a + ' ') + } + }).reduce((c, curr) => c.addTextComponent(curr), new Message()) + } +} + +module.exports = utils
\ No newline at end of file |