pub struct Net { /* private fields */ }Expand description
The network connection: ctx.net. See the module docs.
Implementations§
Source§impl Net
impl Net
Sourcepub fn new(game: impl Into<String>) -> Self
pub fn new(game: impl Into<String>) -> Self
An offline network for the game game. Only clients with the same game name can join.
The engine creates this as ctx.net with the game title.
Sourcepub fn set_name(&mut self, name: impl Into<String>)
pub fn set_name(&mut self, name: impl Into<String>)
The name others see (default "Player", at most 32 characters). Set it before
Net::host or Net::join.
Examples found in repository?
54 fn on_ui(&mut self, event: &UiEvent, ctx: &mut Context) {
55 match event {
56 UiEvent::Changed { item, value, .. } if item == "name" => {
57 self.name = value.as_str().to_string();
58 ctx.storage.set("name", &self.name);
59 }
60 UiEvent::Changed { item, value, .. } if item == "address" => {
61 self.address = value.as_str().to_string();
62 ctx.storage.set("address", &self.address);
63 }
64 UiEvent::Activated { item, .. } => match item.as_str() {
65 "host" => {
66 ctx.net.set_name(&self.name);
67 match ctx.net.host(net::DEFAULT_PORT) {
68 Ok(()) => {
69 let address = Net::local_ip().map_or("unknown".to_string(), |ip| ip.to_string());
70 ctx.speak(format!("Hosting. Your address is {address}"));
71 Self::start_game(ctx);
72 }
73 Err(e) => ctx.ui.message("error", e.to_string()),
74 }
75 }
76 "join" => {
77 ctx.net.set_name(&self.name);
78 ctx.net.join(&self.address);
79 ctx.speak(format!("Connecting to {}", self.address));
80 }
81 "quit" => ctx.quit(),
82 _ => {}
83 },
84 _ => {}
85 }
86 }Sourcepub fn set_version(&mut self, version: impl Into<String>)
pub fn set_version(&mut self, version: impl Into<String>)
The version of your game, e.g. "1.2" (default empty). Clients with another version
cannot join, so old and new game code never meet. Set it before hosting or joining.
Sourcepub fn set_max_players(&mut self, max: usize)
pub fn set_max_players(&mut self, max: usize)
How many clients may join (default 32). The host does not count.
Sourcepub fn host(&mut self, port: u16) -> Result<()>
pub fn host(&mut self, port: u16) -> Result<()>
Starts a WebSocket server on port that others can join. Port 0 picks a free port
(see Net::port). Ends any connection that is open. Fails when the port is in use.
Any URL path is accepted, so a web server can pass on wss://example.com/game.
Players outside your local network need the host’s public address, and the port must be forwarded in the host’s router.
Examples found in repository?
54 fn on_ui(&mut self, event: &UiEvent, ctx: &mut Context) {
55 match event {
56 UiEvent::Changed { item, value, .. } if item == "name" => {
57 self.name = value.as_str().to_string();
58 ctx.storage.set("name", &self.name);
59 }
60 UiEvent::Changed { item, value, .. } if item == "address" => {
61 self.address = value.as_str().to_string();
62 ctx.storage.set("address", &self.address);
63 }
64 UiEvent::Activated { item, .. } => match item.as_str() {
65 "host" => {
66 ctx.net.set_name(&self.name);
67 match ctx.net.host(net::DEFAULT_PORT) {
68 Ok(()) => {
69 let address = Net::local_ip().map_or("unknown".to_string(), |ip| ip.to_string());
70 ctx.speak(format!("Hosting. Your address is {address}"));
71 Self::start_game(ctx);
72 }
73 Err(e) => ctx.ui.message("error", e.to_string()),
74 }
75 }
76 "join" => {
77 ctx.net.set_name(&self.name);
78 ctx.net.join(&self.address);
79 ctx.speak(format!("Connecting to {}", self.address));
80 }
81 "quit" => ctx.quit(),
82 _ => {}
83 },
84 _ => {}
85 }
86 }Sourcepub fn join(&mut self, address: &str)
pub fn join(&mut self, address: &str)
Joins the server at address: a host name or IP address, with or without port
("example.com", "192.168.1.20:7777", "[::1]:7777"), or a WebSocket URL
("ws://example.com:7777/", "wss://example.com/game"). Without a port,
DEFAULT_PORT is used (URLs: 80 for ws://, 443 for wss://). Ends any connection
that is open.
Returns at once. Later a NetEvent::Connected says the connection is ready, or a
NetEvent::Disconnected says why it failed (after at most about 10 seconds).
Examples found in repository?
54 fn on_ui(&mut self, event: &UiEvent, ctx: &mut Context) {
55 match event {
56 UiEvent::Changed { item, value, .. } if item == "name" => {
57 self.name = value.as_str().to_string();
58 ctx.storage.set("name", &self.name);
59 }
60 UiEvent::Changed { item, value, .. } if item == "address" => {
61 self.address = value.as_str().to_string();
62 ctx.storage.set("address", &self.address);
63 }
64 UiEvent::Activated { item, .. } => match item.as_str() {
65 "host" => {
66 ctx.net.set_name(&self.name);
67 match ctx.net.host(net::DEFAULT_PORT) {
68 Ok(()) => {
69 let address = Net::local_ip().map_or("unknown".to_string(), |ip| ip.to_string());
70 ctx.speak(format!("Hosting. Your address is {address}"));
71 Self::start_game(ctx);
72 }
73 Err(e) => ctx.ui.message("error", e.to_string()),
74 }
75 }
76 "join" => {
77 ctx.net.set_name(&self.name);
78 ctx.net.join(&self.address);
79 ctx.speak(format!("Connecting to {}", self.address));
80 }
81 "quit" => ctx.quit(),
82 _ => {}
83 },
84 _ => {}
85 }
86 }Sourcepub fn close(&mut self)
pub fn close(&mut self)
Leaves the game, or stops the server and sends every player away with
Reason::Closed. Called automatically when the game quits. Does nothing when
offline. Produces no events.
Examples found in repository?
231 fn update(&mut self, ctx: &mut Context) {
232 let step = vec3(
233 ctx.input.repeating(Key::Right, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Left, 0.25, 0.25) as i32 as f32,
234 ctx.input.repeating(Key::Up, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Down, 0.25, 0.25) as i32 as f32,
235 0.0,
236 );
237 if step != Vec3::ZERO {
238 self.position = (self.position + step).clamp(Vec3::splat(-20.0), Vec3::splat(20.0));
239 ctx.play("step");
240 if ctx.net.is_host() {
241 ctx.net.send_all(Packet::new("pos").with(PeerId::SERVER).with(self.position));
242 } else {
243 ctx.net.send_all(Packet::new("move").with(self.position));
244 }
245 }
246 ctx.audio.set_listener(self.position, 0.0);
247
248 if ctx.pressed(Key::Enter) {
249 ctx.ui.input("chat", "Message");
250 }
251 if ctx.pressed(Key::Space) {
252 let text = if self.others.is_empty() {
253 "Nobody else is here".to_string()
254 } else {
255 let places: Vec<String> = self
256 .others
257 .values()
258 .map(|o| format!("{}: {}", o.name, ctx.lang.describe_position(self.position, 0.0, o.position)))
259 .collect();
260 places.join(". ")
261 };
262 ctx.speak(text);
263 }
264 if ctx.pressed(Key::P) {
265 if ctx.net.is_host() {
266 ctx.speak(format!("You are the host, {} players connected", ctx.net.player_count()));
267 } else {
268 let ms = (ctx.net.ping(PeerId::SERVER) * 1000.0).round();
269 ctx.speak(format!("Ping {ms} milliseconds"));
270 }
271 }
272 if ctx.pressed(Key::Escape) {
273 ctx.net.close();
274 ctx.audio.stop_all();
275 ctx.speak("You left");
276 let scene = Lobby::new(ctx);
277 ctx.switch_scene(scene);
278 }
279 }Sourcepub fn kick(&mut self, peer: PeerId, reason: &str)
pub fn kick(&mut self, peer: PeerId, reason: &str)
Host: sends a player away. They get Reason::Kicked with reason (may be empty).
The host gets a NetEvent::Disconnected for them next frame.
Sourcepub fn send(&mut self, peer: PeerId, packet: impl Into<Packet>)
pub fn send(&mut self, peer: PeerId, packet: impl Into<Packet>)
Sends a packet to one peer. On a client, the only peer is PeerId::SERVER. Does
nothing if the peer is not connected.
Examples found in repository?
147 fn host_events(&mut self, event: &NetEvent, ctx: &mut Context) {
148 match event {
149 NetEvent::Connected(id) => {
150 let name = ctx.net.name(*id).to_string();
151 ctx.speak(format!("{name} joined"));
152 // Tell the newcomer about everybody, and everybody about the newcomer.
153 ctx.net.send(*id, Packet::new("player").with(PeerId::SERVER).with(ctx.net.name(PeerId::SERVER)).with(self.position));
154 for (other, o) in &self.others {
155 ctx.net.send(*id, Packet::new("player").with(*other).with(&o.name).with(o.position));
156 }
157 ctx.net.send_all_except(*id, Packet::new("player").with(*id).with(&name).with(Vec3::ZERO));
158 self.add(ctx, *id, &name, Vec3::ZERO);
159 }
160 NetEvent::Message(from, packet) => match packet.kind() {
161 "move" => {
162 self.moved(*from, packet.vec3(0));
163 ctx.net.send_all_except(*from, Packet::new("pos").with(*from).with(packet.vec3(0)));
164 }
165 "chat" => {
166 let text = packet.text(0);
167 ctx.play("chat");
168 ctx.speak(format!("{}: {text}", self.name(ctx, *from)));
169 ctx.net.send_all_except(*from, Packet::new("chat").with(*from).with(text));
170 }
171 _ => {}
172 },
173 NetEvent::Disconnected(id, _) => {
174 self.remove(ctx, *id);
175 ctx.net.send_all(Packet::new("gone").with(*id));
176 }
177 }
178 }Sourcepub fn send_all(&mut self, packet: impl Into<Packet>)
pub fn send_all(&mut self, packet: impl Into<Packet>)
Sends a packet to every connected peer. On a client that is the server.
Examples found in repository?
147 fn host_events(&mut self, event: &NetEvent, ctx: &mut Context) {
148 match event {
149 NetEvent::Connected(id) => {
150 let name = ctx.net.name(*id).to_string();
151 ctx.speak(format!("{name} joined"));
152 // Tell the newcomer about everybody, and everybody about the newcomer.
153 ctx.net.send(*id, Packet::new("player").with(PeerId::SERVER).with(ctx.net.name(PeerId::SERVER)).with(self.position));
154 for (other, o) in &self.others {
155 ctx.net.send(*id, Packet::new("player").with(*other).with(&o.name).with(o.position));
156 }
157 ctx.net.send_all_except(*id, Packet::new("player").with(*id).with(&name).with(Vec3::ZERO));
158 self.add(ctx, *id, &name, Vec3::ZERO);
159 }
160 NetEvent::Message(from, packet) => match packet.kind() {
161 "move" => {
162 self.moved(*from, packet.vec3(0));
163 ctx.net.send_all_except(*from, Packet::new("pos").with(*from).with(packet.vec3(0)));
164 }
165 "chat" => {
166 let text = packet.text(0);
167 ctx.play("chat");
168 ctx.speak(format!("{}: {text}", self.name(ctx, *from)));
169 ctx.net.send_all_except(*from, Packet::new("chat").with(*from).with(text));
170 }
171 _ => {}
172 },
173 NetEvent::Disconnected(id, _) => {
174 self.remove(ctx, *id);
175 ctx.net.send_all(Packet::new("gone").with(*id));
176 }
177 }
178 }
179
180 /// The client's side of the protocol.
181 fn client_events(&mut self, event: &NetEvent, ctx: &mut Context) {
182 match event {
183 NetEvent::Message(_, packet) => match packet.kind() {
184 "player" => self.add(ctx, packet.peer(0), packet.text(1), packet.vec3(2)),
185 "pos" => self.moved(packet.peer(0), packet.vec3(1)),
186 "gone" => self.remove(ctx, packet.peer(0)),
187 "chat" => {
188 ctx.play("chat");
189 ctx.speak(format!("{}: {}", self.name(ctx, packet.peer(0)), packet.text(1)));
190 }
191 _ => {}
192 },
193 NetEvent::Disconnected(_, reason) => {
194 ctx.speak(ctx.lang.describe_reason(reason));
195 ctx.audio.stop_all();
196 let scene = Lobby::new(ctx);
197 ctx.switch_scene(scene);
198 }
199 NetEvent::Connected(_) => {}
200 }
201 }
202}
203
204impl Scene for Field {
205 fn start(&mut self, ctx: &mut Context) {
206 ctx.speech.speak_queued("Arrows walk, Enter chats, Space finds the others, Escape leaves.");
207 }
208
209 fn on_net(&mut self, event: &NetEvent, ctx: &mut Context) {
210 if ctx.net.is_host() {
211 self.host_events(event, ctx);
212 } else {
213 self.client_events(event, ctx);
214 }
215 }
216
217 fn on_ui(&mut self, event: &UiEvent, ctx: &mut Context) {
218 if let UiEvent::TextSubmitted { id, text } = event
219 && id == "chat"
220 {
221 // The host sends to everybody, a client sends to the host, who passes it on.
222 if ctx.net.is_host() {
223 ctx.net.send_all(Packet::new("chat").with(PeerId::SERVER).with(text));
224 } else {
225 ctx.net.send_all(Packet::new("chat").with(text));
226 }
227 ctx.play("chat");
228 }
229 }
230
231 fn update(&mut self, ctx: &mut Context) {
232 let step = vec3(
233 ctx.input.repeating(Key::Right, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Left, 0.25, 0.25) as i32 as f32,
234 ctx.input.repeating(Key::Up, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Down, 0.25, 0.25) as i32 as f32,
235 0.0,
236 );
237 if step != Vec3::ZERO {
238 self.position = (self.position + step).clamp(Vec3::splat(-20.0), Vec3::splat(20.0));
239 ctx.play("step");
240 if ctx.net.is_host() {
241 ctx.net.send_all(Packet::new("pos").with(PeerId::SERVER).with(self.position));
242 } else {
243 ctx.net.send_all(Packet::new("move").with(self.position));
244 }
245 }
246 ctx.audio.set_listener(self.position, 0.0);
247
248 if ctx.pressed(Key::Enter) {
249 ctx.ui.input("chat", "Message");
250 }
251 if ctx.pressed(Key::Space) {
252 let text = if self.others.is_empty() {
253 "Nobody else is here".to_string()
254 } else {
255 let places: Vec<String> = self
256 .others
257 .values()
258 .map(|o| format!("{}: {}", o.name, ctx.lang.describe_position(self.position, 0.0, o.position)))
259 .collect();
260 places.join(". ")
261 };
262 ctx.speak(text);
263 }
264 if ctx.pressed(Key::P) {
265 if ctx.net.is_host() {
266 ctx.speak(format!("You are the host, {} players connected", ctx.net.player_count()));
267 } else {
268 let ms = (ctx.net.ping(PeerId::SERVER) * 1000.0).round();
269 ctx.speak(format!("Ping {ms} milliseconds"));
270 }
271 }
272 if ctx.pressed(Key::Escape) {
273 ctx.net.close();
274 ctx.audio.stop_all();
275 ctx.speak("You left");
276 let scene = Lobby::new(ctx);
277 ctx.switch_scene(scene);
278 }
279 }Sourcepub fn send_all_except(&mut self, except: PeerId, packet: impl Into<Packet>)
pub fn send_all_except(&mut self, except: PeerId, packet: impl Into<Packet>)
Sends a packet to every connected peer except one. The usual way for a host to pass on what one player did to everybody else.
Examples found in repository?
147 fn host_events(&mut self, event: &NetEvent, ctx: &mut Context) {
148 match event {
149 NetEvent::Connected(id) => {
150 let name = ctx.net.name(*id).to_string();
151 ctx.speak(format!("{name} joined"));
152 // Tell the newcomer about everybody, and everybody about the newcomer.
153 ctx.net.send(*id, Packet::new("player").with(PeerId::SERVER).with(ctx.net.name(PeerId::SERVER)).with(self.position));
154 for (other, o) in &self.others {
155 ctx.net.send(*id, Packet::new("player").with(*other).with(&o.name).with(o.position));
156 }
157 ctx.net.send_all_except(*id, Packet::new("player").with(*id).with(&name).with(Vec3::ZERO));
158 self.add(ctx, *id, &name, Vec3::ZERO);
159 }
160 NetEvent::Message(from, packet) => match packet.kind() {
161 "move" => {
162 self.moved(*from, packet.vec3(0));
163 ctx.net.send_all_except(*from, Packet::new("pos").with(*from).with(packet.vec3(0)));
164 }
165 "chat" => {
166 let text = packet.text(0);
167 ctx.play("chat");
168 ctx.speak(format!("{}: {text}", self.name(ctx, *from)));
169 ctx.net.send_all_except(*from, Packet::new("chat").with(*from).with(text));
170 }
171 _ => {}
172 },
173 NetEvent::Disconnected(id, _) => {
174 self.remove(ctx, *id);
175 ctx.net.send_all(Packet::new("gone").with(*id));
176 }
177 }
178 }Sourcepub fn events(&self) -> &[NetEvent]
pub fn events(&self) -> &[NetEvent]
Everything that happened on the network this frame, in order.
Sourcepub fn joined(&self) -> Vec<PeerId>
pub fn joined(&self) -> Vec<PeerId>
Players who connected this frame. On a client: PeerId::SERVER when the
connection became ready.
Sourcepub fn left(&self) -> Vec<(PeerId, Reason)>
pub fn left(&self) -> Vec<(PeerId, Reason)>
Players who left this frame and why. On a client: PeerId::SERVER when the
connection ended or could not be made.
Sourcepub fn messages(&self) -> Vec<(PeerId, Packet)>
pub fn messages(&self) -> Vec<(PeerId, Packet)>
All packets that arrived this frame, with their sender.
Sourcepub fn received(&self, kind: &str) -> Vec<(PeerId, Packet)>
pub fn received(&self, kind: &str) -> Vec<(PeerId, Packet)>
The packets of one kind that arrived this frame, with their sender.
Sourcepub fn players(&self) -> Vec<PeerId>
pub fn players(&self) -> Vec<PeerId>
The connected peers in the order they joined. Host: all clients. Client: the server, once connected.
Sourcepub fn player_count(&self) -> usize
pub fn player_count(&self) -> usize
Number of connected peers (the host does not count itself).
Examples found in repository?
231 fn update(&mut self, ctx: &mut Context) {
232 let step = vec3(
233 ctx.input.repeating(Key::Right, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Left, 0.25, 0.25) as i32 as f32,
234 ctx.input.repeating(Key::Up, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Down, 0.25, 0.25) as i32 as f32,
235 0.0,
236 );
237 if step != Vec3::ZERO {
238 self.position = (self.position + step).clamp(Vec3::splat(-20.0), Vec3::splat(20.0));
239 ctx.play("step");
240 if ctx.net.is_host() {
241 ctx.net.send_all(Packet::new("pos").with(PeerId::SERVER).with(self.position));
242 } else {
243 ctx.net.send_all(Packet::new("move").with(self.position));
244 }
245 }
246 ctx.audio.set_listener(self.position, 0.0);
247
248 if ctx.pressed(Key::Enter) {
249 ctx.ui.input("chat", "Message");
250 }
251 if ctx.pressed(Key::Space) {
252 let text = if self.others.is_empty() {
253 "Nobody else is here".to_string()
254 } else {
255 let places: Vec<String> = self
256 .others
257 .values()
258 .map(|o| format!("{}: {}", o.name, ctx.lang.describe_position(self.position, 0.0, o.position)))
259 .collect();
260 places.join(". ")
261 };
262 ctx.speak(text);
263 }
264 if ctx.pressed(Key::P) {
265 if ctx.net.is_host() {
266 ctx.speak(format!("You are the host, {} players connected", ctx.net.player_count()));
267 } else {
268 let ms = (ctx.net.ping(PeerId::SERVER) * 1000.0).round();
269 ctx.speak(format!("Ping {ms} milliseconds"));
270 }
271 }
272 if ctx.pressed(Key::Escape) {
273 ctx.net.close();
274 ctx.audio.stop_all();
275 ctx.speak("You left");
276 let scene = Lobby::new(ctx);
277 ctx.switch_scene(scene);
278 }
279 }Sourcepub fn is_connected_to(&self, peer: PeerId) -> bool
pub fn is_connected_to(&self, peer: PeerId) -> bool
Whether peer is connected right now.
Sourcepub fn name(&self, peer: PeerId) -> &str
pub fn name(&self, peer: PeerId) -> &str
The name a peer chose with Net::set_name, or "" if not connected. Your own
Net::id gives your own name.
Examples found in repository?
139 fn name(&self, ctx: &Context, id: PeerId) -> String {
140 if id == ctx.net.id() {
141 return ctx.net.name(id).to_string();
142 }
143 self.others.get(&id).map_or("Someone".to_string(), |o| o.name.clone())
144 }
145
146 /// The host's side of the protocol.
147 fn host_events(&mut self, event: &NetEvent, ctx: &mut Context) {
148 match event {
149 NetEvent::Connected(id) => {
150 let name = ctx.net.name(*id).to_string();
151 ctx.speak(format!("{name} joined"));
152 // Tell the newcomer about everybody, and everybody about the newcomer.
153 ctx.net.send(*id, Packet::new("player").with(PeerId::SERVER).with(ctx.net.name(PeerId::SERVER)).with(self.position));
154 for (other, o) in &self.others {
155 ctx.net.send(*id, Packet::new("player").with(*other).with(&o.name).with(o.position));
156 }
157 ctx.net.send_all_except(*id, Packet::new("player").with(*id).with(&name).with(Vec3::ZERO));
158 self.add(ctx, *id, &name, Vec3::ZERO);
159 }
160 NetEvent::Message(from, packet) => match packet.kind() {
161 "move" => {
162 self.moved(*from, packet.vec3(0));
163 ctx.net.send_all_except(*from, Packet::new("pos").with(*from).with(packet.vec3(0)));
164 }
165 "chat" => {
166 let text = packet.text(0);
167 ctx.play("chat");
168 ctx.speak(format!("{}: {text}", self.name(ctx, *from)));
169 ctx.net.send_all_except(*from, Packet::new("chat").with(*from).with(text));
170 }
171 _ => {}
172 },
173 NetEvent::Disconnected(id, _) => {
174 self.remove(ctx, *id);
175 ctx.net.send_all(Packet::new("gone").with(*id));
176 }
177 }
178 }Sourcepub fn ping(&self, peer: PeerId) -> f32
pub fn ping(&self, peer: PeerId) -> f32
The round trip time to a peer in seconds: how long a message takes there and back. Updated every second; 0.0 until measured or when not connected.
Examples found in repository?
231 fn update(&mut self, ctx: &mut Context) {
232 let step = vec3(
233 ctx.input.repeating(Key::Right, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Left, 0.25, 0.25) as i32 as f32,
234 ctx.input.repeating(Key::Up, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Down, 0.25, 0.25) as i32 as f32,
235 0.0,
236 );
237 if step != Vec3::ZERO {
238 self.position = (self.position + step).clamp(Vec3::splat(-20.0), Vec3::splat(20.0));
239 ctx.play("step");
240 if ctx.net.is_host() {
241 ctx.net.send_all(Packet::new("pos").with(PeerId::SERVER).with(self.position));
242 } else {
243 ctx.net.send_all(Packet::new("move").with(self.position));
244 }
245 }
246 ctx.audio.set_listener(self.position, 0.0);
247
248 if ctx.pressed(Key::Enter) {
249 ctx.ui.input("chat", "Message");
250 }
251 if ctx.pressed(Key::Space) {
252 let text = if self.others.is_empty() {
253 "Nobody else is here".to_string()
254 } else {
255 let places: Vec<String> = self
256 .others
257 .values()
258 .map(|o| format!("{}: {}", o.name, ctx.lang.describe_position(self.position, 0.0, o.position)))
259 .collect();
260 places.join(". ")
261 };
262 ctx.speak(text);
263 }
264 if ctx.pressed(Key::P) {
265 if ctx.net.is_host() {
266 ctx.speak(format!("You are the host, {} players connected", ctx.net.player_count()));
267 } else {
268 let ms = (ctx.net.ping(PeerId::SERVER) * 1000.0).round();
269 ctx.speak(format!("Ping {ms} milliseconds"));
270 }
271 }
272 if ctx.pressed(Key::Escape) {
273 ctx.net.close();
274 ctx.audio.stop_all();
275 ctx.speak("You left");
276 let scene = Lobby::new(ctx);
277 ctx.switch_scene(scene);
278 }
279 }Sourcepub fn id(&self) -> PeerId
pub fn id(&self) -> PeerId
Your own id: PeerId::SERVER for the host, the number the server gave you on a
client.
Sourcepub fn is_host(&self) -> bool
pub fn is_host(&self) -> bool
Whether this game is hosting.
Examples found in repository?
209 fn on_net(&mut self, event: &NetEvent, ctx: &mut Context) {
210 if ctx.net.is_host() {
211 self.host_events(event, ctx);
212 } else {
213 self.client_events(event, ctx);
214 }
215 }
216
217 fn on_ui(&mut self, event: &UiEvent, ctx: &mut Context) {
218 if let UiEvent::TextSubmitted { id, text } = event
219 && id == "chat"
220 {
221 // The host sends to everybody, a client sends to the host, who passes it on.
222 if ctx.net.is_host() {
223 ctx.net.send_all(Packet::new("chat").with(PeerId::SERVER).with(text));
224 } else {
225 ctx.net.send_all(Packet::new("chat").with(text));
226 }
227 ctx.play("chat");
228 }
229 }
230
231 fn update(&mut self, ctx: &mut Context) {
232 let step = vec3(
233 ctx.input.repeating(Key::Right, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Left, 0.25, 0.25) as i32 as f32,
234 ctx.input.repeating(Key::Up, 0.25, 0.25) as i32 as f32 - ctx.input.repeating(Key::Down, 0.25, 0.25) as i32 as f32,
235 0.0,
236 );
237 if step != Vec3::ZERO {
238 self.position = (self.position + step).clamp(Vec3::splat(-20.0), Vec3::splat(20.0));
239 ctx.play("step");
240 if ctx.net.is_host() {
241 ctx.net.send_all(Packet::new("pos").with(PeerId::SERVER).with(self.position));
242 } else {
243 ctx.net.send_all(Packet::new("move").with(self.position));
244 }
245 }
246 ctx.audio.set_listener(self.position, 0.0);
247
248 if ctx.pressed(Key::Enter) {
249 ctx.ui.input("chat", "Message");
250 }
251 if ctx.pressed(Key::Space) {
252 let text = if self.others.is_empty() {
253 "Nobody else is here".to_string()
254 } else {
255 let places: Vec<String> = self
256 .others
257 .values()
258 .map(|o| format!("{}: {}", o.name, ctx.lang.describe_position(self.position, 0.0, o.position)))
259 .collect();
260 places.join(". ")
261 };
262 ctx.speak(text);
263 }
264 if ctx.pressed(Key::P) {
265 if ctx.net.is_host() {
266 ctx.speak(format!("You are the host, {} players connected", ctx.net.player_count()));
267 } else {
268 let ms = (ctx.net.ping(PeerId::SERVER) * 1000.0).round();
269 ctx.speak(format!("Ping {ms} milliseconds"));
270 }
271 }
272 if ctx.pressed(Key::Escape) {
273 ctx.net.close();
274 ctx.audio.stop_all();
275 ctx.speak("You left");
276 let scene = Lobby::new(ctx);
277 ctx.switch_scene(scene);
278 }
279 }Sourcepub fn is_joining(&self) -> bool
pub fn is_joining(&self) -> bool
Whether a Net::join is still in progress.
Sourcepub fn local_ip() -> Option<IpAddr>
pub fn local_ip() -> Option<IpAddr>
This computer’s address in the local network, e.g. 192.168.1.20: what players in
the same network type to join. None without a network. Sends nothing.
Examples found in repository?
54 fn on_ui(&mut self, event: &UiEvent, ctx: &mut Context) {
55 match event {
56 UiEvent::Changed { item, value, .. } if item == "name" => {
57 self.name = value.as_str().to_string();
58 ctx.storage.set("name", &self.name);
59 }
60 UiEvent::Changed { item, value, .. } if item == "address" => {
61 self.address = value.as_str().to_string();
62 ctx.storage.set("address", &self.address);
63 }
64 UiEvent::Activated { item, .. } => match item.as_str() {
65 "host" => {
66 ctx.net.set_name(&self.name);
67 match ctx.net.host(net::DEFAULT_PORT) {
68 Ok(()) => {
69 let address = Net::local_ip().map_or("unknown".to_string(), |ip| ip.to_string());
70 ctx.speak(format!("Hosting. Your address is {address}"));
71 Self::start_game(ctx);
72 }
73 Err(e) => ctx.ui.message("error", e.to_string()),
74 }
75 }
76 "join" => {
77 ctx.net.set_name(&self.name);
78 ctx.net.join(&self.address);
79 ctx.speak(format!("Connecting to {}", self.address));
80 }
81 "quit" => ctx.quit(),
82 _ => {}
83 },
84 _ => {}
85 }
86 }Trait Implementations§
Auto Trait Implementations§
impl !Sync for Net
impl Freeze for Net
impl RefUnwindSafe for Net
impl Send for Net
impl Unpin for Net
impl UnsafeUnpin for Net
impl UnwindSafe for Net
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.