diff --git a/carrotpay.lua b/carrotpay.lua new file mode 100644 index 0000000..3262e87 --- /dev/null +++ b/carrotpay.lua @@ -0,0 +1,278 @@ +local pkey = settings.get("carrotpay.private_key") +if not switchcraft then + error("Must run on SwitchCraft 3") +end +sleep(1) +local sha256 = require("sha256") +if not chatbox or not chatbox.hasCapability("command") or not chatbox.hasCapability("tell") then + term.setBackgroundColor(colors.black) + term.clear() + term.setCursorPos(1,1) + term.setTextColor(colors.white) + print("Hey! it seems like you haven't registered chatbox") + print("If you don't have a chatbox key, run this command:") + term.setTextColor(colors.green) + print("/chatbox register") + term.setTextColor(colors.white) + print("Then copy that key and paste it here") + write("Alternatively, run ") + term.setTextColor(colors.blue) + print("chatbox register ") + term.setTextColor(colors.white) + local cbkey = read() + settings.set("chatbox.license_key",cbkey) + settings.save(".settings") + print("Key set. Press Any Key to reboot") + os.pullEvent("key") + os.reboot() +end +if not pkey then + term.setBackgroundColor(colors.black) + term.setTextColor(colors.white) + term.clear() + term.setCursorPos(1,1) + term.setBackgroundColor(colors.lightGray) + print("Initial Setup ") + term.setBackgroundColor(colors.black) + print("First, CarrotPay needs your private key") + print("for the wallet you wish to use with CarrotPay") + print("Please enter your private key (not password) here") + local ipkey = read() + settings.set("carrotpay.private_key",ipkey) + settings.save(".settings") + term.clear() + term.setCursorPos(1,1) + term.setBackgroundColor(colors.lightGray) + print("Initial Setup ") + term.setBackgroundColor(colors.black) + print("Do you want to use our default startup script?") + print("(Y/N)") + print("Typing anything other than Y will be treated as no") + term.setTextColor(colors.red) + print("WARNING! Saying yes will OVERWRITE startup.lua") + term.setTextColor(colors.white) + local event = {os.pullEvent("key")} + if event[2] == keys.y then + print("Overwrote startup file.") + fs.delete("startup.lua") + local file = fs.open("startup.lua","w") + file.write([=[while true do + shell.run("]=]..shell.getRunningProgram()..[=[") + sleep(2) + end]=]) + file.close() + end + print("CarrotPay Setup Requires a reboot.") + print("Press any key to reboot") + os.pullEvent("key") + os.reboot() +end +prt = require("cc.pretty").pretty_print +local owner =chatbox.getLicenseOwner() +local function makeaddressbyte(byte) + local byte = 48 + math.floor(byte/7) + return string.char(byte + 39 > 122 and 101 or byte > 57 and byte + 39 or byte) +end +local expect = require("cc.expect").expect +local function split(inputstr, sep) + expect(1,inputstr,"string") + expect(1,sep,"string","nil") + sep = sep or "," + local t={} + for str in string.gmatch(inputstr, "([^"..sep.."]+)") do + table.insert(t, str) + end + return t + end + +local function make_address(key) + local protein = {} + local stick = sha256(sha256(key)) + local n = 0 + local link = 0 + local v2 = "k" + repeat + if n<9 then protein[n] = string.sub(stick,0,2) + stick = sha256(sha256(stick)) end + n = n+1 + until n==9 + n=0 + repeat + link = tonumber(string.sub(stick,1+(2*n),2+(2*n)),16) % 9 + if string.len(protein[link]) ~= 0 then + v2 = v2 .. makeaddressbyte(tonumber(protein[link],16)) + protein[link] = '' + n=n+1 + else + stick = sha256(stick) + end + until n==9 + return v2 +end +local address = make_address(pkey) +local function get_balance(addr) + os.queueEvent("get_balance",addr) + _,balance,err = os.pullEvent("balance") + if balance == "error" then + prt(err) + return -1 + end + return balance +end +local function pay(to,amt,mta) + if not mta then mta = "" end + mta = "username="..owner..";"..mta + amt = tonumber(amt) + local bal = get_balance(address) + if amt > bal then + chatbox.tell(owner,"Transaction failed. Not enough Krist","&6CarrotPay") + return false + else + os.queueEvent("make_transaction",to,amt,mta) + _,ok = os.pullEvent("transaction_complete") + return ok + end +end +local function handleWebSockets() + local id = -1 + local r = http.post("https://krist.dev/ws/start","{\"privatekey\":\""..pkey.."\"}",{["content-type"]="application/json"}) + local resp = textutils.unserialiseJSON(r.readAll()) + r.close() + r = nil + if resp.ok then + socket = http.websocket(resp.url) + print("Connected to Krist Websockets") + id = id + 1 + socket.send('{\"id\":'..id ..',\"type\":\"subscribe\",\"event\":\"ownTransactions\"}') + while true do + event = {os.pullEvent()} + if event[1] == "websocket_message" then + if event[2] == resp.url then + wsevent = textutils.unserialiseJSON(event[3]) + if wsevent.event == "transaction" and wsevent.transaction.to == address then + local from = wsevent.transaction.from + local hasMessage = false + local hasError = false + local hasUsername = false + local message = "" + err = "" + if wsevent.transaction.metadata then + mta = split(wsevent.transaction.metadata,";") + for i,p in pairs(mta) do + if p:match("message") then + message = split(p,"=")[2] + hasMessage = true + end + if p:match("error") then + err = split(p,"=")[2] + hasError = true + end + if p:match("username") and not hasUsername then + from = split(p,"=")[2].." ("..wsevent.transaction.from..")" + hasUsername = true + end + end + end + msg2 = "You have received K"..wsevent.transaction.value.." from "..from + if hasMessage or hasError then + if hasMessage then + msg2 = msg2.."\nMessage: "..message + end + if hasError then + msg2 = msg2.."\nError: "..err + end + end + chatbox.tell(owner,msg2,"&6CarrotPay") + elseif wsevent.type == "keepalive" or wsevent.type == "response" then + else + end + end + elseif event[1] == "get_balance" then + id = id + 1 + local rq = { + id = id, + type="address", + address=event[2] + } + socket.send(textutils.serialiseJSON(rq)) + rspt =socket.receive() + rsp = textutils.unserialiseJSON(rspt) + if rsp.ok then + os.queueEvent("balance",rsp.address.balance) + else + os.queueEvent("balance","error",rsp) + end + + elseif event[1] == "make_transaction" then + id = id + 1 + local rq = { + id = id, + type="make_transaction", + to = event[2], + amount = event[3], + metadata = event[4], + } + socket.send(textutils.serialiseJSON(rq)) + local c + repeat + c = socket.receive() + c = textutils.unserialiseJSON(c) + until c.type == "response" + os.queueEvent("transaction_complete",c.ok) + end + end + end +end +local function handleCommands() + while true do + local command = {os.pullEvent("command")} + if command[3] == "pay" and command[5].ownerOnly then + if command[4][1] == "--update" then + shell.run("wget https://raw.githubusercontent.com/scmcgowen/carrotpay/main/carrotpay.lua "..shell.getRunningProgram()) + os.reboot() + end + if not command[4][1] then + chatbox.tell(command[2],"Specify who to pay","&6CarrotPay") + elseif not command[4][2] then + chatbox.tell(command[2],"Specify how much to pay","&6CarrotPay") + else + local c = false + command_copy = {table.unpack(command)} + mta = table.concat({select(3, unpack(command_copy[4]))}, " ") + local s = command[4][1] + if ((s:match("^k[a-z0-9]+$") or s:match("^[a-f0-9]+$")) and #s == 10) or (s:match("^[a-z0-9]@[a-z0-9]+$")) or s:match("^[%a%d]+@[%a%d]+%.kst$") or s:match("^[%a%d]+%.kst") then + c = pay(s,command[4][2],mta) + if c then + chatbox.tell(command[2],"Paid <:kst:665040403224985611>"..command[4][2].." to "..s,"&6CarrotPay") + end + elseif s:match("^[a-zA-Z0-9_]+$") and #s <16 then + c = pay(s.."@sc.kst",command[4][2],mta) + if c then + chatbox.tell(command[2],"Paid <:kst:665040403224985611>"..command[4][2] .. " to "..s,"&6CarrotPay") + end + else + chatbox.tell(command[2],"Invalid Krist Address","&6CarrotPay") + end + if not c then + chatbox.tell(command[2],"There was an error.","&6CarrotPay") + end + end + elseif command[3] == "request" and command[5].ownerOnly then + msg = table.concat({select(3,unpack(command[4]))}, " ") + if msg == "" then + chatbox.tell(command[4][1],owner.." wants <:kst:665040403224985611>"..command[4][2].." from you.\nPay to "..address,"&6CarrotPay") + else + chatbox.tell(command[4][1],owner.." wants <:kst:665040403224985611>"..command[4][2].." from you.\nPay to "..address.."\nMessage: "..msg,"&6CarrotPay") + end + chatbox.tell(owner,"Requested <:kst:665040403224985611>"..command[4][2].." from "..command[4][1],"&6CarrotPay") + elseif (command[3] == "bal" or command[3] == "balance") and command[5].ownerOnly then + local addr = command[4][1] or address + local bal = get_balance(addr) + chatbox.tell(owner,addr.." has a balance of <:kst:665040403224985611>"..bal,"&6CarrotPay") + + end + end +end +_,e = pcall(parallel.waitForAny,handleWebSockets,handleCommands) +if socket then socket.close() end +printError(e) diff --git a/jasper.lua b/jasper.lua new file mode 100644 index 0000000..8111994 --- /dev/null +++ b/jasper.lua @@ -0,0 +1,439 @@ +-- This is paid software, do not distribute, Rule 6.5 + +-- Settings, change them for different effects +local ownerUserName = "jasper_185" -- If set uses getMetaByName instead of getMetaOwner when getMetaOwner isn't available +local maxSpeed = 1 -- The speed of the last slot, note: it is impossible to go over speed 4, and trying to go over that limit will cause your movement direction to not sync up with your actual velocity "pushing" you towards the diagonals +local launchMult = 1 -- Higher values = stronger launch, may cause overshoot if too high +local baseSlotSpeed = 1 -- The base speed you got at, if set to 0 your slot 0 will not let you move at all, should be 0 if not using a keyboard module (WHY ARE YOU NOT USING IT? ITS AWESOME AND CHEAP) +local speedPower = 0 -- The power the speed is raised to (0 = constant speed, 1 = linear speed increase from each slot, 2 = exponential speed increase) +local sprintSpeedIncrease = 4 -- Whenever we are sprinting, how much faster do we go? +local gpsHover = true -- Do we use the GPS to stay still in the air while we are not moving? +local gpsStrength = 0.025 -- How strong is the GPS correction? (really doesn't need to be strong, as base hover is already really good and instead just makes it less stable) +local pitchChangesForward = false-- If you are looking up and pressing forward do you go up or do you go horizontal? +local doubleTapUpToToggle = 0.3 --t Whats the duration of time to toggle flight by spamming the up key? set to nil or to a negative number to disable and use a dedicated toggle key instead +local lagCompensation = true -- Do we try calculate the amount of lag we have, and try to compensate for that? +local smoothing = 0.65 -- How smooth is the flight? 0 = no smoothing, 1 = so smooth you will never start moving, 0.9 = pretty smooth +local autoDisengageOnGroundTouch = true -- Do we disable flight once we touch the ground? + +-- Still settings, but more technical +local gravityCancelation = 0.08 -- How strong gravity is, too low and you will fall down, too high and you will shoot up (The constant I for the Y PID) +local drag = 0.98 -- What is the drag +local waterGravityCancelation = 0.01 -- Water version of the above +local PStrength = 1 -- Strenght of P in PD settings +local DStrength = 1 -- Strenght of D in PD settings +local rateLimitAtPower = 1.5 -- Going above this power rate limits us +local yMult = 0.5 -- Launching in the Y dir is less strong +local elytraMult = 0.4 -- While elytra flying all dirs are less strong +local maxXZRatio = 0.8 -- How much X and Z axes can be reduced for more power in the Y axis before stopping, lowering this too much will give bad controll when going at high speeds, but having it too high will make hoving slightly less stable + +-- Keybinds +local forwardKey = keys.w; +local backKey = keys.s; +local leftKey = keys.a; +local rightKey = keys.d; +local upKey = keys.space; +local downKey = keys.leftShift; +local SprintKey = keys.r; -- Lets you hold this key to enable sprint mode, so it also lets you go at sprint speed backwards +local toggleFlightKey = keys.g; -- Only used when doubleTapSpaceToToggle is set to false + +-- Internal code, don't change unless you know what you are doing! +local modules = peripheral.wrap("back") +local hasKeyboard = modules.hasModule("plethora:keyboard") + +local pressedKeys = {} + +-- Global for isActive +local flightActive = false +local lastGroundTouch = os.clock() +local function isFlightActiveRaw(meta) + if hasKeyboard then + if autoDisengageOnGroundTouch then + if lastGroundTouch + 0.5 < os.clock() and not meta.isAirborne then + flightActive = false + end + + if not meta.isAirborne then + lastGroundTouch = os.clock() + end + end + return flightActive -- Toggled by keyboard module + end + + -- Enable flight when sneaking and having a decent Y vel so it doesn't activate when just holding shift on a block + if meta.isSneaking then + if not flightActive then + flightActive = math.abs(meta.motionY) > 0.2 + end + else + flightActive = false + end + return flightActive +end + +-- Calculates your desired speed +local isSprinting = false +local function getSpeedRaw(meta) + local selectedSlot = meta.heldItemSlot + + local speed = math.pow((selectedSlot + baseSlotSpeed) / (9 + baseSlotSpeed), speedPower) * maxSpeed; + if meta.isSprinting or pressedKeys[SprintKey] then + isSprinting = true + elseif not pressedKeys[forwardKey] and not pressedKeys[backKey] and not pressedKeys[leftKey] and not pressedKeys[rightKey] and not pressedKeys[upKey] and not pressedKeys[downKey] then -- Not great, but oh well + isSprinting = false + end + + if isSprinting then + speed = speed * sprintSpeedIncrease + end + + return speed +end + +-- Calculates your desired movement direction +local gpsX, gpsY, gpsZ +local function getDesiredDirRaw(meta) + -- If you want a goto function, you can calculate the direction to the next waypoint and return that here for example + + if not hasKeyboard then + local pitch = -math.rad(meta.pitch) + local yaw = math.rad(meta.yaw) + + local dx = -math.sin(yaw) * math.cos(pitch) + local dy = math.sin(pitch) + local dz = math.cos(yaw) * math.cos(pitch) + + return dx, dy, dz + else + local pitch = -math.rad(meta.pitch) + if not pitchChangesForward then pitch = 0 end + + local yaw = math.rad(meta.yaw) + + local fx = -math.sin(yaw) * math.cos(pitch) + local fy = math.sin(pitch) + local fz = math.cos(yaw) * math.cos(pitch) + + local sx = math.cos(yaw) + local sz = math.sin(yaw) + + local forward = (pressedKeys[forwardKey] and 1 or 0) + (pressedKeys[backKey] and -1 or 0) + local left = (pressedKeys[leftKey] and 1 or 0) + (pressedKeys[rightKey] and -1 or 0) + local up = (pressedKeys[upKey] and 1 or 0) + (pressedKeys[downKey] and -1 or 0) + + return fx * forward + sx * left, + fy * forward + up, + fz * forward + sz * left + end +end + +-- Below is the actual math / logic, i don't recommend changing this + +-- Overrides +local defaultIsFlightActiveOverride = function(defaultFlightActive, meta) return defaultFlightActive end +local defaultGetSpeedOverride = function(defaultSpeed, meta) return defaultSpeed end +local defaultGetDesiredDirOverride = function(defaultDirX, defaultDirY, defaultDirZ, meta) return defaultDirX, defaultDirY, defaultDirZ end +local defaultMotionOverride = function(defaultMotionX, defaultMotionY, defaultMotionZ, meta) return defaultMotionX, defaultMotionY, defaultMotionZ end + +local isFlightActiveOverride = defaultIsFlightActiveOverride +local getSpeedOverride = defaultGetSpeedOverride +local getDesiredDirOverride = defaultGetDesiredDirOverride +local motionOverride = defaultMotionOverride + +local function isFlightActive(meta) + return isFlightActiveOverride(isFlightActiveRaw(meta), meta) +end +local function getSpeed(meta) + return getSpeedOverride(getSpeedRaw(meta), meta) +end +local function getDesiredDir(meta) + local x, y, z = getDesiredDirRaw(meta) + return getDesiredDirOverride(x, y, z, meta) +end + + +-- utility function to convert the launch(yaw, pitch, speed) into a launch(x, y, z) +local lastLaunchX = 0 +local lastLaunchY = 0 +local lastLaunchZ = 0 + +local function launch(x, y, z, isElytraFlying) + lastLaunchX = x + lastLaunchY = y + lastLaunchZ = z + + y = y / yMult + + if isElytraFlying then + x = x / elytraMult + y = y / elytraMult + z = z / elytraMult + end + + local speed = math.sqrt(x * x + y * y + z * z) + if speed <= 0 then return end + + local launchSpeed = speed + if launchSpeed > 4 then launchSpeed = 4 end + + if launchSpeed > rateLimitAtPower then + launchSpeed = rateLimitAtPower + end + + if launchSpeed ~= speed then + -- reduce X and Z, but keep Y the same + -- This way hover is more stable when moving around quickly + + -- ((x*x+z*z)*M + y * y)^0.5 = launchSpeed + + if math.abs(y) < launchSpeed then + local ratio = (launchSpeed * launchSpeed - y * y) / (x * x + z * z) + if ratio > maxXZRatio then + lastLaunchX = lastLaunchX * ratio + lastLaunchZ = lastLaunchZ * ratio + speed = launchSpeed + end + elseif maxXZRatio <= 0 then + -- Okay, just using the Y is requiring more speed than we have + -- Set x and z to 0, and just maximize Y for what we can. not ideal. + x = 0 + z = 0 + speed = math.abs(y) + end + + + end + + local yaw = math.deg(math.atan2(-x, z)) + local pitch = math.deg(math.asin(-y / speed)) + + if yaw ~= yaw or pitch ~= pitch then return end -- Check for NaN's + + if launchSpeed ~= speed then + local ratio = launchSpeed / speed + lastLaunchX = lastLaunchX * ratio + lastLaunchY = lastLaunchY * ratio + lastLaunchZ = lastLaunchZ * ratio + end + + coroutine.resume(coroutine.create(function() modules.launch(yaw, pitch, launchSpeed) end)) +end + +-- Gps locking globals +local lockY -- Do you want to lock your coord? +local desiredGpsY -- What are your locked coords? + +-- For smoothing +local lastDesiredX, lastDesiredY, lastDesiredZ = 0, 0, 0 +local function flyLoop() + local lastIngame = os.epoch("ingame") + local lastUtc = os.epoch("utc") + + local expectedYVel = 0 + while true do + local meta + if ownerUserName and not modules.getMetaOwner then + meta = modules.getMetaByName(ownerUserName) + else + meta = modules.getMetaOwner() + end + + -- Fix inconsistency with meta input (it can be from before the launch, or after the launch, so add the expected launch speed if we are behind) + if math.abs(meta.motionY - expectedYVel) < math.abs(meta.motionY - expectedYVel - lastLaunchY) then + meta.motionX = meta.motionX + lastLaunchX + meta.motionY = meta.motionY + lastLaunchY + meta.motionZ = meta.motionZ + lastLaunchZ + end + + local gravity + if meta.isInWater then + gravity = waterGravityCancelation + else + gravity = gravityCancelation + end + + expectedYVel = (meta.motionY - gravity) * drag + + local nowIngame = os.epoch("ingame") + local nowUtc = os.epoch("utc") + local estimatedServerTicks = (nowIngame - lastIngame) / 3600 + local estimatedClientTicks = math.floor((nowUtc - lastUtc) / 50 + 0.5) + lastIngame = nowIngame + lastUtc = lastUtc + estimatedClientTicks * 50 + + estimatedServerTicks = 1 -- Its better this way + + if not lagCompensation then estimatedClientTicks = 1 end + + if not meta then + modules = peripheral.wrap("back") -- Fix it in case of death + -- But also don't sleep as FOR SOME REASON that can happen when you fly into unloaded chunks + -- And also don't restart for the same reason.. UGH! + -- There is just no good way to handle this + end + + if meta and isFlightActive(meta) then + local speed = getSpeed(meta) + + -- Calculate D + local cx = -meta.motionX * drag * DStrength + local cy = -(meta.motionY - gravity) * drag * DStrength + local cz = -meta.motionZ * drag * DStrength + + local dx, dy, dz = getDesiredDir(meta) + + -- Apply speed + dx = dx * speed + dy = dy * speed + dz = dz * speed + + dx, dy, dz = motionOverride(dx, dy, dz, meta) + + -- Apply smoothing + local canLockY = dy == 0 -- We need this before smoothing for gps hover + dx = dx + (lastDesiredX - dx) * smoothing + dy = dy + (lastDesiredY - dy) * smoothing + dz = dz + (lastDesiredZ - dz) * smoothing + + lastDesiredX = dx + lastDesiredY = dy + lastDesiredZ = dz + + -- Calculate P + dx = dx * PStrength + dy = dy * PStrength + dz = dz * PStrength + + if gpsHover then + -- Only start to lock the coords once we have slowed down to prevent a "jerk back" effect due to the GPS coords we have being slightly behind + lockY = canLockY and math.abs(dy) <= 0.001 and (lockY or math.abs(meta.motionY) < (0.1 * estimatedServerTicks)) + + -- Clear if it we do not want to lock the axis + if not lockY then desiredGpsY = nil end + + -- Set our desired movement direction towards our locked position + if lockY and desiredGpsY and gpsY then dy = (desiredGpsY - gpsY) * gpsStrength end + end + + launch( + (cx + dx) * launchMult, + (cy + dy) * launchMult + gravity * (estimatedServerTicks + estimatedClientTicks - 1), + (cz + dz) * launchMult, + meta.isElytraFlying + ) + else + lockY = false + + desiredGpsY = nil + end + end +end + +local lastUpKeyPressed = 0 +local function keyboardInputLoop() + while true do + local data = {os.pullEvent()} + + if data[1] == "key_up" then + pressedKeys[data[2]] = false + + -- Toggle flight logic + if doubleTapUpToToggle and doubleTapUpToToggle > 0 then + if data[2] == upKey then + lastUpKeyPressed = os.epoch("utc") + end + end + elseif data[1] == "key" then + -- Toggle flight logic + if doubleTapUpToToggle and doubleTapUpToToggle > 0 then + if data[2] == upKey then + local now = os.epoch("utc") + if now - doubleTapUpToToggle * 1000 < lastUpKeyPressed then + flightActive = not flightActive + lastUpKeyPressed = 0 + end + end + elseif data[2] == toggleFlightKey and not pressedKeys[data[2]] then + flightActive = not flightActive + end + + pressedKeys[data[2]] = true + end + end +end + +local overridesRequireGPS = false +local function updateGpsLoop() + while true do + if lockY or overridesRequireGPS then + overridesRequireGPS = false + + gpsX, gpsY, gpsZ = gps.locate() + if not gpsX or gpsX ~= gpsX then -- NaN(i)? + gpsX = nil + gpsY = nil + gpsZ = nil + elseif not desiredGpsY then + desiredGpsY = gpsY + end + end + sleep(0.2) -- We don't need to spam the GPS so hard + end +end + +---Gets the current estimated coords, can return nil when calling for the first couple time or gps failed +---@return number | nil x +---@return number | nil y +---@return number | nil z +local function getCoords() + overridesRequireGPS = true + return gpsX, gpsY, gpsZ +end + +local function doFlyloop() + parallel.waitForAny(flyLoop, keyboardInputLoop, updateGpsLoop) +end + +local args = {...} +if #args > 0 then + print("running as flight library (args detected), call doFlightLoop to start flying!") + + ---@param overrideFunc (fun(defaultIsFlightActive: boolean, playerMeta: table): boolean) | nil + local function setIsFlightActiveOverride(overrideFunc) + isFlightActiveOverride = overrideFunc or defaultIsFlightActiveOverride + end + ---@param overrideFunc (fun(defaultSpeed: number, playerMeta: table): number) | nil + local function setGetSpeedOverride(overrideFunc) + getSpeedOverride = overrideFunc or defaultGetSpeedOverride + end + ---@param overrideFunc (fun(defaultDesiredX: number, defaultDesiredY: number, defaultDesiredZ: number, playerMeta: table): number, number, number) | nil + local function setGetDesiredDirOverride(overrideFunc) + getDesiredDirOverride = overrideFunc or defaultGetDesiredDirOverride + end + ---@param overrideFunc (fun(defaultMotionX: number, defaultMotionY: number, defaultMotionZ: number, playerMeta: table): number, number, number) | nil + local function setMotionOverride(overrideFunc) + motionOverride = overrideFunc or defaultMotionOverride + end + + ---@param newFlightActive boolean + local function setBaseFlightActive(newFlightActive) + flightActive = newFlightActive + end + + return { + doFlyloop = doFlyloop, + getCoords = getCoords, + + pressedKeys = pressedKeys, + + setBaseFlightActive = setBaseFlightActive, + + setIsFlightActiveOverride = setIsFlightActiveOverride, + setGetSpeedOverride = setGetSpeedOverride, + setGetDesiredDirOverride = setGetDesiredDirOverride, + setMotionOverride = setMotionOverride, + } +else + doFlyloop() +end + +-- Created by jasper_185 diff --git a/mpp.lua b/mpp.lua new file mode 100644 index 0000000..997af90 --- /dev/null +++ b/mpp.lua @@ -0,0 +1,56 @@ +local connectionUrl = "wss://mppclone.com"; + +local ws, err = http.websocket(connectionUrl) + +if not ws then + return printError(err) +end + +function send(data) + local message = {} + message[1] = data; + ws.send(textutils.serialiseJSON(message)); +end + +local function tSender() + while true do + os.sleep(15) + send({ + m = "t" + }) + end +end +local function pollWebsocket() + while true do + + local _, url, response, isBinary = os.pullEvent("websocket_message"); + if url == connectionUrl then + local json = textutils.unserializeJSON(response); + if json[1].m == "b" then + print("Connected to MPP!"); + send({ + m = "hi", + token = "" + }) + end + if json[1].m == "hi" then + print("Authenicated!") + send({ + m = "ch", + _id = "The Roleplay Room" + }) + end + if json[1].m == "a" then + print("["..json[1].p._id:sub(0, 6).."] "..json[1].p.name..": "..json[1].a) + + end + local g = json[1].m == "m" or json[1].m == "n" + if not g then + print(json[1].m) + end + end + + end +end + +parallel.waitForAny(tSender,pollWebsocket) diff --git a/previous-flight.lua b/previous-flight.lua new file mode 100644 index 0000000..d5f5968 --- /dev/null +++ b/previous-flight.lua @@ -0,0 +1,250 @@ +-- Elytra Flight module for Minit +-- Copyright (C) 2023 AlexDevs +-- This software is licensed under the MIT license. + +local module = { + name = "flight", +} + +local locale = { + direction = "%s : %d", -- windrose : pitch + altitude = "Y: %d", + yMotion = "Y: %.2f", + speed = "%.2f m/s", +} + +local icons = { + empty = "air", + fly = "elytra", + launch = "firework_rocket", + slow = "feather", + disabled = "barrier", + propelling = "blaze_powder" +} + +-- Default variables. Use settings file to change values. +settings.define("elytra.power", { + description = "Propeller power", + type = "number", + default = 2, +}) + +settings.define("elytra.pitch", { + description = "Propeller pitch treshold for automatic mode", + type = "number", + default = 0, +}) + +settings.define("elytra.scale", { + description = "Scale of UI", + type = "number", + default = 0.6, +}) + +settings.define("elytra.sounds", { + description = "Enable sound effects", + type = "boolean", + default = true, +}) + +settings.define("elytra.manual", { + description = "Press SHIFT while flying to propel", + type = "boolean", + default = true, +}) + +settings.define("elytra.softfall.enable", { + description = "Enable softfall", + type = "boolean", + default = true, +}) + +settings.define("elytra.softfall.basepower", { + description = "Base power for soft fall", + type = "number", + default = 0.75, +}) + +settings.define("elytra.softfall.trigger", { + description = "Minimum negative Y motion required to trigger soft fall. USE NEGATIVE NUMBERS", + type = "number", + default = -1, +}) + +local neural, speaker +local canvas, container +local screen = {} +local currentY = 0 + +local function getRoseWind(degrees) + degrees = degrees + 180 + local directions = { "N", "NE", "E", "SE", "S", "SW", "W", "NW" } + local index = math.floor((degrees / 45) + 0.5) % 8 + return directions[index + 1] +end + +local function createScreen() + canvas = neural.canvas() + screen = {} + + if container then + pcall(container.clear) + end + + container = canvas.addGroup({ 1, 1 }) + + local scale = settings.get("elytra.scale") + local x, y = 25, math.ceil(9 * scale) + + screen.icon = container.addItem({ 0, 1 }, "elytra") + screen.speed = container.addText({ x, y * 1 }, "") + screen.speed.setScale(scale) + + screen.altitude = container.addText({ x, y * 2 }, "") + screen.altitude.setScale(scale) + + screen.direction = container.addText({ x, y * 3 }, "") + screen.direction.setScale(scale) +end + +local function updateScreen(meta) + if not canvas or not container then + createScreen() + end + + local mVector = vector.new(meta.deltaPosX, meta.deltaPosY, meta.deltaPosZ) + local speed = mVector:length() * 20 + screen.speed.setText(string.format(locale.speed, speed)) + screen.direction.setText(string.format(locale.direction, getRoseWind(meta.yaw), meta.pitch)) + screen.altitude.setText(string.format(locale.altitude, currentY)) +end + +local icon = icons.empty +local function toggleScreen(show) + local alpha = show and 0xff or 0 + screen.icon.setItem(show and icon or icons.empty) + screen.speed.setAlpha(alpha) + screen.altitude.setAlpha(alpha) + screen.direction.setAlpha(alpha) +end + +local function setIcon(newIcon) + icon = newIcon + screen.icon.setItem(newIcon) +end + +local function playSound(sound, volume, pitch) + if speaker and settings.get("elytra.sounds") then + speaker.playSound(sound, volume, pitch) + end +end + +local function launch(yaw, pitch, power) + power = power or settings.get("elytra.power") + neural.launch(yaw, pitch, math.min(power, 4)) +end + +local function launchUp(power) + launch(0, -90, power) +end + +local function softFall(motionY) + motionY = motionY or 0 + launchUp(-motionY + settings.get("elytra.softfall.basepower")) + playSound("minecraft:entity.phantom.flap", 1, 1) +end + +local function canPropel(meta) + return settings.get("elytra.manual") and meta.isSneaking or not meta.isSneaking +end + +local function propel(meta, icon) + neural.launch(meta.yaw, meta.pitch, settings.get("elytra.power")) + playSound("minecraft:entity.fishing_bobber.throw", 0.4, 1) + + if icon then + setIcon(icon) + end +end + +local function gpsLocate() + while true do + local x, y, z = gps.locate() + if x then + currentY = y + end + sleep(0.5) + end +end + +function module.init(init) + init.addTask(gpsLocate) +end + +function module.setup(ni) + neural = ni + speaker = peripheral.find("speaker") + + createScreen() + toggleScreen(false) +end + +function module.update(meta) + if not meta.isElytraFlying then + if meta.isSneaking then + if meta.pitch == -90 then + setIcon(icons.launch) + launchUp(2) + else + setIcon(icons.disabled) + end + return + end + + if meta.deltaPosY < settings.get("elytra.softfall.trigger") and settings.get("elytra.softfall.enable") then + softFall(meta.motionY) + setIcon(icons.slow) + return + end + + toggleScreen(false) + return + end + + toggleScreen(true) + updateScreen(meta) + + local pitch = meta.pitch + local yaw = meta.yaw + + if not canPropel(meta) then + setIcon(icons.disabled) + return + end + + if settings.get("elytra.manual") then + if meta.isSneaking then + propel(meta, icons.propelling) + else + if meta.deltaPosY < settings.get("elytra.softfall.trigger") and settings.get("elytra.softfall.enable") then + softFall(meta.motionY) + setIcon(icons.slow) + else + setIcon(icons.fly) + end + end + else + if pitch > settings.get("elytra.pitch") then + if meta.deltaPosY < settings.get("elytra.softfall.trigger") and settings.get("elytra.softfall.enable") then + softFall(meta.motionY) + setIcon(icons.slow) + end + return + end + + setIcon(icons.fly) + propel(meta, false) + end +end + +return module \ No newline at end of file diff --git a/sha256.lua b/sha256.lua new file mode 100644 index 0000000..26893fc --- /dev/null +++ b/sha256.lua @@ -0,0 +1,3 @@ +local g = string.gsub +sha256 = loadstring(g(g(g(g(g(g(g(g('Sa=XbandSb=XbxWSc=XlshiftSd=unpackSe=2^32SYf(g,h)Si=g/2^hSj=i%1Ui-j+j*eVSYk(l,m)Sn=l/2^mUn-n%1VSo={0x6a09e667Tbb67ae85T3c6ef372Ta54ff53aT510e527fT9b05688cT1f83d9abT5be0cd19}Sp={0x428a2f98T71374491Tb5c0fbcfTe9b5dba5T3956c25bT59f111f1T923f82a4Tab1c5ed5Td807aa98T12835b01T243185beT550c7dc3T72be5d74T80deb1feT9bdc06a7Tc19bf174Te49b69c1Tefbe4786T0fc19dc6T240ca1ccT2de92c6fT4a7484aaT5cb0a9dcT76f988daT983e5152Ta831c66dTb00327c8Tbf597fc7Tc6e00bf3Td5a79147T06ca6351T14292967T27b70a85T2e1b2138T4d2c6dfcT53380d13T650a7354T766a0abbT81c2c92eT92722c85Ta2bfe8a1Ta81a664bTc24b8b70Tc76c51a3Td192e819Td6990624Tf40e3585T106aa070T19a4c116T1e376c08T2748774cT34b0bcb5T391c0cb3T4ed8aa4aT5b9cca4fT682e6ff3T748f82eeT78a5636fT84c87814T8cc70208T90befffaTa4506cebTbef9a3f7Tc67178f2}SYq(r,q)if e-1-r[1]