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 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" ,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue