Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ run-data

repo

.DS_Store
.DS_Store
2 changes: 2 additions & 0 deletions rustedcomputer-rs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
target/
65 changes: 65 additions & 0 deletions rustedcomputer-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions rustedcomputer-rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "rustedcomputer"
version = "0.1.0"
edition = "2024"
license = "MPL-2.0"
description = "Programmable Computers in Minecraft with WebAssembly"
homepage = "https://github.com/TheBlckbird/rustedcomputer"
repository = "https://github.com/TheBlckbird/rustedcomputer"
readme = "Readme.md"

[dependencies]
thiserror = "2.0.16"
3 changes: 3 additions & 0 deletions rustedcomputer-rs/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Rusted Computer

This is a reserved crate. It will later be the wrapper crate for [github.com/TheBlckbird/rustedcomputer](https://github.com/TheBlckbird/rustedcomputer).
23 changes: 23 additions & 0 deletions rustedcomputer-rs/src/async_runtime/future_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::ops::{Deref, DerefMut};

pub struct FutureId(i32);

impl From<i32> for FutureId {
fn from(value: i32) -> Self {
Self(value)
}
}

impl Deref for FutureId {
type Target = i32;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for FutureId {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
95 changes: 95 additions & 0 deletions rustedcomputer-rs/src/async_runtime/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::pin::Pin;
use std::{ptr, slice, thread};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
use std::time::Duration;
use crate::async_runtime::future_id::FutureId;
use crate::error::{Result, RustedComputerError};

pub mod future_id;

pub struct RustedComputerFuture<T, F>
where
F: Fn(String) -> T,
{
pub id: FutureId,
pub converter: F,
}

impl<T, F> RustedComputerFuture<T, F>
where
F: Fn(String) -> T,
{
pub fn new<G>(caller: G, converter: F) -> Self
where
G: Fn() -> FutureId,
{
let id = caller();
Self { id, converter }
}
}

impl<T, F> Future for RustedComputerFuture<T, F>
where
F: Fn(String) -> T,
{
type Output = Result<T>;

fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
let poll_result = unsafe { poll(*self.id) };

let length = (poll_result & 0xFFFFFFFF) as usize;
let pointer = (poll_result >> 32) as *mut u8;

let slice = unsafe { slice::from_raw_parts_mut(pointer, length) };
let boxed_slice = unsafe { Box::from_raw(slice) };
let future = str::from_utf8(&boxed_slice).unwrap();

if future == "P" {
Poll::Pending
} else if future == "F" {
Poll::Ready(Err(RustedComputerError::FutureFailed))
} else if future.starts_with("S") {
let future_result = future[1..].to_owned();
let converted_result = (self.converter)(future_result);

Poll::Ready(Ok(converted_result))
} else {
unreachable!()
}
}
}

fn noop_raw_waker() -> RawWaker {
fn clone(_: *const ()) -> RawWaker {
noop_raw_waker()
}
fn no_op(_: *const ()) {}

static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, no_op, no_op, no_op);
RawWaker::new(ptr::null(), &VTABLE)
}

fn noop_waker() -> Waker {
unsafe { Waker::from_raw(noop_raw_waker()) }
}

pub fn block_on<F: Future>(mut future: F) -> F::Output {
let mut future = unsafe { Pin::new_unchecked(&mut future) };
let waker = noop_waker();
let mut cx = Context::from_waker(&waker);

loop {
match future.as_mut().poll(&mut cx) {
Poll::Ready(val) => return val,
Poll::Pending => {
thread::sleep(Duration::from_millis(100));
}
}
}
}

#[link(wasm_import_module = "future")]
unsafe extern "C" {
#[link_name = "poll"]
pub fn poll(future_id: i32) -> i64;
}
11 changes: 11 additions & 0 deletions rustedcomputer-rs/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum RustedComputerError {
#[error("Future failed to resolve")]
FutureFailed,
#[error("Future had a timeout")]
FutureTimeout,
}

pub type Result<T, E = RustedComputerError> = std::result::Result<T, E>;
1 change: 1 addition & 0 deletions rustedcomputer-rs/src/functions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod redstone;
34 changes: 34 additions & 0 deletions rustedcomputer-rs/src/functions/redstone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::async_runtime::RustedComputerFuture;
use crate::error::Result;
use crate::side::Side;

pub async fn set_output(side: Side, power: u8) -> Result<()> {
let side = side.to_string();
let side_length = side.len() as i32;
let side_offset = side.as_ptr() as i32;

let caller = || unsafe { ext_set_output(side_length, side_offset, power as i32) }.into();
let converter = |_| ();

RustedComputerFuture::new(caller, converter).await
}

pub async fn get_input(side: Side) -> Result<u8> {
let side = side.to_string();
let side_length = side.len() as i32;
let side_offset = side.as_ptr() as i32;

let caller = || unsafe { ext_get_input(side_length, side_offset) }.into();
let converter = |value: String| value.parse().unwrap();

RustedComputerFuture::new(caller, converter).await
}

#[link(wasm_import_module = "redstone")]
unsafe extern "C" {
#[link_name = "set_output"]
fn ext_set_output(side_length: i32, side_offset: i32, power: i32) -> i32;

#[link_name = "get_input"]
fn ext_get_input(side_length: i32, side_offset: i32) -> i32;
}
11 changes: 11 additions & 0 deletions rustedcomputer-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub mod async_runtime;
pub mod side;
pub mod functions;
pub mod error;

#[unsafe(no_mangle)]
pub extern "C" fn alloc(length: i32) -> i32 {
let buffer = vec![0u8; length as usize];
let boxed_slice = buffer.into_boxed_slice();
Box::into_raw(boxed_slice) as *mut u8 as i32
}
25 changes: 25 additions & 0 deletions rustedcomputer-rs/src/side.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::fmt::{Display, Formatter, write};

pub enum Side {
Top,
Bottom,
Left,
Right,
Front,
Back,
}

impl Display for Side {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let out = match self {
Side::Top => "top",
Side::Bottom => "bottom",
Side::Left => "left",
Side::Right => "right",
Side::Front => "front",
Side::Back => "back",
};

write!(f, "{out}")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ enum class RelativeDirection {
else -> null
}
}

fun fromString(string: String): RelativeDirection? {
return when(string.lowercase()) {
"top" -> TOP
"bottom" -> BOTTOM
"left" -> LEFT
"right" -> RIGHT
"front" -> FRONT
"back" -> BACK
else -> null
}
}
}

