185 lines
4.7 KiB
Markdown
185 lines
4.7 KiB
Markdown
# opencomputers
|
|
|
|
Typed wrappers for the OC2R high-level API based on `oc2r-core`.
|
|
Each module exposes a safe, idiomatic Rust interface for a specific
|
|
device class.
|
|
|
|
## Usage Overview
|
|
|
|
Every wrapper sits on top of `Device::call`. Typical imports look like:
|
|
|
|
```rust
|
|
use oc2r_core::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
|
|
use opencomputers::*;
|
|
```
|
|
|
|
Attach the device before use:
|
|
|
|
```rust
|
|
let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
|
|
let mut redstone = RedstoneInterface::attach(&mut bus)?
|
|
.expect("no redstone interface attached");
|
|
redstone.subscribe()?; // unsubscribe() once you are done
|
|
```
|
|
|
|
### Robot
|
|
|
|
```rust
|
|
use opencomputers::{Robot, RobotDirection};
|
|
|
|
let mut robot = Robot::attach(&mut bus)?.expect("no robot available");
|
|
println!("energy {}/{}", robot.energy()?, robot.capacity()?);
|
|
|
|
let selected = robot.slot(None)?;
|
|
println!("selected slot {selected}");
|
|
if let Some(stack) = robot.stack(None)? {
|
|
println!("holding: {stack:?}");
|
|
}
|
|
|
|
if robot.move_blocking(RobotDirection::Forward)? {
|
|
println!("stepped forward");
|
|
}
|
|
robot.turn(RobotDirection::Left)?;
|
|
```
|
|
|
|
### Redstone Interface
|
|
|
|
```rust
|
|
use opencomputers::{RedstoneInterface, RedstoneSignal, Side};
|
|
|
|
redstone.set_output_state(Side::East, true)?;
|
|
let input = redstone.input(Side::East)?;
|
|
let output = redstone.output(Side::East)?;
|
|
redstone.set_output_level(Side::East, 7)?;
|
|
|
|
if let Some(signal) = redstone.try_event()? {
|
|
println!("{} -> {}", signal.side, signal.level);
|
|
}
|
|
```
|
|
|
|
`Side` implements `FromStr` so strings like "north" parse safely. Incoming
|
|
events surface as `RedstoneSignal { side, level }`; see
|
|
[`examples/redstone-events.rs`](examples/redstone-events.rs) for a full event
|
|
loop.
|
|
|
|
### Energy Storage
|
|
|
|
```rust
|
|
use opencomputers::EnergyStorage;
|
|
|
|
let mut energy = EnergyStorage::attach(&mut bus)?.expect("no energy storage");
|
|
println!("{}/{}", energy.energy_stored()?, energy.max_energy_stored()?);
|
|
println!("can_extract: {}", energy.can_extract()?);
|
|
println!("can_receive: {}", energy.can_receive()?);
|
|
```
|
|
|
|
### Fluid Handler
|
|
|
|
```rust
|
|
use opencomputers::FluidHandler;
|
|
|
|
let mut fluids = FluidHandler::attach(&mut bus)?.expect("no fluid handler");
|
|
let tanks = fluids.tank_count()? as usize;
|
|
for tank in 0..tanks {
|
|
let capacity = fluids.tank_capacity(tank)?;
|
|
let content = fluids.fluid_in_tank(tank)?;
|
|
println!("tank {tank}: {content:?}/{capacity}");
|
|
}
|
|
```
|
|
|
|
### Item Handler
|
|
|
|
```rust
|
|
use opencomputers::ItemHandler;
|
|
|
|
let mut items = ItemHandler::attach(&mut bus)?.expect("no item handler");
|
|
let slots = items.slot_count()? as usize;
|
|
for slot in 0..slots {
|
|
let stack = items.stack_in_slot(slot)?;
|
|
let limit = items.slot_limit(slot)?;
|
|
println!("slot {slot}: {stack:?} (limit {limit})");
|
|
}
|
|
```
|
|
|
|
### CPU
|
|
|
|
```rust
|
|
use opencomputers::Cpu;
|
|
|
|
let mut cpu = Cpu::attach(&mut bus)?.expect("no cpu card");
|
|
println!("frequency {} MHz", cpu.frequency()?);
|
|
```
|
|
|
|
### Sound Card
|
|
|
|
```rust
|
|
use opencomputers::SoundCard;
|
|
|
|
let mut sound = SoundCard::attach(&mut bus)?.expect("no sound card");
|
|
sound.play_with_volume_and_pitch("minecraft:block.note_block.harp", 0.8, 1.2)?;
|
|
let matches = sound.find("note_block")?;
|
|
println!("found {} sound(s)", matches.len());
|
|
```
|
|
|
|
### Block Operations Module
|
|
|
|
```rust
|
|
use opencomputers::{BlockOperations, RobotSide};
|
|
|
|
let mut ops = BlockOperations::attach(&mut bus)?.expect("no block module");
|
|
ops.excavate_on(RobotSide::Front)?;
|
|
ops.place_on(RobotSide::Down)?;
|
|
println!("durability {}", ops.durability()?);
|
|
if ops.repair()? {
|
|
println!("tool repaired");
|
|
}
|
|
```
|
|
|
|
### Inventory Operations Module
|
|
|
|
```rust
|
|
use opencomputers::{InventoryOperations, RobotSide};
|
|
|
|
let mut inv = InventoryOperations::attach(&mut bus)?.expect("no inventory module");
|
|
inv.move_items(0, 1, 32)?;
|
|
inv.drop_on(16, RobotSide::Front)?;
|
|
let taken = inv.take_from_slot_on(0, 8, RobotSide::Up)?;
|
|
println!("taken {taken}");
|
|
```
|
|
|
|
### File Import/Export Card
|
|
|
|
```rust
|
|
use opencomputers::FileImportExport;
|
|
|
|
let mut fie = FileImportExport::attach(&mut bus)?.expect("no file card");
|
|
fie.reset()?;
|
|
fie.begin_export("test.txt")?;
|
|
fie.write_export_chunk(b"hello world")?;
|
|
fie.finish_export()?;
|
|
|
|
if fie.request_import()? {
|
|
if let Some(info) = fie.begin_import()? {
|
|
println!(
|
|
"importing {} ({} bytes)",
|
|
info.name.unwrap_or_default(),
|
|
info.size
|
|
);
|
|
while let Some(bytes) = fie.read_import_chunk()? {
|
|
// write bytes to disk
|
|
println!("chunk {} bytes", bytes.len());
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Device-specific events remain accessible through `Device::next_event` or
|
|
`DeviceBus::next_event_for` when you need raw payloads.
|
|
|
|
## Examples
|
|
|
|
- [`examples/redstone.rs`](examples/redstone.rs) — control redstone IO from the
|
|
command line.
|
|
- [`examples/redstone-events.rs`](examples/redstone-events.rs) — subscribe to
|
|
redstone change events.
|