# 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.