fun toInt(): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import dev.theblckbird.rustedcomputer.RustedComputer
import dev.theblckbird.rustedcomputer.RelativeDirection
import dev.theblckbird.rustedcomputer.computer.ComputerObservations
import dev.theblckbird.rustedcomputer.computer.ComputerScreenHolder
import dev.theblckbird.rustedcomputer.computer.hostfunctions.HostFunctions
import dev.theblckbird.rustedcomputer.computer.MinecraftTimeClock
import dev.theblckbird.rustedcomputer.computer.hostfunctions.infrastructure.FutureFunctions
import dev.theblckbird.rustedcomputer.computer.hostfunctions.redstone.RedstoneFunctions
import dev.theblckbird.rustedcomputer.computer.networking.toclient.stdout.StdoutData
import dev.theblckbird.rustedcomputer.helpers.SaveFileHelper
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -104,11 +105,13 @@ class ComputerBlockEntity(position: BlockPos, state: BlockState) :

val wasi = WasiPreview1.builder().withOptions(options).build()

val hostFunctions = HostFunctions()
val redstoneFunctions = RedstoneFunctions(level, blockPos)
val futureFunctions = FutureFunctions()

val store = Store()
.addFunction(*wasi.toHostFunctions())
.addFunction(*hostFunctions.toHostFunctions())
.addFunction(*redstoneFunctions.toHostFunctions())
.addFunction(*futureFunctions.toHostFunctions())

val resourceManager = level.server.resourceManager
val romFileLocation = ResourceLocation.fromNamespaceAndPath(RustedComputer.MODID, "rom/$fileName")
Expand All @@ -132,7 +135,7 @@ class ComputerBlockEntity(position: BlockPos, state: BlockState) :
)
}
} else {
writelnStdout("Couldn't find file $fileName")
writelnStdout("Can't find file $fileName")
}
}

Expand Down

This file was deleted.

Loading