Moved devices into their own crate
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -56,6 +56,14 @@ dependencies = [
|
||||
"miniserde-enum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opencomputers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"oc2r-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
|
||||
@@ -24,3 +24,4 @@ codegen-units = 1
|
||||
|
||||
[workspace.dependencies]
|
||||
oc2r-core = { path = "crates/oc2r-core" }
|
||||
opencomputers = { path = "crates/opencomputers" }
|
||||
|
||||
@@ -5,7 +5,8 @@ Thin, synchronous access to the [OpenComputers II: Reimagined](https://github.co
|
||||
This repository is a workspace is divided into multiple crates:
|
||||
|
||||
- `crates/oc2r-core`: mirrors the stock Lua helpers (`devices.lua`, `robot.lua`) so you can list devices, invoke methods,
|
||||
subscribe to events, and work with typed wrappers for common peripherals.
|
||||
subscribe to events, and work with the low-level RPC primitives.
|
||||
- `crates/opencomputers`: companion crate that provides strongly typed wrappers for the common HLAPI peripherals.
|
||||
|
||||
## Development
|
||||
|
||||
@@ -26,4 +27,3 @@ Each crates has some examples of how to use it crate are in the `examples` direc
|
||||
|
||||
Copy the resulting binaries from `target/<triple>/release/examples/` into Minux (an Import/Export card works
|
||||
well), mark them as executable and then execute them inside the VM.
|
||||
|
||||
|
||||
@@ -1,13 +1,66 @@
|
||||
# OC2R-Core
|
||||
|
||||
This crate mirrors the stock Lua helpers (`devices.lua`, `robot.lua`) so you can list devices, invoke methods,
|
||||
subscribe to events, and work with typed wrappers for common peripherals.
|
||||
Minimal Rust client for the OC2R high-level API. It mirrors the bundled Lua
|
||||
helper (`devices.lua`) so you can list devices, invoke methods,
|
||||
and subscribe to events. For ergonomic wrappers on top of these primitives, add
|
||||
the [`opencomputers`](../opencomputers) crate.
|
||||
|
||||
## Documentation
|
||||
## Getting Started
|
||||
|
||||
See [`docs/index.md`](docs/index.md) for the full guide and
|
||||
[`docs/wrappers.md`](docs/wrappers.md) for device-by-device examples.
|
||||
1. Install [cross](https://github.com/cross-rs/cross):
|
||||
```bash
|
||||
cargo install cross --git https://github.com/cross-rs/cross
|
||||
```
|
||||
2. Compile your binary for Minux:
|
||||
```bash
|
||||
cross build --release
|
||||
```
|
||||
3. Copy `target/<triple>/release/your-app` onto the Import/Export card and drop
|
||||
it inside the OC2R VM (for example `/usr/bin/your-app`).
|
||||
|
||||
## Quick Start
|
||||
|
||||
```rust
|
||||
use oc2r_core::{DeviceBus, DeviceEvent, Result, DEFAULT_DEVICE_PATH};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
|
||||
|
||||
// Enumerate devices.
|
||||
let devices = bus.list()?;
|
||||
println!("Found {} device(s)", devices.len());
|
||||
|
||||
// Call a method dynamically.
|
||||
let first = &devices[0].device_id;
|
||||
let mut device = bus.device(first)?.expect("device disappeared");
|
||||
let response = device.call("help", ())?;
|
||||
println!("help(): {response}");
|
||||
|
||||
// Subscribe to events and drain one.
|
||||
device.subscribe()?;
|
||||
let event = bus.next_event_for(&device_id)?;
|
||||
println!("{device_id} -> {:#?}", event.payload);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Transport & API Surface
|
||||
|
||||
- **Framing:** Messages are JSON framed with a leading/trailing NUL, exactly
|
||||
like the Lua RPC client. `DeviceBus::flush` drains stale responses before each
|
||||
call.
|
||||
- **Dynamic calls:** Use `Device::call` or `DeviceBus::call`. Anything that
|
||||
implements `IntoJsonArgs` (tuples, slices, `Vec<T>`) is accepted and converted
|
||||
into JSON automatically.
|
||||
- **Subscriptions:** `Device::subscribe` / `Device::unsubscribe` send the
|
||||
corresponding RPC requests. `DeviceBus::next_event_for(device_id)` waits for
|
||||
the next matching event; `Device::next_event()` provides a convenience
|
||||
wrapper. `try_event*` variants check queues without blocking. For a Lua-style
|
||||
dispatcher, use [`EventLoop`](src/event.rs) which mirrors `event.pull` and
|
||||
friends.
|
||||
|
||||
## Development
|
||||
|
||||
The crate targets rust nightly for some size optimisations and relies on `miniserde` and `libc`.
|
||||
The crate targets rust nightly for size optimisations and relies on `miniserde`
|
||||
and `libc`.
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# OC2R Rust Client Guide
|
||||
|
||||
This guide walks through everything you can do with the crate: connecting to
|
||||
the RPC controller, issuing method calls, handling events, and using the typed
|
||||
wrappers that mirror `devices.lua`.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Install [cross](https://github.com/cross-rs/cross):
|
||||
```bash
|
||||
cargo install cross --git https://github.com/cross-rs/cross
|
||||
```
|
||||
2. Compile your binary for Minux:
|
||||
```bash
|
||||
cross build --release
|
||||
```
|
||||
3. Copy `target/<triple>/release/your-app` onto the Import/Export card and drop
|
||||
it inside the OC2R VM (e.g. `/usr/bin/your-app`).
|
||||
|
||||
## Quick Start
|
||||
|
||||
```rust
|
||||
use oc2r_rust::{DeviceBus, DeviceEvent, Result, DEFAULT_DEVICE_PATH};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
|
||||
|
||||
// Enumerate devices.
|
||||
let devices = bus.list()?;
|
||||
println!("Found {} device(s)", devices.len());
|
||||
|
||||
// Call a method dynamically.
|
||||
let first = &devices[0].device_id;
|
||||
let mut device = bus.device(first)?.expect("device disappeared");
|
||||
let response = device.call("help", ())?;
|
||||
println!("help(): {response}");
|
||||
|
||||
// Subscribe to events and drain one.
|
||||
device.subscribe()?;
|
||||
let event = bus.next_event_for(&device_id)?;
|
||||
println!("{device_id} -> {:#?}", event.payload);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Transport & API Surface
|
||||
|
||||
- **Framing:** Messages are JSON framed with a leading/trailing NUL, exactly like
|
||||
Lua’s RPC client. `DeviceBus::flush` drains stale responses before each call.
|
||||
- **Dynamic calls:** Use `Device::call` or `DeviceBus::call`. Anything that
|
||||
implements `IntoJsonArgs` (tuples, slices, `Vec<T>`) is accepted and converted
|
||||
into JSON automatically.
|
||||
- **Subscriptions:** `Device::subscribe` / `Device::unsubscribe` send the
|
||||
corresponding RPC requests. `DeviceBus::next_event_for(device_id)` waits for
|
||||
the next matching event; `Device::next_event()` provides a convenience wrapper.
|
||||
`try_event*` variants check queues without blocking. For a Lua-style
|
||||
dispatcher, use [`EventLoop`](../src/event.rs) which mirrors `event.pull` and
|
||||
friends.
|
||||
|
||||
## Typed Wrappers
|
||||
|
||||
To avoid raw JSON, every base device has a wrapper with strongly typed methods:
|
||||
|
||||
- `RedstoneInterface`
|
||||
- `EnergyStorage`
|
||||
- `FluidHandler`
|
||||
- `ItemHandler`
|
||||
- `Cpu`
|
||||
- `SoundCard`
|
||||
- `BlockOperations`
|
||||
- `InventoryOperations`
|
||||
- `FileImportExport`
|
||||
- `Robot`
|
||||
|
||||
Each wrapper exposes Rust-style methods (e.g. `RedstoneInterface::input`, `SoundCard::find`)
|
||||
built on top of the dynamic API. See [`wrappers.md`](wrappers.md) for detailed
|
||||
examples and method-by-method coverage.
|
||||
|
||||
## Additional Topics
|
||||
|
||||
- [Device wrapper reference](wrappers.md)
|
||||
- [Redstone event example](../examples/redstone-events.rs)
|
||||
- [Lua-style event loop](../src/event.rs)
|
||||
@@ -3,11 +3,12 @@
|
||||
//! This crate mirrors the behaviour of the bundled Lua `devices.lua`
|
||||
//! helper. It communicates with the OC2R RPC controller over the first
|
||||
//! VirtIO console device (`/dev/hvc0`) and exposes helpers for listing
|
||||
//! devices, inspecting available methods and invoking them.
|
||||
//! devices, inspecting available methods and invoking them. For ergonomic
|
||||
//! wrappers built on this low level API, add the `opencomputers` crate.
|
||||
//!
|
||||
//! # Quick start
|
||||
//! ```no_run
|
||||
//! use oc2r_rust::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
|
||||
//! use oc2r_core::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
|
||||
//!
|
||||
//! fn main() -> Result<()> {
|
||||
//! let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
|
||||
@@ -25,7 +26,6 @@
|
||||
//! ```
|
||||
|
||||
pub mod bus;
|
||||
pub mod devices;
|
||||
pub mod error;
|
||||
pub mod event;
|
||||
pub mod rpc;
|
||||
@@ -33,14 +33,9 @@ mod transport;
|
||||
mod value;
|
||||
|
||||
pub use bus::{Device, DeviceBus, DeviceEvent};
|
||||
pub use devices::{
|
||||
BlockOperations, Cpu, EnergyStorage, FileImportExport, FluidHandler, ImportedFileInfo,
|
||||
InventoryOperations, ItemHandler, ParseSideError, RedstoneInterface, RedstoneSignal, Robot,
|
||||
RobotDirection, RobotSide, Side, SoundCard,
|
||||
};
|
||||
pub use error::{Error, Result};
|
||||
pub use event::{EventLoop, Signal};
|
||||
pub use rpc::{DeviceEntry, JsonValue, MethodEntry, MethodParameter};
|
||||
pub use rpc::{DeviceEntry, JsonArray, JsonNumber, JsonValue, MethodEntry, MethodParameter};
|
||||
pub use value::{IntoJsonArgs, IntoJsonValue, JsonValueExt};
|
||||
|
||||
pub const DEFAULT_DEVICE_PATH: &str = "/dev/hvc0";
|
||||
|
||||
@@ -71,3 +71,5 @@ pub struct MethodParameter {
|
||||
}
|
||||
|
||||
pub type JsonValue = json::Value;
|
||||
pub type JsonArray = json::Array;
|
||||
pub type JsonNumber = json::Number;
|
||||
|
||||
10
crates/opencomputers/Cargo.toml
Normal file
10
crates/opencomputers/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "opencomputers"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
oc2r-core = { path = "../oc2r-core" }
|
||||
|
||||
[dev-dependencies]
|
||||
libc = "0.2"
|
||||
@@ -1,26 +1,31 @@
|
||||
# Device Wrapper Reference
|
||||
# opencomputers
|
||||
|
||||
Each wrapper mirrors the Lua helper for the corresponding OC2R device and builds
|
||||
on top of `Device::call`. All examples assume:
|
||||
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_rust::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
|
||||
use oc2r_core::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
|
||||
use opencomputers::*;
|
||||
```
|
||||
|
||||
Before using any wrapper, attach it:
|
||||
Attach the device before use:
|
||||
|
||||
```rust
|
||||
let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
|
||||
let mut redstone = oc2r_rust::RedstoneInterface::attach(&mut bus)?
|
||||
let mut redstone = RedstoneInterface::attach(&mut bus)?
|
||||
.expect("no redstone interface attached");
|
||||
// call unsubscribe() once you are done processing events
|
||||
redstone.subscribe()?;
|
||||
redstone.subscribe()?; // unsubscribe() once you are done
|
||||
```
|
||||
|
||||
## Robot
|
||||
### Robot
|
||||
|
||||
```rust
|
||||
use oc2r_rust::{Robot, RobotDirection};
|
||||
use opencomputers::{Robot, RobotDirection};
|
||||
|
||||
let mut robot = Robot::attach(&mut bus)?.expect("no robot available");
|
||||
println!("energy {}/{}", robot.energy()?, robot.capacity()?);
|
||||
@@ -37,10 +42,10 @@ if robot.move_blocking(RobotDirection::Forward)? {
|
||||
robot.turn(RobotDirection::Left)?;
|
||||
```
|
||||
|
||||
## Redstone
|
||||
### Redstone Interface
|
||||
|
||||
```rust
|
||||
use oc2r_rust::{RedstoneInterface, RedstoneSignal, Side};
|
||||
use opencomputers::{RedstoneInterface, RedstoneSignal, Side};
|
||||
|
||||
redstone.set_output_state(Side::East, true)?;
|
||||
let input = redstone.input(Side::East)?;
|
||||
@@ -52,14 +57,15 @@ if let Some(signal) = redstone.try_event()? {
|
||||
}
|
||||
```
|
||||
|
||||
`Side` implements `FromStr` so strings like "north" can be parsed safely.
|
||||
Incoming events surface as `RedstoneSignal { side, level }`; see also the
|
||||
`examples/redstone-events.rs` program.
|
||||
`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
|
||||
### Energy Storage
|
||||
|
||||
```rust
|
||||
use oc2r_rust::EnergyStorage;
|
||||
use opencomputers::EnergyStorage;
|
||||
|
||||
let mut energy = EnergyStorage::attach(&mut bus)?.expect("no energy storage");
|
||||
println!("{}/{}", energy.energy_stored()?, energy.max_energy_stored()?);
|
||||
@@ -67,10 +73,10 @@ println!("can_extract: {}", energy.can_extract()?);
|
||||
println!("can_receive: {}", energy.can_receive()?);
|
||||
```
|
||||
|
||||
## Fluid Handler
|
||||
### Fluid Handler
|
||||
|
||||
```rust
|
||||
use oc2r_rust::FluidHandler;
|
||||
use opencomputers::FluidHandler;
|
||||
|
||||
let mut fluids = FluidHandler::attach(&mut bus)?.expect("no fluid handler");
|
||||
let tanks = fluids.tank_count()? as usize;
|
||||
@@ -81,10 +87,10 @@ for tank in 0..tanks {
|
||||
}
|
||||
```
|
||||
|
||||
## Item Handler
|
||||
### Item Handler
|
||||
|
||||
```rust
|
||||
use oc2r_rust::ItemHandler;
|
||||
use opencomputers::ItemHandler;
|
||||
|
||||
let mut items = ItemHandler::attach(&mut bus)?.expect("no item handler");
|
||||
let slots = items.slot_count()? as usize;
|
||||
@@ -95,19 +101,19 @@ for slot in 0..slots {
|
||||
}
|
||||
```
|
||||
|
||||
## CPU
|
||||
### CPU
|
||||
|
||||
```rust
|
||||
use oc2r_rust::Cpu;
|
||||
use opencomputers::Cpu;
|
||||
|
||||
let mut cpu = Cpu::attach(&mut bus)?.expect("no cpu card");
|
||||
println!("frequency {} MHz", cpu.frequency()?);
|
||||
```
|
||||
|
||||
## Sound Card
|
||||
### Sound Card
|
||||
|
||||
```rust
|
||||
use oc2r_rust::SoundCard;
|
||||
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)?;
|
||||
@@ -115,10 +121,10 @@ let matches = sound.find("note_block")?;
|
||||
println!("found {} sound(s)", matches.len());
|
||||
```
|
||||
|
||||
## Block Operations Module
|
||||
### Block Operations Module
|
||||
|
||||
```rust
|
||||
use oc2r_rust::{BlockOperations, RobotSide};
|
||||
use opencomputers::{BlockOperations, RobotSide};
|
||||
|
||||
let mut ops = BlockOperations::attach(&mut bus)?.expect("no block module");
|
||||
ops.excavate_on(RobotSide::Front)?;
|
||||
@@ -129,10 +135,10 @@ if ops.repair()? {
|
||||
}
|
||||
```
|
||||
|
||||
## Inventory Operations Module
|
||||
### Inventory Operations Module
|
||||
|
||||
```rust
|
||||
use oc2r_rust::{InventoryOperations, RobotSide};
|
||||
use opencomputers::{InventoryOperations, RobotSide};
|
||||
|
||||
let mut inv = InventoryOperations::attach(&mut bus)?.expect("no inventory module");
|
||||
inv.move_items(0, 1, 32)?;
|
||||
@@ -141,10 +147,10 @@ let taken = inv.take_from_slot_on(0, 8, RobotSide::Up)?;
|
||||
println!("taken {taken}");
|
||||
```
|
||||
|
||||
## File Import/Export Card
|
||||
### File Import/Export Card
|
||||
|
||||
```rust
|
||||
use oc2r_rust::FileImportExport;
|
||||
use opencomputers::FileImportExport;
|
||||
|
||||
let mut fie = FileImportExport::attach(&mut bus)?.expect("no file card");
|
||||
fie.reset()?;
|
||||
@@ -154,7 +160,11 @@ fie.finish_export()?;
|
||||
|
||||
if fie.request_import()? {
|
||||
if let Some(info) = fie.begin_import()? {
|
||||
println!("importing {} ({} bytes)", info.name.unwrap_or_default(), info.size);
|
||||
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());
|
||||
@@ -163,9 +173,12 @@ if fie.request_import()? {
|
||||
}
|
||||
```
|
||||
|
||||
The raw event payloads for these devices can also be obtained via
|
||||
`Device::next_event`/`DeviceBus::next_event_for` when you need to handle
|
||||
custom packets.
|
||||
Device-specific events remain accessible through `Device::next_event` or
|
||||
`DeviceBus::next_event_for` when you need raw payloads.
|
||||
|
||||
Feel free to extend these wrappers or add new ones; each uses the same
|
||||
`define_wrapper!` macro found in `src/devices/mod.rs`.
|
||||
## 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.
|
||||
@@ -1,4 +1,5 @@
|
||||
use oc2r_core::{DEFAULT_DEVICE_PATH, DeviceBus, EventLoop, JsonValueExt, RedstoneInterface, Result};
|
||||
use oc2r_core::{DEFAULT_DEVICE_PATH, DeviceBus, EventLoop, JsonValueExt, Result};
|
||||
use opencomputers::RedstoneInterface;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Build with: cross build --release --example redstone
|
||||
|
||||
use oc2r_core::{DEFAULT_DEVICE_PATH, DeviceBus, RedstoneInterface, Result, Side};
|
||||
use oc2r_core::{DEFAULT_DEVICE_PATH, DeviceBus, Result};
|
||||
use opencomputers::{RedstoneInterface, Side};
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::Result;
|
||||
use crate::value::JsonValueExt;
|
||||
use oc2r_core::{JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
BlockOperations,
|
||||
"block_operations",
|
||||
"Wrapper for the block operations robot module."
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::Result;
|
||||
use crate::value::JsonValueExt;
|
||||
use oc2r_core::{JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(Cpu, "cpu", "Wrapper exposing CPU metadata.");
|
||||
crate::define_wrapper!(Cpu, "cpu", "Wrapper exposing CPU metadata.");
|
||||
|
||||
impl<'bus> Cpu<'bus> {
|
||||
pub fn frequency(&mut self) -> Result<i64> {
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::Result;
|
||||
use crate::value::JsonValueExt;
|
||||
use oc2r_core::{JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
EnergyStorage,
|
||||
"energy_storage",
|
||||
"Wrapper for OC2R energy storage devices."
|
||||
@@ -1,8 +1,6 @@
|
||||
use crate::value::JsonValueExt;
|
||||
use crate::{Error, JsonValue, Result};
|
||||
use miniserde::json::{Array, Number};
|
||||
use oc2r_core::{Error, JsonArray, JsonNumber, JsonValue, JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
FileImportExport,
|
||||
"file_import_export",
|
||||
"Wrapper for the file import/export card."
|
||||
@@ -28,8 +26,8 @@ impl<'bus> FileImportExport<'bus> {
|
||||
chunk
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|byte| JsonValue::Number(Number::U64(byte as u64)))
|
||||
.collect::<Array>(),
|
||||
.map(|byte| JsonValue::Number(JsonNumber::U64(byte as u64)))
|
||||
.collect::<JsonArray>(),
|
||||
);
|
||||
self.device.call("writeExportFile", (payload,)).map(|_| ())
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::value::JsonValueExt;
|
||||
use crate::{JsonValue, Result};
|
||||
use oc2r_core::{JsonValue, JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
FluidHandler,
|
||||
"fluid_handler",
|
||||
"Wrapper for Forge fluid handler devices."
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::Result;
|
||||
use crate::devices::RobotSide;
|
||||
use crate::value::JsonValueExt;
|
||||
use crate::RobotSide;
|
||||
use oc2r_core::{JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
InventoryOperations,
|
||||
"inventory_operations",
|
||||
"Wrapper for the inventory operations robot module."
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::value::JsonValueExt;
|
||||
use crate::{JsonValue, Result};
|
||||
use oc2r_core::{JsonValue, JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
ItemHandler,
|
||||
"item_handler",
|
||||
"Wrapper for Forge item handler devices."
|
||||
@@ -1,31 +1,32 @@
|
||||
//! Typed OC2R device wrappers built on top of `oc2r-core`.
|
||||
|
||||
macro_rules! define_wrapper {
|
||||
($name:ident, $type_name:literal, $doc:literal) => {
|
||||
#[doc = $doc]
|
||||
pub struct $name<'bus> {
|
||||
pub(crate) device: crate::Device<'bus>,
|
||||
pub(crate) device: oc2r_core::Device<'bus>,
|
||||
}
|
||||
|
||||
impl<'bus> $name<'bus> {
|
||||
pub const TYPE_NAME: &'static str = $type_name;
|
||||
|
||||
pub fn attach(bus: &'bus mut crate::DeviceBus) -> crate::Result<Option<Self>> {
|
||||
crate::devices::attach_device(bus, Self::TYPE_NAME)
|
||||
.map(|opt| opt.map(Self::from_device))
|
||||
pub fn attach(bus: &'bus mut oc2r_core::DeviceBus) -> oc2r_core::Result<Option<Self>> {
|
||||
crate::attach_device(bus, Self::TYPE_NAME).map(|opt| opt.map(Self::from_device))
|
||||
}
|
||||
|
||||
pub fn from_device(device: crate::Device<'bus>) -> Self {
|
||||
pub fn from_device(device: oc2r_core::Device<'bus>) -> Self {
|
||||
Self { device }
|
||||
}
|
||||
|
||||
pub fn info(&self) -> &crate::DeviceEntry {
|
||||
pub fn info(&self) -> &oc2r_core::DeviceEntry {
|
||||
self.device.info()
|
||||
}
|
||||
|
||||
pub fn as_device(&mut self) -> &mut crate::Device<'bus> {
|
||||
pub fn as_device(&mut self) -> &mut oc2r_core::Device<'bus> {
|
||||
&mut self.device
|
||||
}
|
||||
|
||||
pub fn into_device(self) -> crate::Device<'bus> {
|
||||
pub fn into_device(self) -> oc2r_core::Device<'bus> {
|
||||
self.device
|
||||
}
|
||||
}
|
||||
@@ -35,9 +36,9 @@ macro_rules! define_wrapper {
|
||||
pub(crate) use define_wrapper;
|
||||
|
||||
pub(crate) fn attach_device<'bus>(
|
||||
bus: &'bus mut crate::DeviceBus,
|
||||
bus: &'bus mut oc2r_core::DeviceBus,
|
||||
type_name: &str,
|
||||
) -> crate::Result<Option<crate::Device<'bus>>> {
|
||||
) -> oc2r_core::Result<Option<oc2r_core::Device<'bus>>> {
|
||||
match bus.find(type_name)? {
|
||||
Some(entry) => bus.device(&entry.device_id),
|
||||
None => Ok(None),
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::value::JsonValueExt;
|
||||
use crate::{DeviceEvent, Error, Result};
|
||||
use oc2r_core::{DeviceEvent, Error, JsonValueExt, Result};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
RedstoneInterface,
|
||||
"redstone",
|
||||
"Typed wrapper around the HLAPI redstone interface."
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::value::JsonValueExt;
|
||||
use crate::{Error, JsonValue, Result};
|
||||
use oc2r_core::{Error, JsonValue, JsonValueExt, Result};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
Robot,
|
||||
"robot",
|
||||
"High level wrapper mirroring the Lua robot helper."
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::Result;
|
||||
use crate::value::JsonValueExt;
|
||||
use oc2r_core::{JsonValueExt, Result};
|
||||
|
||||
crate::devices::define_wrapper!(
|
||||
crate::define_wrapper!(
|
||||
SoundCard,
|
||||
"sound",
|
||||
"Wrapper around the OC2R sound card HLAPI."
|
||||
Reference in New Issue
Block a user