Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory::ROOT is broken #545

Open
stefandollase opened this issue Nov 27, 2024 · 0 comments
Open

memory::ROOT is broken #545

stefandollase opened this issue Nov 27, 2024 · 0 comments

Comments

@stefandollase
Copy link

stefandollase commented Nov 27, 2024

The Rust API binding memory::ROOT for the Javascript Memory object is broken.

In the first tick after a global reset, everything works as intended. memory::ROOT is properly restored from the database and all changes to it are written to the database.

In all following ticks, memory::ROOT is not restored from the database and changes to it are not written to the database. However, it acts as if it was stored in the global object, i.e., it contains the same information as in the previous tick.

My explanation is, that the wasm binding does not properly handle that the Javascript Memory object is recreated by the Screeps engine each tick. Instead, it holds onto the object that was the Javascript Memory object in the first tick after the global reset.

This comment actually explains the issue, but the binding itself seems to cause it.

I use the steam client with a private docker server.

Related: #477 #538

Thanks for all your work!

Minimal Example

main.js

const bot = require("screeps-rust-playground");

bot.initialize_instance();

let first_run = true;

module.exports.loop = function() {
    if (first_run) {
        first_run = false;
        console.log("=================================");
    }

    console.log("before time in js:   " + Memory.time);
    bot.loop();
    console.log("after  time in js:   " + Memory.time);
}

lib.rs

use js_sys::{JsString, Reflect};
use log::info;
use screeps::game;
use wasm_bindgen::prelude::*;

mod logging;

static INIT_LOGGING: std::sync::Once = std::sync::Once::new();

#[wasm_bindgen(js_name = loop)]
pub fn game_loop() {
    INIT_LOGGING.call_once(|| {
        logging::setup_logging(logging::Debug);
    });

    let time_js = Reflect::get(&screeps::memory::ROOT, &JsString::from("time")).unwrap();
    info!("before time in rust: {time_js:?}");
    let new_time = time_js.as_f64().unwrap_or_else(|| game::time().into()) + 1.0;
    if !Reflect::set(&screeps::memory::ROOT, &JsString::from("time"), &JsValue::from_f64(new_time)).unwrap() {
        panic!("write failed");
    }
    let time_js = Reflect::get(&screeps::memory::ROOT, &JsString::from("time")).unwrap();
    info!("after  time in rust: {time_js:?}");
}

Console output (====== is a global reset caused by pressing CTRL+ENTER in main.js in the steam client)

[11:24:36 AM]before time in js:   7916
[11:24:36 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7951)
[11:24:36 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7952)
[11:24:36 AM]after  time in js:   7916
[11:24:41 AM]before time in js:   7916
[11:24:41 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7952)
[11:24:41 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7953)
[11:24:41 AM]after  time in js:   7916
[11:24:46 AM]before time in js:   7916
[11:24:46 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7953)
[11:24:46 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7954)
[11:24:46 AM]after  time in js:   7916
[11:24:51 AM]before time in js:   7916
[11:24:51 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7954)
[11:24:51 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7955)
[11:24:51 AM]after  time in js:   7916
[11:24:56 AM]=================================
[11:24:56 AM]before time in js:   7916
[11:24:56 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7916)
[11:24:56 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7917)
[11:24:56 AM]after  time in js:   7917
[11:25:01 AM]before time in js:   7917
[11:25:01 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7917)
[11:25:01 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7918)
[11:25:01 AM]after  time in js:   7917
[11:25:06 AM]before time in js:   7917
[11:25:06 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7918)
[11:25:06 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7919)
[11:25:06 AM]after  time in js:   7917
[11:25:11 AM]before time in js:   7917
[11:25:11 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7919)
[11:25:11 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7920)
[11:25:11 AM]after  time in js:   7917
[11:25:16 AM]before time in js:   7917
[11:25:16 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7920)
[11:25:16 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7921)
[11:25:16 AM]after  time in js:   7917
[11:25:21 AM]before time in js:   7917
[11:25:21 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7921)
[11:25:21 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7922)
[11:25:21 AM]after  time in js:   7917
[11:25:26 AM]=================================
[11:25:26 AM]before time in js:   7917
[11:25:26 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7917)
[11:25:26 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7918)
[11:25:26 AM]after  time in js:   7918
[11:25:31 AM]before time in js:   7918
[11:25:31 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7918)
[11:25:31 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7919)
[11:25:31 AM]after  time in js:   7918
[11:25:36 AM]before time in js:   7918
[11:25:36 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7919)
[11:25:36 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7920)
[11:25:36 AM]after  time in js:   7918
[11:25:41 AM]before time in js:   7918
[11:25:41 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7920)
[11:25:41 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7921)
[11:25:41 AM]after  time in js:   7918
[11:25:46 AM]=================================
[11:25:46 AM]before time in js:   7918
[11:25:46 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7918)
[11:25:46 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7919)
[11:25:46 AM]after  time in js:   7919
[11:25:51 AM]before time in js:   7919
[11:25:51 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7919)
[11:25:51 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7920)
[11:25:51 AM]after  time in js:   7919
[11:25:56 AM]before time in js:   7919
[11:25:56 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7920)
[11:25:56 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7921)
[11:25:56 AM]after  time in js:   7919
[11:26:01 AM]before time in js:   7919
[11:26:01 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7921)
[11:26:01 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7922)
[11:26:01 AM]after  time in js:   7919
[11:26:06 AM]before time in js:   7919
[11:26:06 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7922)
[11:26:06 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7923)
[11:26:06 AM]after  time in js:   7919
[11:26:11 AM]before time in js:   7919
[11:26:11 AM](INFO) screeps_rust_playground: before time in rust: JsValue(7923)
[11:26:11 AM](INFO) screeps_rust_playground: after  time in rust: JsValue(7924)
[11:26:11 AM]after  time in js:   7919

Temporary Workaround

As a temporary workaround, we can defer the read and write operations to Javascript.

main.js

const bot = require("screeps-rust-playground");

bot.initialize_instance();

module.exports.loop = function() {
    Memory.permanent_memory = bot.loop(Memory.permanent_memory);
}

lib.rs

#[wasm_bindgen(js_name = loop)]
pub fn game_loop(permanent_memory_string: Option<String>) -> String {
    // deserialize memory from string
    // do stuff
    // serialize memory to string and return it
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant