Skip to content

Commit

Permalink
Merge pull request #625 from AmbientRun/connect-url
Browse files Browse the repository at this point in the history
Allow web client to join a custom url
  • Loading branch information
ten3roberts authored Jul 31, 2023
2 parents 63c2fc6 + eed5e2b commit efa0016
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ rustflags = ["--cfg=web_sys_unstable_apis"]

[alias]
campfire = "run --package campfire --"
campfire-ndf = "run --package campfire --no-default-features --"
cf = "run --package campfire --"

8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
- name: Check that guest/rust's documentation is well-formed
run: cd guest/rust && RUSTDOCFLAGS="-Dwarnings" cargo doc --workspace --all-features --no-deps
- name: Check that guest/rust builds under all configurations
run: cargo run -p campfire example check-all
run: cargo run -p campfire --no-default-features example check-all

build-web:
runs-on: ubuntu-20.04
Expand All @@ -117,13 +117,13 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
args: --package campfire
args: --package campfire --no-default-features

- name: "Build web client"
uses: actions-rs/cargo@v1
with:
command: run
args: --package campfire -- web build --profile release --target standalone
args: --package campfire --no-default-features -- web build --profile release --target standalone

- name: Upload package
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -214,7 +214,7 @@ jobs:
sudo apt install -y libxcb-xfixes0-dev mesa-vulkan-drivers
- name: Run golden image tests
run: cargo cf golden-images --ambient-path=./ambient check
run: cargo campfire-ndf golden-images --ambient-path=./ambient check
- uses: actions/upload-artifact@v3
if: always()
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deploy-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
args: --package campfire
args: --package campfire --no-default-features

- name: "Build web client"
uses: actions-rs/cargo@v1
with:
command: run
args: --package campfire -- web build --profile release --target standalone --pkg-name ${{ env.PACKAGE_NAME }}
args: --package campfire --no-default-features web build --profile release --target standalone --pkg-name ${{ env.PACKAGE_NAME }}

- name: Upload package
uses: actions/upload-artifact@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- run: rustup target add --toolchain stable wasm32-wasi
- name: Release all packages required for API
run: cargo run -p campfire release publish --execute
run: cargo run -p campfire-ndf release publish --execute

