| @@ -650,12 +650,22 @@ impl BuildContext<'_> { |
| 650 |
650 |
} |
| 651 |
651 |
|
| 652 |
652 |
fn material_source(&self, from: UVec2, (kind, amount): (ItemKind, u32)) -> Option<UVec2> { |
|
653 |
+ let free = |pos: UVec2| self.reservations.is_free(Target::Pickup(pos)); |
|
654 |
+ let available: u32 = self |
|
655 |
+ .items |
|
656 |
+ .iter() |
|
657 |
+ .filter(|(item, pos)| item.kind == kind && free(pos.0)) |
|
658 |
+ .map(|(item, _)| item.count) |
|
659 |
+ .sum(); |
|
660 |
+ if available < amount { |
|
661 |
+ return None; |
|
662 |
+ } |
| 653 |
663 |
nearest_tile(self.map, from, SEARCH_TILES, |p| { |
| 654 |
|
- self.reservations.is_free(Target::Pickup(p)) |
|
664 |
+ free(p) |
| 655 |
665 |
&& self |
| 656 |
666 |
.items |
| 657 |
667 |
.iter() |
| 658 |
|
- .any(|(item, pos)| pos.0 == p && item.kind == kind && item.count >= amount) |
|
668 |
+ .any(|(item, pos)| pos.0 == p && item.kind == kind) |
| 659 |
669 |
}) |
| 660 |
670 |
} |
| 661 |
671 |
|
| @@ -926,6 +936,8 @@ fn choose_jobs( |
| 926 |
936 |
}) |
| 927 |
937 |
.flatten() |
| 928 |
938 |
}) |
|
939 |
+ .or_else(|| find_bed_site(&build, colonist_count, tile.0)) |
|
940 |
+ .or_else(|| find_blueprint_work(&build, tile.0)) |
| 929 |
941 |
.or_else(|| find_work(&map, &reservations, tile.0, wanted)) |
| 930 |
942 |
.or_else(|| { |
| 931 |
943 |
wanted(ItemKind::Meat) |
| @@ -934,8 +946,6 @@ fn choose_jobs( |
| 934 |
946 |
}) |
| 935 |
947 |
.or_else(|| find_sowing(&map, &zones, &reservations, tile.0)) |
| 936 |
948 |
.or_else(|| find_haul(&map, &zones, &reservations, &snapshot, tile.0)) |
| 937 |
|
- .or_else(|| find_bed_site(&build, colonist_count, tile.0)) |
| 938 |
|
- .or_else(|| find_blueprint_work(&build, tile.0)) |
| 939 |
949 |
}; |
| 940 |
950 |
if let Some(task) = task { |
| 941 |
951 |
if let Task::Work { site, .. } = task |
| @@ -1276,17 +1286,36 @@ fn run_jobs( |
| 1276 |
1286 |
Step::Done |
| 1277 |
1287 |
} else if tile.0 != from { |
| 1278 |
1288 |
walk_to(&map, tile.0, from, &mut path) |
|
1289 |
+ } else if carrying.0.is_some_and(|load| load.kind != material) { |
|
1290 |
+ Step::Done |
| 1279 |
1291 |
} else { |
| 1280 |
|
- let load = take_items(&mut commands, &mut items, from, cost) |
| 1281 |
|
- .filter(|load| load.kind == material && load.count > 0); |
| 1282 |
|
- carrying.0 = load; |
| 1283 |
|
- match load { |
| 1284 |
|
- Some(load) if load.count >= cost => { |
| 1285 |
|
- reservations.release(Target::Pickup(from)); |
|
1292 |
+ let have = carrying.0.map_or(0, |load| load.count); |
|
1293 |
+ let taken = take_items(&mut commands, &mut items, from, cost - have) |
|
1294 |
+ .filter(|load| load.kind == material) |
|
1295 |
+ .map_or(0, |load| load.count); |
|
1296 |
+ reservations.release(Target::Pickup(from)); |
|
1297 |
+ let total = have + taken; |
|
1298 |
+ carrying.0 = (total > 0).then_some(Item { |
|
1299 |
+ kind: material, |
|
1300 |
+ count: total, |
|
1301 |
+ }); |
|
1302 |
+ let next = nearest_tile(&map, tile.0, SEARCH_TILES, |p| { |
|
1303 |
+ reservations.is_free(Target::Pickup(p)) |
|
1304 |
+ && items.iter().any(|(_, item, pos)| { |
|
1305 |
+ pos.0 == p && item.kind == material && item.count > 0 |
|
1306 |
+ }) |
|
1307 |
+ }); |
|
1308 |
+ match next { |
|
1309 |
+ _ if total >= cost => { |
| 1286 |
1310 |
*pickup = None; |
| 1287 |
1311 |
Step::Continue |
| 1288 |
1312 |
} |
| 1289 |
|
- _ => Step::Done, |
|
1313 |
+ Some(next) => { |
|
1314 |
+ reservations.reserve(Target::Pickup(next), entity); |
|
1315 |
+ *pickup = Some(next); |
|
1316 |
+ Step::Continue |
|
1317 |
+ } |
|
1318 |
+ None => Step::Done, |
| 1290 |
1319 |
} |
| 1291 |
1320 |
} |
| 1292 |
1321 |
} else if !carrying |