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?;
|
||||
|
||||
// dump inventory
|
||||
for i in 1..=16 {
|
||||
turtle.execute(Select(i)).await;
|
||||
for (i, _) in turtle.inventory().await.into_iter().enumerate().filter(|(_,n)| n.is_some()) {
|
||||
turtle.execute(Select(i as u32)).await;
|
||||
turtle.execute(DropDown(64)).await;
|
||||
}
|
||||
|
||||
|
@ -81,8 +81,8 @@ impl Depots {
|
|||
drop(depot);
|
||||
|
||||
// lava bucket fix
|
||||
for i in 1..=16 {
|
||||
turtle.execute(Select(i)).await;
|
||||
for (i, _) in turtle.inventory().await.into_iter().enumerate().filter(|(_,n)| n.is_some()) {
|
||||
turtle.execute(Select(i as u32)).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
|
||||
where F: FnMut(InventorySlot) -> bool {
|
||||
let mut counter = 0;
|
||||
for i in 1..=16 {
|
||||
if let TurtleCommandResponse::Item(item) = turtle.execute(ItemInfo(i)).await.ret {
|
||||
for (i, slot) in turtle.inventory().await.into_iter().enumerate() {
|
||||
if let Some(item) = slot {
|
||||
if filter(item) {
|
||||
turtle.execute(Select(i)).await;
|
||||
turtle.execute(Select(i as u32)).await;
|
||||
turtle.execute(DropFront(64)).await;
|
||||
} else {
|
||||
counter += 1;
|
||||
|
|
|
@ -154,6 +154,7 @@ pub struct TurtleCommander {
|
|||
fuel: Arc<AtomicUsize>,
|
||||
max_fuel: Arc<AtomicUsize>,
|
||||
name: Arc<OnceCell<Name>>,
|
||||
inventory: Arc<RwLock<Option<Vec<Option<InventorySlot>>>>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for TurtleCommander {
|
||||
|
@ -176,6 +177,7 @@ impl TurtleCommander {
|
|||
max_fuel: Arc::new(AtomicUsize::new(turtle.fuel_limit)),
|
||||
name: Arc::new(OnceCell::new_with(Some(turtle.name))),
|
||||
depots: state.depots.clone(),
|
||||
inventory: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -188,6 +190,7 @@ impl TurtleCommander {
|
|||
max_fuel: Arc::new(AtomicUsize::new(turtle.fuel_limit)),
|
||||
name: Arc::new(OnceCell::new_with(Some(turtle.name))),
|
||||
depots: state.depots.clone(),
|
||||
inventory: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,16 +198,33 @@ impl TurtleCommander {
|
|||
pub async fn execute(&self, command: TurtleCommand) -> 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
|
||||
// is left to read garbage
|
||||
};
|
||||
|
||||
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))
|
||||
});
|
||||
|
||||
// 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;
|
||||
*pos = resp.pos;
|
||||
self.fuel.store(resp.fuel, std::sync::atomic::Ordering::SeqCst);
|
||||
|
@ -231,20 +251,42 @@ impl TurtleCommander {
|
|||
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))]
|
||||
pub async fn dock(&self) -> usize {
|
||||
let mut wait = 1;
|
||||
loop {
|
||||
let res = Depots::dock(&self.depots, self.to_owned()).await;
|
||||
if let Some(fuel) = res {
|
||||
return 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;
|
||||
}
|
||||
};
|
||||
error!("dock failed");
|
||||
self.fuel()
|
||||
}
|
||||
|
||||
pub async fn try_dock(&self) -> Option<usize> {
|
||||
|
|
Loading…
Reference in a new issue