cache inventory
This commit is contained in:
parent
e73e77f800
commit
81a56331f9
3 changed files with 63 additions and 21 deletions
|
@ -52,8 +52,8 @@ impl Depots {
|
||||||
turtle.goto(*depot.position()).await?;
|
turtle.goto(*depot.position()).await?;
|
||||||
|
|
||||||
// dump inventory
|
// dump inventory
|
||||||
for i in 1..=16 {
|
for (i, _) in turtle.inventory().await.into_iter().enumerate().filter(|(_,n)| n.is_some()) {
|
||||||
turtle.execute(Select(i)).await;
|
turtle.execute(Select(i as u32)).await;
|
||||||
turtle.execute(DropDown(64)).await;
|
turtle.execute(DropDown(64)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ impl Depots {
|
||||||
drop(depot);
|
drop(depot);
|
||||||
|
|
||||||
// lava bucket fix
|
// lava bucket fix
|
||||||
for i in 1..=16 {
|
for (i, _) in turtle.inventory().await.into_iter().enumerate().filter(|(_,n)| n.is_some()) {
|
||||||
turtle.execute(Select(i)).await;
|
turtle.execute(Select(i as u32)).await;
|
||||||
turtle.execute(DropDown(64)).await;
|
turtle.execute(DropDown(64)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,10 +131,10 @@ async fn dump(turtle: TurtleCommander) {
|
||||||
async fn dump_filter<F>(turtle: TurtleCommander, mut filter: F) -> u32
|
async fn dump_filter<F>(turtle: TurtleCommander, mut filter: F) -> u32
|
||||||
where F: FnMut(InventorySlot) -> bool {
|
where F: FnMut(InventorySlot) -> bool {
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
for i in 1..=16 {
|
for (i, slot) in turtle.inventory().await.into_iter().enumerate() {
|
||||||
if let TurtleCommandResponse::Item(item) = turtle.execute(ItemInfo(i)).await.ret {
|
if let Some(item) = slot {
|
||||||
if filter(item) {
|
if filter(item) {
|
||||||
turtle.execute(Select(i)).await;
|
turtle.execute(Select(i as u32)).await;
|
||||||
turtle.execute(DropFront(64)).await;
|
turtle.execute(DropFront(64)).await;
|
||||||
} else {
|
} else {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
|
|
|
@ -154,6 +154,7 @@ pub struct TurtleCommander {
|
||||||
fuel: Arc<AtomicUsize>,
|
fuel: Arc<AtomicUsize>,
|
||||||
max_fuel: Arc<AtomicUsize>,
|
max_fuel: Arc<AtomicUsize>,
|
||||||
name: Arc<OnceCell<Name>>,
|
name: Arc<OnceCell<Name>>,
|
||||||
|
inventory: Arc<RwLock<Option<Vec<Option<InventorySlot>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for TurtleCommander {
|
impl fmt::Debug for TurtleCommander {
|
||||||
|
@ -176,6 +177,7 @@ impl TurtleCommander {
|
||||||
max_fuel: Arc::new(AtomicUsize::new(turtle.fuel_limit)),
|
max_fuel: Arc::new(AtomicUsize::new(turtle.fuel_limit)),
|
||||||
name: Arc::new(OnceCell::new_with(Some(turtle.name))),
|
name: Arc::new(OnceCell::new_with(Some(turtle.name))),
|
||||||
depots: state.depots.clone(),
|
depots: state.depots.clone(),
|
||||||
|
inventory: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +190,7 @@ impl TurtleCommander {
|
||||||
max_fuel: Arc::new(AtomicUsize::new(turtle.fuel_limit)),
|
max_fuel: Arc::new(AtomicUsize::new(turtle.fuel_limit)),
|
||||||
name: Arc::new(OnceCell::new_with(Some(turtle.name))),
|
name: Arc::new(OnceCell::new_with(Some(turtle.name))),
|
||||||
depots: state.depots.clone(),
|
depots: state.depots.clone(),
|
||||||
|
inventory: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,16 +198,33 @@ impl TurtleCommander {
|
||||||
pub async fn execute(&self, command: TurtleCommand) -> TurtleInfo {
|
pub async fn execute(&self, command: TurtleCommand) -> TurtleInfo {
|
||||||
let (send, recv) = oneshot::channel::<TurtleInfo>();
|
let (send, recv) = oneshot::channel::<TurtleInfo>();
|
||||||
|
|
||||||
if let Err(_) = self.sender.to_owned().send((command,send)).await {
|
if let Err(_) = self.sender.to_owned().send((command.clone(),send)).await {
|
||||||
error!("server disappeared"); // It's fine to continue, nobody
|
error!("server disappeared"); // It's fine to continue, nobody
|
||||||
// is left to read garbage
|
// is left to read garbage
|
||||||
};
|
};
|
||||||
|
|
||||||
let resp = recv.await.unwrap_or_else(|_| {
|
let resp = recv.await.unwrap_or_else(|_| {
|
||||||
error!("server dissapering");
|
error!("server disappearing");
|
||||||
TurtleInfo::from_update(TurtleUpdate { fuel: self.fuel(), ahead: "".into(), above: "".into(), below: "".into(), ret: TurtleCommandResponse::Failure }, self.name(), Position::new(Vec3::zeros(), Direction::North))
|
TurtleInfo::from_update(TurtleUpdate { fuel: self.fuel(), ahead: "".into(), above: "".into(), below: "".into(), ret: TurtleCommandResponse::Failure }, self.name(), Position::new(Vec3::zeros(), Direction::North))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// invalidate inventory when we run commands that modify it
|
||||||
|
// this is not safe if you make a second TurtleCommander
|
||||||
|
if let TurtleCommandResponse::Success = resp.ret {
|
||||||
|
if match command {
|
||||||
|
TurtleCommand::Wait(_) => false,
|
||||||
|
TurtleCommand::Forward(_) => false,
|
||||||
|
TurtleCommand::Backward(_) => false,
|
||||||
|
TurtleCommand::Up(_) => false,
|
||||||
|
TurtleCommand::Down(_) => false,
|
||||||
|
TurtleCommand::Left => false,
|
||||||
|
TurtleCommand::Right => false,
|
||||||
|
_ => true,
|
||||||
|
} {
|
||||||
|
*self.inventory.write().await = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut pos = self.pos.write().await;
|
let mut pos = self.pos.write().await;
|
||||||
*pos = resp.pos;
|
*pos = resp.pos;
|
||||||
self.fuel.store(resp.fuel, std::sync::atomic::Ordering::SeqCst);
|
self.fuel.store(resp.fuel, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
@ -231,20 +251,42 @@ impl TurtleCommander {
|
||||||
self.world.clone()
|
self.world.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn inventory(&self) -> Vec<Option<InventorySlot>> {
|
||||||
|
let mut inventory = self.inventory.write().await;
|
||||||
|
|
||||||
|
if inventory.is_some() {
|
||||||
|
return inventory.clone().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut scan = Vec::new();
|
||||||
|
|
||||||
|
for i in 1..=16 {
|
||||||
|
match self.execute(TurtleCommand::ItemInfo(i)).await.ret {
|
||||||
|
TurtleCommandResponse::Item(item) => {
|
||||||
|
scan.push(Some(item));
|
||||||
|
}
|
||||||
|
TurtleCommandResponse::None => {
|
||||||
|
scan.push(None);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("inventory scan for #{} is going sideways", self.name().to_str());
|
||||||
|
scan.push(None);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*inventory = Some(scan.clone());
|
||||||
|
scan
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub async fn dock(&self) -> usize {
|
pub async fn dock(&self) -> usize {
|
||||||
let mut wait = 1;
|
let res = Depots::dock(&self.depots, self.to_owned()).await;
|
||||||
loop {
|
if let Some(fuel) = res {
|
||||||
let res = Depots::dock(&self.depots, self.to_owned()).await;
|
return fuel;
|
||||||
if let Some(fuel) = res {
|
};
|
||||||
return fuel;
|
error!("dock failed");
|
||||||
}
|
self.fuel()
|
||||||
error!("depot lock failed");
|
|
||||||
// this is a poor way to do this, but I feel like select! ing on 30 different things
|
|
||||||
// would be harder
|
|
||||||
tokio::time::sleep(Duration::from_millis(wait)).await;
|
|
||||||
wait += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn try_dock(&self) -> Option<usize> {
|
pub async fn try_dock(&self) -> Option<usize> {
|
||||||
|
|
Loading…
Reference in a new issue