Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- turtle_server with local and remote command input
- -- Auto-detect and open wireless modem
- local opened = false
- for _, side in ipairs({"left", "right", "top", "bottom", "back"}) do
- if peripheral.getType(side) == "modem" and peripheral.call(side, "isWireless") then
- rednet.open(side)
- print("Opened modem on " .. side)
- opened = true
- break
- end
- end
- if not opened then
- print("No wireless modem found.")
- end
- local password = "test" -- set to "" to disable
- local secured = password ~= ""
- local authenticatedClients = {} -- stores senderIDs who passed auth
- local selected_slot = turtle.getSelectedSlot()
- local commandLog = {} -- logs movement for return_home
- local remoteNames = {} -- senderID -> name
- local localName = "turtle"
- local awaitingInput = false
- -- Position tracking
- local position = { x = 0, y = 0, z = 0 }
- local facing = 0 -- 0 = north, 1 = east, 2 = south, 3 = west
- local home = { x = 0, y = 0, z = 0, facing = 0 }
- -- Direction vectors
- local directions = {
- [0] = { x = 0, z = -1 }, -- North
- [1] = { x = 1, z = 0 }, -- East
- [2] = { x = 0, z = 1 }, -- South
- [3] = { x = -1, z = 0 } -- West
- }
- print("Turtle is online and listening...")
- if secured then print("password is: " .. password) end
- -- Helper functions
- local function repeatAction(amount, action, direction)
- amount = tonumber(amount) or 1
- for i = 1, amount do
- local success, result = pcall(action)
- if success and result then
- if direction == "forward" then
- table.insert(commandLog, "back")
- elseif direction == "back" then
- table.insert(commandLog, "forward")
- elseif direction == "up" then
- table.insert(commandLog, "down")
- elseif direction == "down" then
- table.insert(commandLog, "up")
- elseif direction == "right" then
- table.insert(commandLog, "left")
- elseif direction == "left" then
- table.insert(commandLog, "right")
- end
- elseif not result then
- return false, "Blocked: " .. direction
- elseif not success then
- return false, "Error: " .. tostring(result)
- end
- end
- return true
- end
- local function randomObjectFromTable(t)
- return t[math.random(1, #t)]
- end
- -- [NEW] Core command handler (shared by both local and remote input)
- local function handleCommand(input, senderID)
- local args = {}
- for word in string.gmatch(input, "%S+") do
- table.insert(args, word)
- end
- local command = args[1]
- local success, err, replyMessage
- if command == "forward" then
- success, err = repeatAction(args[2], turtle.forward, "forward")
- replyMessage = success and "Moved forward" or ("Error moving forward: " .. tostring(err))
- elseif command == "back" then
- success, err = repeatAction(args[2], turtle.back, "back")
- replyMessage = success and "Moved back" or ("Error moving back: " .. tostring(err))
- elseif command == "left" then
- success, err = repeatAction(args[2], turtle.turnLeft, "left")
- replyMessage = success and "Turned left" or ("Error turning left: " .. tostring(err))
- elseif command == "right" then
- success, err = repeatAction(args[2], turtle.turnRight, "right")
- replyMessage = success and "Turned right" or ("Error turning right: " .. tostring(err))
- elseif command == "180" then
- local maybe = {true, false}
- if randomObjectFromTable(maybe) then
- success, err = repeatAction(2, turtle.turnLeft, "left")
- replyMessage = success and "Turned 180 degress left" or ("Error turning 180 degress left: " .. tostring(err))
- else
- success, err = repeatAction(2, turtle.turnRight, "right")
- replyMessage = success and "Turned 180 degress right" or ("Error turning 180 degress right: " .. tostring(err))
- end
- elseif command == "up" then
- success, err = repeatAction(args[2], turtle.up, "up")
- replyMessage = success and "Moved up" or ("Error moving up: " .. tostring(err))
- elseif command == "down" then
- success, err = repeatAction(args[2], turtle.down, "down")
- replyMessage = success and "Moved down" or ("Error moving down: " .. tostring(err))
- elseif command == "dig" then
- local right = turtle.getEquippedRight()
- if right and right.name ~= "minecraft:diamond_pickaxe" then
- local selected_slot = turtle.getSelectedSlot()
- turtle.select(16)
- turtle.equipRight()
- turtle.select(selected_slot)
- end
- local dir = args[2] or "forward"
- if dir == "up" then
- success, err = pcall(turtle.digUp)
- replyMessage = success and "Dug up" or ("Error digging up: " .. tostring(err))
- elseif dir == "down" then
- success, err = pcall(turtle.digDown)
- replyMessage = success and "Dug down" or ("Error digging down: " .. tostring(err))
- else
- success, err = pcall(turtle.dig)
- replyMessage = success and "Dug forward" or ("Error digging forward: " .. tostring(err))
- end
- elseif command == "attack" then
- local right = turtle.getEquippedRight()
- if right and right.name ~= "minecraft:diamond_sword" then
- local selected_slot = turtle.getSelectedSlot()
- turtle.select(16)
- turtle.equipRight()
- turtle.select(selected_slot)
- end
- local dir = args[2] or "forward"
- if dir == "up" then
- success, err = pcall(turtle.attackUp)
- replyMessage = success and "Attacked up" or ("Error attacking up: " .. tostring(err))
- elseif dir == "down" then
- success, err = pcall(turtle.attackDown)
- replyMessage = success and "Attacked down" or ("Error attacking down: " .. tostring(err))
- else
- success, err = pcall(turtle.attack)
- replyMessage = success and "Attacked forward" or ("Error attacking forward: " .. tostring(err))
- end
- elseif command == "place" then
- local dir = args[2] or "forward"
- if dir == "up" then
- success, err = pcall(turtle.placeUp)
- replyMessage = success and "Placed up" or ("Error placing up: " .. tostring(err))
- elseif dir == "down" then
- success, err = pcall(turtle.placeDown)
- replyMessage = success and "Placed down" or ("Error placing down: " .. tostring(err))
- else
- success, err = pcall(turtle.place)
- replyMessage = success and "Placed forward" or ("Error placing forward: " .. tostring(err))
- end
- elseif (command == "select" or command == "slot") and args[2] then
- if args[2] == "help" then
- replyMessage = "Use select/slot <1-15>"
- else
- local slot = tonumber(args[2])
- if slot and slot >= 1 and slot <= 15 then
- selected_slot = slot
- turtle.select(selected_slot)
- replyMessage = "Selected slot " .. slot
- else
- replyMessage = "Invalid slot number."
- end
- end
- elseif command == "name" and args[2] then
- local newName = table.concat(args, " ", 2)
- if senderID then
- remoteNames[senderID] = newName
- replyMessage = "Name set to '" .. newName .. "'"
- else
- localName = newName
- replyMessage = "Local name set to '" .. newName .. "'"
- end
- elseif command == "whoami" then
- if senderID then
- local name = remoteNames[senderID]
- if name then
- replyMessage = "You are named '" .. name .. "'"
- else
- replyMessage = "You are senderID #" .. tostring(senderID)
- end
- else
- replyMessage = "You are named '" .. localName .. "'"
- end
- elseif command == "print" and args[2] then
- local message = table.concat(args, " ", 2)
- replyMessage = message
- elseif command == "set_home" then
- commandLog = {}
- replyMessage = "Set home."
- elseif command == "return_home" or command == "home" then
- for i = #commandLog, 1, -1 do
- local reverseCmd = commandLog[i]
- handleCommand(reverseCmd, nil) -- simulate local call
- end
- commandLog = {} -- optional: clear log after returning
- replyMessage = "Returned home."
- elseif command == "dump" then
- local selected_slot = turtle.getSelectedSlot()
- local dir = args[2] or "down"
- local dropped = 0
- for slot = 1, 15 do -- skip slot 16
- turtle.select(slot)
- local item = turtle.getItemDetail()
- if item then
- local success
- if dir == "up" then
- success = turtle.dropUp()
- elseif dir == "forward" then
- success = turtle.drop()
- else
- success = turtle.dropDown()
- end
- if success then
- dropped = dropped + 1
- end
- end
- end
- turtle.select(selected_slot)
- turtle.select(selected_slot or 1)
- replyMessage = "Dropped " .. dropped .. " item stacks to the " .. dir
- elseif command == "exit" or command == off then
- replyMessage = "Shutting down on command."
- if senderID then rednet.send(senderID, replyMessage) end
- print(replyMessage)
- os.shutdown() -- Immediate exit
- else
- replyMessage = "Unknown command."
- end
- if senderID and replyMessage then
- rednet.send(senderID, replyMessage)
- elseif not senderID then
- print("< " .. replyMessage)
- if awaitingInput then
- local x, y = term.getCursorPos()
- local w, h = term.getSize()
- term.setCursorPos(1, y)
- term.clearLine()
- term.write(localName .. "> ")
- end
- end
- end
- -- [NEW] Thread 1: Remote command listener
- local function listenRednet()
- while true do
- local senderID, message = rednet.receive()
- if type(message) == "string" then
- local displayName = remoteNames[senderID] or tostring(senderID)
- if remoteNames[senderID] then
- print("Remote message from " .. displayName .. " (" .. senderID .. "): " .. message)
- if awaitingInput then
- local x, y = term.getCursorPos()
- local w, h = term.getSize()
- term.setCursorPos(1, y)
- term.clearLine()
- term.write(localName .. "> ")
- end
- else
- print("Remote message from " .. displayName .. ": " .. message)
- if awaitingInput then
- local x, y = term.getCursorPos()
- local w, h = term.getSize()
- term.setCursorPos(1, y)
- term.clearLine()
- term.write(localName .. "> ")
- end
- end
- if secured and not authenticatedClients[senderID] then
- -- Require authentication first
- local args = {}
- for word in string.gmatch(message, "%S+") do
- table.insert(args, word)
- end
- if args[1] == "auth" and args[2] == password then
- authenticatedClients[senderID] = true
- rednet.send(senderID, "Authentication successful.")
- print("Client " .. senderID .. " authenticated.")
- if awaitingInput then
- local x, y = term.getCursorPos()
- local w, h = term.getSize()
- term.setCursorPos(1, y)
- term.clearLine()
- term.write(localName .. "> ")
- end
- else
- rednet.send(senderID, "Please authenticate with: auth <password>")
- print("Blocked command from unauthenticated client " .. senderID)
- if awaitingInput then
- local x, y = term.getCursorPos()
- local w, h = term.getSize()
- term.setCursorPos(1, y)
- term.clearLine()
- term.write(localName .. "> ")
- end
- end
- else
- -- Already authenticated
- handleCommand(message, senderID)
- end
- end
- end
- end
- -- [NEW] Thread 2: Local command listener
- local function listenKeyboard()
- while true do
- term.write(localName .. "> ")
- awaitingInput = true
- local input = read()
- awaitingInput = false
- handleCommand(input, nil)
- end
- end
- -- [NEW] Run both listeners simultaneously
- parallel.waitForAny(listenRednet, listenKeyboard)
Advertisement
Add Comment
Please, Sign In to add comment