1
Fork 0

cache inventory

This commit is contained in:
Andy Killorin 2023-12-26 20:15:49 -06:00
parent e73e77f800
commit 81a56331f9
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 63 additions and 21 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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> {