Skip to content

Commit

Permalink
Simplify NetworkingMessages example
Browse files Browse the repository at this point in the history
  • Loading branch information
Noxime committed Sep 15, 2024
1 parent 9b99d7e commit e9d0332
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 84 deletions.
2 changes: 1 addition & 1 deletion examples/networking-messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ edition = "2021"

[dependencies]
steamworks = { path = "../.." }
eframe = "0.28.1"
macroquad = "0.4"
6 changes: 3 additions & 3 deletions examples/networking-messages/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# NetworkingMessages Example

This example demonstrates how to use the NetworkingMessages API to send and receive messages between friends playing the
same game. You can use any SteamID, doesn't have to be a friend. For example, networking messages can be with the steam
matchmaking service.
This example demonstrates how to use the NetworkingMessages API to send and receive messages over the network. It sends
the mouse position to all friends playing the same game. Green circle is your local player and red circles are your
friends.

## Note
To use this example, you need to have two instances on two machines with two steam accounts running at the same time.
134 changes: 54 additions & 80 deletions examples/networking-messages/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use eframe::{egui::*, *};
use std::collections::HashMap;

use macroquad::prelude::*;
use steamworks::{
networking_types::{NetworkingIdentity, SendFlags},
FriendFlags,
};

fn main() -> eframe::Result {
#[macroquad::main("steamworks-rs")]
async fn main() {
// 480 is Spacewar!, the Steamworks SDK example app.
let client =
steamworks::Client::init_app(480).expect("Steam is not running or has not been detected");
Expand All @@ -25,84 +28,55 @@ fn main() -> eframe::Result {
eprintln!("Session failed: {info:#?}");
});

// UI state
let mut text_field = "Hello, world!".to_string();
let mut message_history = vec![];
// Keep track of all players
let mut peers = HashMap::new();

run_simple_native("steamworks-rs", Default::default(), move |ctx, _| {
// Run callback periodically, this is usually your main game loop or networking thread
loop {
// Poll the internal callbacks
client.run_callbacks();
ctx.request_repaint();

CentralPanel::default().show(ctx, |ui| {
let text_height = ui.text_style_height(&TextStyle::Body);

// Get a list of friends who are playing Spacewar!
let mut friend_list = friends.get_friends(FriendFlags::IMMEDIATE);
friend_list.retain(|f| f.game_played().map_or(false, |g| g.game.app_id().0 == 480));

// Show the friend list
SidePanel::left("friends").show_inside(ui, |ui| {
ui.heading(format!("Logged in: {}", friends.name()));
ui.label(format!("Online friends: {}", friend_list.len()));

// Show the list of friends
ScrollArea::both().show_rows(ui, text_height, friend_list.len(), |ui, range| {
for friend in &friend_list[range] {
ui.monospace(friend.name());
}
});
});

// Receive any pending messages
let new_messages = messages.receive_messages_on_channel(0, 10);
for msg in new_messages {
println!("Received message #{:?}", msg.message_number());

let peer = msg.identity_peer();
let data = std::str::from_utf8(msg.data()).expect("Peer sent invalid UTF-8");

message_history.push(format!("{peer:?}: {data}"));
}

// Show message history
ui.heading(format!("Chat history ({} messages)", message_history.len()));
ScrollArea::both().auto_shrink([false, true]).show_rows(
ui,
text_height,
message_history.len(),
|ui, range| {
for msg in &message_history[range] {
ui.label(msg);
}
},
);

// Text box for inputting a message and a button to send it
TopBottomPanel::bottom("textbox").show_inside(ui, |ui| {
ui.horizontal(|ui| {
ui.text_edit_singleline(&mut text_field).request_focus();

// Send message to all friends
if ui.button("Send message").clicked() {
for friend in &friend_list {
println!("Sending to {:?}", friend.id());

if let Err(err) = messages.send_message_to_user(
NetworkingIdentity::new_steam_id(friend.id()),
SendFlags::RELIABLE,
text_field.as_bytes(),
0,
) {
eprintln!("Send error: {err:?}");
}
}

// We can't send message to ourselves, so add it to chat history manually
message_history.push(format!("Me: {text_field}"));
}
});
});
});
})

clear_background(BLACK);

set_camera(&Camera2D::from_display_rect(Rect::new(
-1.0, 1.0, 2.0, -2.0,
)));

// Draw us at our mouse position
let me = mouse_position_local();
draw_circle(me.x, me.y, 0.1, GREEN);

// Send our mouse position to all friends
for friend in friends.get_friends(FriendFlags::IMMEDIATE) {
let identity = NetworkingIdentity::new_steam_id(friend.id());

// Convert our position to bytes
let mut data = [0; 8];
data[0..4].copy_from_slice(&me.x.to_le_bytes());
data[4..8].copy_from_slice(&me.y.to_le_bytes());

let _ =
messages.send_message_to_user(identity, SendFlags::UNRELIABLE_NO_DELAY, &data, 0);
}

// Receive messages from the network
for message in messages.receive_messages_on_channel(0, 100) {
let peer = message.identity_peer();
let data = message.data();

// Convert peer position from bytes
let peer_x =
f32::from_le_bytes(data[0..4].try_into().expect("Someone sent bad message"));
let peer_y =
f32::from_le_bytes(data[4..8].try_into().expect("Someone sent bad message"));

peers.insert(peer.debug_string(), (peer_x, peer_y));
}

// Draw all peers
for peer in peers.values() {
draw_circle(peer.0, peer.1, 0.1, RED);
}

next_frame().await;
}
}

0 comments on commit e9d0332

Please sign in to comment.