1
Fork 0

authorized digging

This commit is contained in:
Andy Killorin 2023-12-17 15:28:18 -06:00
parent 42eff1af2b
commit 96a8de6858
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 152 additions and 59 deletions

View file

@ -1,3 +1,38 @@
local port = "48228"
local endpoint = "http://" .. ipaddr .. ":" .. port
local function update(args)
if args[1] == "nested" then
-- no exec = stack overflow
return false
end
local req = http.get(endpoint .. "/turtle/client.lua")
if not req then
os.reboot()
end
local update = req.readAll()
req.close()
fs.delete("startup-backup")
if fs.exists("/startup") then
-- pcall does not work with cc fs
fs.move("startup", "startup-backup")
end
local startup = fs.open("startup", "w")
startup.write(update)
startup.close()
shell.run("startup", "nested")
return true
end
local function cycle(func, n)
for i = 1, n, 1 do
if not func() then
return false
end
end
return true
end
if not ipaddr then
if fs.exists("/disk/ip") then
local ipfile = fs.open("/disk/ip")
@ -9,10 +44,6 @@ if not ipaddr then
end
end
local port = "48228"
local endpoint = "http://" .. ipaddr .. ":" .. port
local idfile = fs.open("id", "r")
local id = nil
@ -60,41 +91,54 @@ end
repeat
print(command)
local args = nil
if type(command) == "table" then
command, args = pairs(command)(command)
end
local ret = nil
if command == "Wait" then
sleep(5)
sleep(args)
elseif command == "Forward" then
turtle.forward()
ret = cycle(turtle.forward, args)
elseif command == "Backward" then
turtle.back()
ret = cycle(turtle.back, args)
elseif command == "Left" then
turtle.turnLeft()
ret = turtle.turnLeft()
elseif command == "Right" then
turtle.turnRight()
ret = turtle.turnRight()
elseif command == "Up" then
turtle.up()
ret = cycle(turtle.up, args)
elseif command == "Down" then
turtle.down()
ret = cycle(turtle.down, args)
elseif command == "Dig" then
ret = turtle.dig()
elseif command == "DigUp" then
ret = turtle.digUp()
elseif command == "DigDown" then
ret = turtle.digDown()
elseif command == "ItemInfo" then
ret = { Item = turtle.getItemDetail(args) }
elseif command == "Update" then
args = {...}
if args[1] == "nested" then
-- no exec = stack overflow
if not update({...}) then
break
end
local req = http.get(endpoint .. "/turtle/client.lua")
if not req then
os.reboot()
end
local update = req.readAll()
req.close()
fs.delete("startup-backup")
if fs.exists("/startup") then
-- pcall does not work with cc fs
fs.move("startup", "startup-backup")
local ret_table = nil
if type(ret) == "boolean" then
if ret then
ret_table = "Success"
else
ret_table = "Failure"
end
local startup = fs.open("startup", "w")
startup.write(update)
startup.close()
shell.run("startup", "nested")
else
ret_table = ret
end
if not ret_table then
ret_table = "None"
end
local ahead = "minecraft:air"
@ -119,8 +163,10 @@ repeat
fuel = turtle.getFuelLevel(),
ahead = ahead,
above = above,
below = below
below = below,
ret = ret_table,
}
print(info.ret)
local rsp = http.post(
endpoint .. "/turtle/" .. id .. "/update" ,

View file

@ -10,7 +10,7 @@ use rstar::{self, AABB};
mod names;
use names::Name;
use tokio::{sync::{Mutex, RwLock, watch}, signal};
use tokio::{sync::{Mutex, RwLock, watch::{self, Sender}}, signal};
use serde::{Serialize, Deserialize};
use const_format::formatcp;
use hyper_util::rt::TokioIo;
@ -116,14 +116,18 @@ async fn main() -> Result<(), Error> {
.route("/flush", get(flush))
.with_state(state.clone());
serve(server).await;
let server = serve(server).await;
println!("writing");
write_to_disk(state).await?;
server.closed().await;
Ok(())
}
async fn serve(serv: Router) {
async fn serve(server: Router) -> Sender<()> {
let listener = tokio::net::TcpListener::bind("0.0.0.0:48228").await.unwrap();
let (close_tx, close_rx) = watch::channel(());
@ -139,7 +143,7 @@ async fn serve(serv: Router) {
}
};
let tower = serv.clone();
let tower = server.clone();
let close_rx = close_rx.clone();
tokio::spawn(async move {
@ -175,7 +179,7 @@ async fn serve(serv: Router) {
drop(listener);
close_tx.closed().await;
close_tx
}
async fn write_to_disk(state: SharedControl) -> anyhow::Result<()> {
@ -259,13 +263,14 @@ async fn command(
) -> Json<TurtleCommand> {
let mut state = &mut state.write().await;
println!("{:?}", &req);
if id as usize > state.turtles.len() {
return Json(TurtleCommand::Update);
}
Json(
process_turtle_update(id, &mut state, req).unwrap_or(TurtleCommand::Update),
)
}
@ -317,9 +322,18 @@ fn process_turtle_update(
if let Some(goal) = turtle.goal {
// TODO: memoize this whenever we aren't digging
let route = route(turtle.position, goal, world);
let route = route(turtle.position, goal, world).unwrap();
println!("route: {:?}", route);
let next_move = difference(route[0], route[1]).unwrap();
let mut next_move = difference(route[0], route[1]).unwrap();
if world.locate_at_point(&route[1].0.into()).is_some_and(|b| b.name != "minecraft:air") {
next_move = match next_move {
TurtleCommand::Up(_) => TurtleCommand::DigUp,
TurtleCommand::Down(_) => TurtleCommand::DigDown,
TurtleCommand::Forward(_) => TurtleCommand::Dig,
_ => next_move,
}
}
turtle.queued_movement = next_move.delta(turtle.position.1);
match next_move {
TurtleCommand::Left => turtle.position.1 = turtle.position.1.left(),
@ -329,7 +343,7 @@ fn process_turtle_update(
return Ok(next_move);
}
Ok(TurtleCommand::Wait)
Ok(TurtleCommand::Wait(3))
}
#[derive(Serialize, Deserialize)]
@ -354,13 +368,13 @@ fn difference(from: Position, to: Position) -> Option<TurtleCommand> {
}
} else if to.1 == from.1 {
if to.0 == from.0 + from.1.unit() {
Some(Forward)
Some(Forward(1))
} else if to.0 == from.0 - from.1.unit() {
Some(Backward)
Some(Backward(1))
} else if to.0 == from.0 + Vec3::y() {
Some(Up)
Some(Up(1))
} else if to.0 == from.0 - Vec3::y() {
Some(Down)
Some(Down(1))
} else {
None
}
@ -395,41 +409,66 @@ enum TurtleMineMethod {
#[derive(Serialize, Deserialize, Clone)]
enum TurtleCommand {
Wait,
Forward,
Backward,
Up,
Down,
Wait(u32),
Forward(u32),
Backward(u32),
Up(u32),
Down(u32),
Left,
Right,
Dig,
DigUp,
DigDown,
TakeInventory,
PlaceUp,
Place,
PlaceDown,
/// Count
DropFront(u32),
DropUp(u32),
DropDown(u32),
Select(u32),
/// Slot in inventory
ItemInfo(u32),
Update,
Poweroff,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
struct InventorySlot {
name: String,
count: u32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
enum TurtleCommandResponse {
None,
Success,
Failure,
Item(InventorySlot),
Inventory(Vec<InventorySlot>),
}
impl TurtleCommand {
fn delta(&self, direction: Direction) -> Vec3 {
let dir = direction.unit();
match self {
TurtleCommand::Forward => dir,
TurtleCommand::Backward => -dir,
TurtleCommand::Up => Vec3::y(),
TurtleCommand::Down => -Vec3::y(),
TurtleCommand::Forward(count) => dir * *count as i32,
TurtleCommand::Backward(count) => -dir * *count as i32,
TurtleCommand::Up(count) => Vec3::y() * *count as i32,
TurtleCommand::Down(count) => -Vec3::y() * *count as i32,
_ => Vec3::zeros(),
}
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
struct TurtleUpdate {
fuel: usize,
/// Block name
ahead: String,
above: String,
below: String,
ret: TurtleCommandResponse,
}
#[derive(Serialize, Deserialize)]

View file

@ -5,9 +5,15 @@ use crate::{blocks::{World, Block}, Position, Direction};
use super::Vec3;
pub fn route(from: Position, to: Position, world: &World) -> Vec<Position> {
pub fn route(from: Position, to: Position, world: &World) -> Option<Vec<Position>> {
// attempt at not crashing by looking infinitely into the abyss
if world.locate_at_point(&to.0.into())
.is_some_and(|b| difficulty(&b.name).is_none()) {
return None;
}
let route = astar(&from, move |p| {next(p, world)} , |p1| {(p1.0 - &to.0).abs().sum() as u32}, |p| {p == &to}).unwrap();
route.0
Some(route.0)
}
fn next(from: &Position, world: &World) -> Vec<(Position, u32)> {
@ -24,8 +30,8 @@ fn next(from: &Position, world: &World) -> Vec<(Position, u32)> {
let ahead = from.0 + from.1.unit();
insert(&mut vec, ahead, from.1, world, UNKNOWN);
let behind = from.0 - from.1.unit();
insert(&mut vec, behind, from.1, world, None);
//let behind = from.0 - from.1.unit();
//insert(&mut vec, behind, from.1, world, None);
let above = from.0 + Vec3::y();
insert(&mut vec, above, from.1, world,UNKNOWN);
@ -37,10 +43,12 @@ fn next(from: &Position, world: &World) -> Vec<(Position, u32)> {
}
/// Blocks that are fine to tunnel through
const GARBAGE: [&str; 3] = [
const GARBAGE: [&str; 5] = [
"minecraft:stone",
"minecraft:dirt",
"minecraft:andesite",
"minecraft:sand",
"minecraft:gravel",
];
/// time taken to go through uncharted territory (in turtle. calls)
@ -49,6 +57,6 @@ const UNKNOWN: Option<u32> = Some(2);
// time to go somewhere
fn difficulty(name: &str) -> Option<u32> {
if name == "minecraft:air" { return Some(1) };
//if GARBAGE.contains(&name) { return Some(2)};
if GARBAGE.contains(&name) { return Some(2)};
None
}