publish-release:
needs: [create-release, build-app, publish-api]
Expand Down
1 change: 1 addition & 0 deletions app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ async fn main() -> anyhow::Result<()> {
if let Some(mut host) = host.clone() {
if host.starts_with("http://") || host.starts_with("https://") {
tracing::info!("NOTE: Joining server by http url is still experimental and can be removed without warning.");

host = ReqwestClientKey
.get(&assets)
.get(host)
Expand Down
3 changes: 3 additions & 0 deletions campfire/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ openssl = { version = "0.10", features = ["vendored"], optional = true }

[target.'cfg(not(target_os="windows"))'.dependencies]
openssl = { version = "0.10", optional = true }

[features]
default = ["openssl"]
1 change: 0 additions & 1 deletion campfire/src/web/browser.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::time::Duration;

use anyhow::Context;
use base64::Engine;
use openssl::hash::MessageDigest;
use tokio::process::Command;

Expand Down
42 changes: 31 additions & 11 deletions crates/network/src/web/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ambient_renderer::RenderTarget;
use ambient_rpc::RpcRegistry;
use ambient_std::{
asset_cache::{AssetCache, SyncAssetKeyExt},
download_asset::ReqwestClientKey,
Cb,
};
use ambient_sys::{task::RuntimeHandle, time::sleep};
Expand Down Expand Up @@ -39,7 +40,7 @@ use super::ProxyMessage;
#[derive(Debug, Clone)]
pub struct GameClientView {
/// The url to connect to
pub url: Url,
pub url: String,
pub user_id: String,
pub systems_and_resources: Cb<dyn Fn() -> (SystemGroup, Entity) + Sync + Send>,
/// Invoked when the game client is loaded
Expand All @@ -62,6 +63,8 @@ impl ElementComponent for GameClientView {
inner,
} = *self;

let assets = hooks.world.resource(asset_cache()).clone();

let gpu = hooks.world.resource(gpu()).clone();

hooks.provide_context(|| {
Expand All @@ -70,8 +73,6 @@ impl ElementComponent for GameClientView {

let (render_target, _) = hooks.consume_context::<GameClientRenderTarget>().unwrap();

let assets = hooks.world.resource(asset_cache()).clone();

// The game client will be set once a connection establishes
let (client_state, set_client_state) = hooks.use_state(None as Option<ClientState>);

Expand All @@ -95,14 +96,15 @@ impl ElementComponent for GameClientView {
.with(game_screen_render_target(), render_target.0.clone());

let task = async move {
// NOTE: this is here to simulate a little connection delay to test the
// robustness for execution before connect etc
//
// TODO: remove once the web is fully working
tracing::info!("Sleeping for 2 seconds to simulate connection delay");
sleep(Duration::from_millis(2000)).await;

let conn = Connection::connect(url.clone()).await.with_context(|| {
let mut url = Url::parse(&url).context("Malformed Url")?;

if url.path() == "/servers/ensure-running" {
url = resolve_hosted_server(&assets, url).await?;
}

sleep(Duration::from_millis(1000)).await;

let conn = Connection::connect(&url.as_str()).await.with_context(|| {
format!("Failed to establish a WebTransport session to {url}")
})?;

Expand Down Expand Up @@ -425,3 +427,21 @@ async fn handle_request(
}
}
}

async fn resolve_hosted_server(assets: &AssetCache, url: Url) -> anyhow::Result<Url> {
tracing::debug!("Resolving hosted server at {url}");

let client = ReqwestClientKey.get(assets);

let res = client
.get(url)
.send()
.await
.context("Failed to resolve hosted server")?
.text()
.await
.context("Failed to get result for request")?;

Url::parse(&format!("https://{}", res.trim()))
.context("Expected a valid URL for host resolution")
}
11 changes: 6 additions & 5 deletions crates/network/src/webtransport/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ use std::{
task::{Context, Poll},
};

use anyhow::anyhow;
use anyhow::{anyhow, Context as _};
use bytes::Bytes;
use futures::{ready, Future};
use js_sys::Uint8Array;
use parking_lot::Mutex;
use url::Url;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{
Expand Down Expand Up @@ -42,12 +41,14 @@ impl Drop for Connection {

impl Connection {
/// Open a connection to `url`
pub async fn connect(url: Url) -> anyhow::Result<Self> {
let transport = WebTransport::new(url.as_str()).map_err(|e| anyhow!("{e:?}"))?;
pub async fn connect(url: &str) -> anyhow::Result<Self> {
let transport = WebTransport::new(url)
.map_err(|e| anyhow!("Failed to connect to game server. {e:?}"))?;

JsFuture::from(transport.ready())
.await
.map_err(|e| anyhow!("{e:?}"))?;
.map_err(|e| anyhow!("{e:?}"))
.context("While waiting for ready handshake")?;

tracing::info!("Connection ready");

Expand Down
25 changes: 3 additions & 22 deletions web/client/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,11 @@ use std::collections::HashMap;
use url::Url;

#[element_component]
pub fn MainApp(_hooks: &mut Hooks) -> Element {
let url = Url::parse("https://127.0.0.1:9000").unwrap();
pub fn MainApp(_hooks: &mut Hooks, server_url: String) -> Element {
tracing::info!("Connecting to {server_url:?}");

// FlowColumn(vec![
// Button::new("Dump native UI", |w| {
// let mut buf = Vec::new();
// dump_world_hierarchy(w, &mut buf);
// let s = String::from_utf8(buf).unwrap();
//
// tracing::info!("Dumping native UI: {}", s.len());
// ambient_sys::task::RuntimeHandle::current().spawn_local({
// async move {
// let s = s;
// ambient_sys::clipboard::set(&s).await;
// }
// });
// })
// .el(),
// Text::el(format!("Url: {url}")),
GameClientView {
url,
url: server_url,
user_id: friendly_id(),
systems_and_resources: cb(|| {
let mut resources = Entity::new();
Expand Down Expand Up @@ -68,9 +52,6 @@ pub fn MainApp(_hooks: &mut Hooks) -> Element {
inner: Dock::el(vec![GameView { show_debug: true }.el()]),
}
.el()
// ])
// .el()
// .with(space_between_items(), 10.)
}

/// Declares the systems to run in the network client world
Expand Down
16 changes: 9 additions & 7 deletions web/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ pub fn init_ambient(logging: bool, panic: bool) {
}

#[wasm_bindgen]
/// Starts execution of the ambient client
pub async fn start(target: Option<web_sys::HtmlElement>) {
if let Err(err) = run(target).await {
/// Starts execution of the ambient client and connects to the specified URL
///
/// TODO: The MainApp setup will move to an ember and this will only load the runtime
pub async fn start(target: Option<web_sys::HtmlElement>, server_url: String) {
if let Err(err) = run(target, server_url).await {
tracing::error!("{err:?}")
}
}

async fn run(target: Option<web_sys::HtmlElement>) -> anyhow::Result<()> {
async fn run(target: Option<web_sys::HtmlElement>, server_url: String) -> anyhow::Result<()> {
use ambient_sys::timer::TimerWheel;
ambient_sys::task::spawn(TimerWheel::new().start());

Expand All @@ -60,21 +62,21 @@ async fn run(target: Option<web_sys::HtmlElement>) -> anyhow::Result<()> {

tracing::info!("Finished building app");

init(&mut app).await;
init(&mut app, server_url).await;

// Spawn the event loop
app.spawn();

Ok(())
}

async fn init(app: &mut App) {
async fn init(app: &mut App, server_url: String) {
let world = &mut app.world;

Group(vec![
UICamera.el().with(active_camera(), 0.),
FocusRoot(vec![WindowSized::el([
MainApp::el().with(padding(), Borders::even(10.).into())
MainApp::el(server_url).with(padding(), Borders::even(10.).into())
])])
.el(),
])
Expand Down
2 changes: 1 addition & 1 deletion web/dioxus_example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn Ambient(cx: Scope) -> Element {
.unwrap()
.dyn_into::<web_sys::HtmlElement>()
.unwrap();
ambient_web::start(Some(element)).await;
ambient_web::start(Some(element), "127.0.0.1:9000".into()).await;
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion web/www/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@ import("ambient_web")
}

ambient.init_ambient(true, true);
ambient.start();
ambient.start(null, "https://api.ambient.run/servers/ensure-running?deployment_id=17zKiSVwEBHXiC0d8avbro");
// setupAudio();
});

0 comments on commit efa0016

Please sign in to comment.