M crates/client/src/components.rs => crates/client/src/components.rs +6 -0
@@ 86,3 86,9 @@ pub struct ServerId(pub u32);
pub struct SendPacket(pub Packet);
#[derive(Event, Clone, PartialEq)]
pub struct RecvPacket(pub Packet);
+
+#[derive(Resource, Clone)]
+pub struct Chat {
+ pub messages: Vec<String>,
+ pub textbox: String,
+}
M crates/client/src/lib.rs => crates/client/src/lib.rs +7 -2
@@ 1,5 1,5 @@
use bevy_ecs::{event::Events, world::World};
-use components::{Camera, Part, Player, RecvPacket, SendPacket, Texture, Transform};
+use components::{Camera, Chat, Part, Player, RecvPacket, SendPacket, Texture, Transform};
use nalgebra::{Rotation2, Rotation3, Scale2, Scale3, Translation2, Translation3, Vector3};
use networking::ws::Ws;
use rendering::{assets::Assets, App};
@@ 49,8 49,13 @@ pub fn start() {
fuel_amount: 0,
fuel_max: 0,
});
+ world.insert_resource(Chat {
+ messages: vec![
+ ],
+ textbox: String::new(),
+ });
- let mut send_packet_events = Events::<SendPacket>::default();
+ let send_packet_events = Events::<SendPacket>::default();
let recv_packet_events = Events::<RecvPacket>::default();
world.spawn((
M crates/client/src/networking/mod.rs => crates/client/src/networking/mod.rs +5 -1
@@ 9,7 9,7 @@ use bevy_ecs::{
use nalgebra::{Rotation2, Scale2, Scale3, Translation3};
use starkingdoms_common::{packet::Packet, PartType, PlanetType};
-use crate::components::{Camera, Part, Planet, Player, PlayerResources, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture, Transform};
+use crate::components::{Camera, Chat, Part, Planet, Player, PlayerResources, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture, Transform};
#[cfg(target_arch = "wasm32")]
#[path = "ws_wasm.rs"]
@@ 203,6 203,10 @@ pub fn process_packets(
r.fuel_amount = *amount;
r.fuel_max = *max;
}
+ Message { message_type, actor, content } => {
+ let mut chat = world.get_resource_mut::<Chat>().unwrap();
+ chat.messages.push(format!("{}: {}", actor.clone(), content.clone()));
+ }
PlayerLeave { id } => {
let mut part_query = world.query_filtered::<(Entity, &ServerId), With<Part>>();
let mut entity_to_remove = None;
M crates/client/src/rendering/mod.rs => crates/client/src/rendering/mod.rs +9 -6
@@ 344,6 344,14 @@ impl ApplicationHandler for App {
window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
+ let event_response = self
+ .egui_glow
+ .as_mut()
+ .unwrap()
+ .on_window_event(self.window.as_ref().unwrap(), &event);
+ if event_response.consumed {
+ return;
+ }
match event {
WindowEvent::CloseRequested => {
event_loop.exit();
@@ 460,11 468,6 @@ impl ApplicationHandler for App {
}
_ => {}
}
- let event_response = self
- .egui_glow
- .as_mut()
- .unwrap()
- .on_window_event(self.window.as_ref().unwrap(), &event);
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
let mut ws = self
@@ 498,7 501,7 @@ impl ApplicationHandler for App {
.as_mut()
.unwrap()
.run(self.window.as_ref().unwrap(), |ctx| {
- draw_ui(ctx, &mut self.world);
+ draw_ui(ctx, &mut self.world, &mut self.send_packet_events);
});
let camera = self.world.get_resource::<Camera>().unwrap();
M crates/client/src/ui/mod.rs => crates/client/src/ui/mod.rs +47 -7
@@ 1,10 1,14 @@
mod colors;
mod widgets;
+use std::f32;
+
+use bevy_ecs::event::Events;
use bevy_ecs::prelude::With;
use bevy_ecs::world::World;
-use egui::{Align, Align2, CornerRadius, CursorIcon, Layout, Order, ProgressBar, RichText, Shadow, Stroke, Visuals};
-use crate::components::{Player, PlayerResources, Transform};
+use egui::{Align, Align2, CornerRadius, CursorIcon, Layout, Margin, Order, ProgressBar, RichText, Shadow, Stroke, Visuals};
+use starkingdoms_common::packet::Packet;
+use crate::components::{Chat, Player, PlayerResources, SendPacket, Transform};
use crate::ui::widgets::{progress_bar, RichTextExt};
pub fn init_ui(ctx: egui::Context) {
@@ 48,16 52,17 @@ pub fn init_ui(ctx: egui::Context) {
ctx.set_style(style);
}
-pub fn draw_ui(ctx: &egui::Context, world: &mut World) {
- draw_hud(ctx, world);
+pub fn draw_ui(ctx: &egui::Context, world: &mut World, send_packet_events: &mut Events<SendPacket>) {
+ draw_status_bar(ctx, world);
+ draw_chat(ctx, world, send_packet_events);
}
-pub fn draw_hud(ctx: &egui::Context, world: &mut World) {
+pub fn draw_status_bar(ctx: &egui::Context, world: &mut World) {
let mut player = world.query_filtered::<&Transform, With<Player>>();
let player_position = player.single(&world);
let player_resources = world.resource::<PlayerResources>();
- egui::Window::new("hud")
+ egui::Window::new("status_bar")
.title_bar(false)
.movable(false)
.resizable(false)
@@ 88,4 93,39 @@ pub fn draw_hud(ctx: &egui::Context, world: &mut World) {
})
});
});
-}>
\ No newline at end of file
+}
+
+pub fn draw_chat(ctx: &egui::Context, world: &mut World, send_packet_events: &mut Events<SendPacket>) {
+ let mut chat = world.get_resource_mut::<Chat>().unwrap();
+
+ egui::Window::new("Chat")
+ .movable(true)
+ .order(Order::Foreground)
+ .show(ctx, |ui| {
+ egui::Frame::new()
+ .inner_margin(Margin::same(5))
+ .corner_radius(2)
+ .fill(colors::CRUST)
+ .show(ui, |ui| {
+ egui::ScrollArea::vertical()
+ .max_width(f32::INFINITY)
+ .max_height(100.0)
+ .auto_shrink(false)
+ .stick_to_bottom(true)
+ .show(ui, |ui| {
+ for message in &chat.messages {
+ ui.label(message);
+ }
+ });
+ });
+ ui.horizontal(|ui| {
+ egui::TextEdit::singleline(&mut chat.textbox).show(ui);
+ if ui.button("Send").clicked() {
+ send_packet_events.send(SendPacket(Packet::SendMessage {
+ target: None,
+ content: chat.textbox.clone(),
+ }));
+ }
+ });
+ });
+}