authorized digging
This commit is contained in:
parent
42eff1af2b
commit
96a8de6858
3 changed files with 152 additions and 59 deletions
|
@ -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 not ipaddr then
|
||||||
if fs.exists("/disk/ip") then
|
if fs.exists("/disk/ip") then
|
||||||
local ipfile = fs.open("/disk/ip")
|
local ipfile = fs.open("/disk/ip")
|
||||||
|
@ -9,10 +44,6 @@ if not ipaddr then
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local port = "48228"
|
|
||||||
|
|
||||||
local endpoint = "http://" .. ipaddr .. ":" .. port
|
|
||||||
|
|
||||||
local idfile = fs.open("id", "r")
|
local idfile = fs.open("id", "r")
|
||||||
|
|
||||||
local id = nil
|
local id = nil
|
||||||
|
@ -60,41 +91,54 @@ end
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
print(command)
|
print(command)
|
||||||
|
local args = nil
|
||||||
|
if type(command) == "table" then
|
||||||
|
command, args = pairs(command)(command)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ret = nil
|
||||||
|
|
||||||
if command == "Wait" then
|
if command == "Wait" then
|
||||||
sleep(5)
|
sleep(args)
|
||||||
elseif command == "Forward" then
|
elseif command == "Forward" then
|
||||||
turtle.forward()
|
ret = cycle(turtle.forward, args)
|
||||||
elseif command == "Backward" then
|
elseif command == "Backward" then
|
||||||
turtle.back()
|
ret = cycle(turtle.back, args)
|
||||||
elseif command == "Left" then
|
elseif command == "Left" then
|
||||||
turtle.turnLeft()
|
ret = turtle.turnLeft()
|
||||||
elseif command == "Right" then
|
elseif command == "Right" then
|
||||||
turtle.turnRight()
|
ret = turtle.turnRight()
|
||||||
elseif command == "Up" then
|
elseif command == "Up" then
|
||||||
turtle.up()
|
ret = cycle(turtle.up, args)
|
||||||
elseif command == "Down" then
|
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
|
elseif command == "Update" then
|
||||||
args = {...}
|
if not update({...}) then
|
||||||
if args[1] == "nested" then
|
|
||||||
-- no exec = stack overflow
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
local req = http.get(endpoint .. "/turtle/client.lua")
|
end
|
||||||
if not req then
|
|
||||||
os.reboot()
|
local ret_table = nil
|
||||||
|
if type(ret) == "boolean" then
|
||||||
|
if ret then
|
||||||
|
ret_table = "Success"
|
||||||
|
else
|
||||||
|
ret_table = "Failure"
|
||||||
end
|
end
|
||||||
local update = req.readAll()
|
else
|
||||||
req.close()
|
ret_table = ret
|
||||||
fs.delete("startup-backup")
|
end
|
||||||
if fs.exists("/startup") then
|
|
||||||
-- pcall does not work with cc fs
|
if not ret_table then
|
||||||
fs.move("startup", "startup-backup")
|
ret_table = "None"
|
||||||
end
|
|
||||||
local startup = fs.open("startup", "w")
|
|
||||||
startup.write(update)
|
|
||||||
startup.close()
|
|
||||||
shell.run("startup", "nested")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local ahead = "minecraft:air"
|
local ahead = "minecraft:air"
|
||||||
|
@ -119,8 +163,10 @@ repeat
|
||||||
fuel = turtle.getFuelLevel(),
|
fuel = turtle.getFuelLevel(),
|
||||||
ahead = ahead,
|
ahead = ahead,
|
||||||
above = above,
|
above = above,
|
||||||
below = below
|
below = below,
|
||||||
|
ret = ret_table,
|
||||||
}
|
}
|
||||||
|
print(info.ret)
|
||||||
|
|
||||||
local rsp = http.post(
|
local rsp = http.post(
|
||||||
endpoint .. "/turtle/" .. id .. "/update" ,
|
endpoint .. "/turtle/" .. id .. "/update" ,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rstar::{self, AABB};
|
||||||
|
|
||||||
mod names;
|
mod names;
|
||||||
use names::Name;
|
use names::Name;
|
||||||
use tokio::{sync::{Mutex, RwLock, watch}, signal};
|
use tokio::{sync::{Mutex, RwLock, watch::{self, Sender}}, signal};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use const_format::formatcp;
|
use const_format::formatcp;
|
||||||
use hyper_util::rt::TokioIo;
|
use hyper_util::rt::TokioIo;
|
||||||
|
@ -116,14 +116,18 @@ async fn main() -> Result<(), Error> {
|
||||||
.route("/flush", get(flush))
|
.route("/flush", get(flush))
|
||||||
.with_state(state.clone());
|
.with_state(state.clone());
|
||||||
|
|
||||||
serve(server).await;
|
|
||||||
|
|
||||||
|
let server = serve(server).await;
|
||||||
|
|
||||||
|
println!("writing");
|
||||||
write_to_disk(state).await?;
|
write_to_disk(state).await?;
|
||||||
|
|
||||||
|
server.closed().await;
|
||||||
|
|
||||||
Ok(())
|
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 listener = tokio::net::TcpListener::bind("0.0.0.0:48228").await.unwrap();
|
||||||
|
|
||||||
let (close_tx, close_rx) = watch::channel(());
|
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();
|
let close_rx = close_rx.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
@ -175,7 +179,7 @@ async fn serve(serv: Router) {
|
||||||
|
|
||||||
drop(listener);
|
drop(listener);
|
||||||
|
|
||||||
close_tx.closed().await;
|
close_tx
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_to_disk(state: SharedControl) -> anyhow::Result<()> {
|
async fn write_to_disk(state: SharedControl) -> anyhow::Result<()> {
|
||||||
|
@ -259,13 +263,14 @@ async fn command(
|
||||||
) -> Json<TurtleCommand> {
|
) -> Json<TurtleCommand> {
|
||||||
let mut state = &mut state.write().await;
|
let mut state = &mut state.write().await;
|
||||||
|
|
||||||
|
println!("{:?}", &req);
|
||||||
|
|
||||||
if id as usize > state.turtles.len() {
|
if id as usize > state.turtles.len() {
|
||||||
return Json(TurtleCommand::Update);
|
return Json(TurtleCommand::Update);
|
||||||
}
|
}
|
||||||
|
|
||||||
Json(
|
Json(
|
||||||
process_turtle_update(id, &mut state, req).unwrap_or(TurtleCommand::Update),
|
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 {
|
if let Some(goal) = turtle.goal {
|
||||||
// TODO: memoize this whenever we aren't digging
|
// 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);
|
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);
|
turtle.queued_movement = next_move.delta(turtle.position.1);
|
||||||
match next_move {
|
match next_move {
|
||||||
TurtleCommand::Left => turtle.position.1 = turtle.position.1.left(),
|
TurtleCommand::Left => turtle.position.1 = turtle.position.1.left(),
|
||||||
|
@ -329,7 +343,7 @@ fn process_turtle_update(
|
||||||
return Ok(next_move);
|
return Ok(next_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TurtleCommand::Wait)
|
Ok(TurtleCommand::Wait(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -354,13 +368,13 @@ fn difference(from: Position, to: Position) -> Option<TurtleCommand> {
|
||||||
}
|
}
|
||||||
} else if to.1 == from.1 {
|
} else if to.1 == from.1 {
|
||||||
if to.0 == from.0 + from.1.unit() {
|
if to.0 == from.0 + from.1.unit() {
|
||||||
Some(Forward)
|
Some(Forward(1))
|
||||||
} else if to.0 == from.0 - from.1.unit() {
|
} else if to.0 == from.0 - from.1.unit() {
|
||||||
Some(Backward)
|
Some(Backward(1))
|
||||||
} else if to.0 == from.0 + Vec3::y() {
|
} else if to.0 == from.0 + Vec3::y() {
|
||||||
Some(Up)
|
Some(Up(1))
|
||||||
} else if to.0 == from.0 - Vec3::y() {
|
} else if to.0 == from.0 - Vec3::y() {
|
||||||
Some(Down)
|
Some(Down(1))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -395,41 +409,66 @@ enum TurtleMineMethod {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
enum TurtleCommand {
|
enum TurtleCommand {
|
||||||
Wait,
|
Wait(u32),
|
||||||
Forward,
|
Forward(u32),
|
||||||
Backward,
|
Backward(u32),
|
||||||
Up,
|
Up(u32),
|
||||||
Down,
|
Down(u32),
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
Dig,
|
Dig,
|
||||||
DigUp,
|
DigUp,
|
||||||
DigDown,
|
DigDown,
|
||||||
TakeInventory,
|
PlaceUp,
|
||||||
|
Place,
|
||||||
|
PlaceDown,
|
||||||
|
/// Count
|
||||||
|
DropFront(u32),
|
||||||
|
DropUp(u32),
|
||||||
|
DropDown(u32),
|
||||||
|
Select(u32),
|
||||||
|
/// Slot in inventory
|
||||||
|
ItemInfo(u32),
|
||||||
Update,
|
Update,
|
||||||
Poweroff,
|
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 {
|
impl TurtleCommand {
|
||||||
fn delta(&self, direction: Direction) -> Vec3 {
|
fn delta(&self, direction: Direction) -> Vec3 {
|
||||||
let dir = direction.unit();
|
let dir = direction.unit();
|
||||||
match self {
|
match self {
|
||||||
TurtleCommand::Forward => dir,
|
TurtleCommand::Forward(count) => dir * *count as i32,
|
||||||
TurtleCommand::Backward => -dir,
|
TurtleCommand::Backward(count) => -dir * *count as i32,
|
||||||
TurtleCommand::Up => Vec3::y(),
|
TurtleCommand::Up(count) => Vec3::y() * *count as i32,
|
||||||
TurtleCommand::Down => -Vec3::y(),
|
TurtleCommand::Down(count) => -Vec3::y() * *count as i32,
|
||||||
_ => Vec3::zeros(),
|
_ => Vec3::zeros(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct TurtleUpdate {
|
struct TurtleUpdate {
|
||||||
fuel: usize,
|
fuel: usize,
|
||||||
/// Block name
|
/// Block name
|
||||||
ahead: String,
|
ahead: String,
|
||||||
above: String,
|
above: String,
|
||||||
below: String,
|
below: String,
|
||||||
|
ret: TurtleCommandResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
|
|
@ -5,9 +5,15 @@ use crate::{blocks::{World, Block}, Position, Direction};
|
||||||
|
|
||||||
use super::Vec3;
|
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();
|
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)> {
|
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();
|
let ahead = from.0 + from.1.unit();
|
||||||
insert(&mut vec, ahead, from.1, world, UNKNOWN);
|
insert(&mut vec, ahead, from.1, world, UNKNOWN);
|
||||||
|
|
||||||
let behind = from.0 - from.1.unit();
|
//let behind = from.0 - from.1.unit();
|
||||||
insert(&mut vec, behind, from.1, world, None);
|
//insert(&mut vec, behind, from.1, world, None);
|
||||||
|
|
||||||
let above = from.0 + Vec3::y();
|
let above = from.0 + Vec3::y();
|
||||||
insert(&mut vec, above, from.1, world,UNKNOWN);
|
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
|
/// Blocks that are fine to tunnel through
|
||||||
const GARBAGE: [&str; 3] = [
|
const GARBAGE: [&str; 5] = [
|
||||||
"minecraft:stone",
|
"minecraft:stone",
|
||||||
"minecraft:dirt",
|
"minecraft:dirt",
|
||||||
"minecraft:andesite",
|
"minecraft:andesite",
|
||||||
|
"minecraft:sand",
|
||||||
|
"minecraft:gravel",
|
||||||
];
|
];
|
||||||
|
|
||||||
/// time taken to go through uncharted territory (in turtle. calls)
|
/// time taken to go through uncharted territory (in turtle. calls)
|
||||||
|
@ -49,6 +57,6 @@ const UNKNOWN: Option<u32> = Some(2);
|
||||||
// time to go somewhere
|
// time to go somewhere
|
||||||
fn difficulty(name: &str) -> Option<u32> {
|
fn difficulty(name: &str) -> Option<u32> {
|
||||||
if name == "minecraft:air" { return Some(1) };
|
if name == "minecraft:air" { return Some(1) };
|
||||||
//if GARBAGE.contains(&name) { return Some(2)};
|
if GARBAGE.contains(&name) { return Some(2)};
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue