summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-02-07 18:49:39 +0100
committermetamuffin <metamuffin@disroot.org>2025-02-07 18:49:39 +0100
commit6f2db738f7845b7e75ca2e85b49db0c8b7eee213 (patch)
tree539cbcfb42d2ca4850717aa933a73ff55afe0375
parent422f4e8ebc02d10e41a0e1a8a570d95ba7943ee4 (diff)
downloadweareserver-6f2db738f7845b7e75ca2e85b49db0c8b7eee213.tar
weareserver-6f2db738f7845b7e75ca2e85b49db0c8b7eee213.tar.bz2
weareserver-6f2db738f7845b7e75ca2e85b49db0c8b7eee213.tar.zst
chat
-rw-r--r--client/src/chat.rs44
-rw-r--r--client/src/interfaces/chat.rs44
-rw-r--r--client/src/interfaces/mod.rs21
-rw-r--r--client/src/main.rs1
-rw-r--r--client/src/state.rs16
5 files changed, 120 insertions, 6 deletions
diff --git a/client/src/chat.rs b/client/src/chat.rs
new file mode 100644
index 0000000..e5580f5
--- /dev/null
+++ b/client/src/chat.rs
@@ -0,0 +1,44 @@
+/*
+ wearechat - generic multiplayer game with voip
+ Copyright (C) 2025 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+use crate::network::Network;
+use std::collections::VecDeque;
+use weareshared::packets::{Message, Object, Packet};
+
+pub struct Chat {
+ pub send_queue: VecDeque<String>,
+ pub history: VecDeque<String>,
+}
+impl Chat {
+ pub fn new() -> Self {
+ Self {
+ send_queue: VecDeque::new(),
+ history: VecDeque::new(),
+ }
+ }
+
+ pub fn incoming(&mut self, _ob: Object, msg: String) {
+ self.history.push_front(msg);
+ if self.history.len() > 128 {
+ self.history.pop_back();
+ }
+ }
+ pub fn update(&mut self, me: Object, net: &Network) {
+ for m in self.send_queue.drain(..) {
+ let _ = net.packet_send.send(Packet::Chat(me, Message(m)));
+ }
+ }
+}
diff --git a/client/src/interfaces/chat.rs b/client/src/interfaces/chat.rs
new file mode 100644
index 0000000..04b1f2c
--- /dev/null
+++ b/client/src/interfaces/chat.rs
@@ -0,0 +1,44 @@
+/*
+ wearechat - generic multiplayer game with voip
+ Copyright (C) 2025 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+use super::InterfaceData;
+use egui::{TextEdit, Widget};
+use std::sync::Arc;
+
+pub struct ChatInterface {
+ pub idata: Arc<InterfaceData>,
+ pub edit: String,
+}
+
+impl Widget for &mut ChatInterface {
+ fn ui(self, ui: &mut egui::Ui) -> egui::Response {
+ let mut chat = self.idata.chat.lock().unwrap();
+
+ ui.add(TextEdit::singleline(&mut self.edit));
+ if ui.button("Send").clicked() {
+ chat.send_queue.push_back(self.edit.clone());
+ self.edit.clear();
+ }
+
+ ui.group(|ui| {
+ for m in &chat.history {
+ ui.label(m);
+ }
+ });
+
+ ui.response()
+ }
+}
diff --git a/client/src/interfaces/mod.rs b/client/src/interfaces/mod.rs
index 9cbfbe3..0e419bc 100644
--- a/client/src/interfaces/mod.rs
+++ b/client/src/interfaces/mod.rs
@@ -14,15 +14,18 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+pub mod chat;
pub mod graphicsconfig;
pub mod prefabindex;
pub mod profiler;
use crate::{
+ chat::Chat,
download::Downloader,
network::Network,
render::{GraphicsConfig, scene::ScenePreparer, ui::UI_POSITION_OFFSET},
};
+use chat::ChatInterface;
use egui::{Pos2, Widget};
use graphicsconfig::GraphicsConfigInterface;
use prefabindex::PrefabIndexInterface;
@@ -36,6 +39,7 @@ enum Interface {
Profiler(Profiler),
PrefabIndex(PrefabIndexInterface),
GraphicsConfig(GraphicsConfigInterface),
+ Chat(ChatInterface),
}
pub struct InterfaceData {
@@ -46,6 +50,7 @@ pub struct InterfaceData {
pub render_timing: Arc<Mutex<TimingProfiler>>,
pub adapter_info: Arc<AdapterInfo>,
pub graphics_config: Arc<Mutex<(bool, GraphicsConfig)>>,
+ pub chat: Arc<Mutex<Chat>>,
}
pub fn ui_selector(idata: Arc<InterfaceData>) -> impl Fn(&egui::Context) -> bool {
@@ -58,6 +63,7 @@ pub fn ui_selector(idata: Arc<InterfaceData>) -> impl Fn(&egui::Context) -> bool
Interface::Profiler(_) => "Profiler",
Interface::PrefabIndex(_) => "Prefab Index",
Interface::GraphicsConfig(_) => "Graphics Configuration",
+ Interface::Chat(_) => "Chat",
})
.open(&mut open)
.default_pos(Pos2::new(UI_POSITION_OFFSET, UI_POSITION_OFFSET))
@@ -78,13 +84,18 @@ pub fn ui_selector(idata: Arc<InterfaceData>) -> impl Fn(&egui::Context) -> bool
idata: idata.clone(),
})
}
+ if ui.button("Chat").clicked() {
+ *state = Interface::Chat(ChatInterface {
+ idata: idata.clone(),
+ edit: Default::default(),
+ })
+ }
ui.response()
}
- Interface::Profiler(profiler) => profiler.ui(ui),
- Interface::PrefabIndex(prefab_index_interface) => prefab_index_interface.ui(ui),
- Interface::GraphicsConfig(graphics_config_interface) => {
- graphics_config_interface.ui(ui)
- }
+ Interface::Profiler(i) => i.ui(ui),
+ Interface::PrefabIndex(i) => i.ui(ui),
+ Interface::GraphicsConfig(i) => i.ui(ui),
+ Interface::Chat(i) => i.ui(ui),
});
open
}
diff --git a/client/src/main.rs b/client/src/main.rs
index 5fa790a..94057fe 100644
--- a/client/src/main.rs
+++ b/client/src/main.rs
@@ -25,6 +25,7 @@ pub mod network;
pub mod render;
pub mod state;
pub mod window;
+pub mod chat;
use anyhow::Result;
use clap::Parser;
diff --git a/client/src/state.rs b/client/src/state.rs
index c39e13a..eec9fde 100644
--- a/client/src/state.rs
+++ b/client/src/state.rs
@@ -17,6 +17,7 @@
use crate::{
audio::Audio,
camera::Camera,
+ chat::Chat,
download::Downloader,
interfaces::{InterfaceData, ui_selector},
network::Network,
@@ -25,7 +26,11 @@ use crate::{
use anyhow::{Context, Result};
use glam::{Vec2, Vec3};
use log::{info, warn};
-use std::{net::TcpStream, sync::Arc, time::Instant};
+use std::{
+ net::TcpStream,
+ sync::{Arc, Mutex},
+ time::Instant,
+};
use weareshared::{
packets::{Data, Object, Packet, Resource},
resources::PrefabIndex,
@@ -47,6 +52,7 @@ pub struct State<'a> {
pub prefab_index_res: Option<Resource<PrefabIndex>>,
pub avatar_ob: Option<Object>,
pub last_position_tx: Instant,
+ pub chat: Arc<Mutex<Chat>>,
}
pub struct InputState {
@@ -80,6 +86,7 @@ impl<'a> State<'a> {
avatar_ob: None,
prefab_index: PrefabIndex::default().into(),
last_position_tx: Instant::now(),
+ chat: Arc::new(Mutex::new(Chat::new())),
})
}
pub fn draw(&mut self) {
@@ -110,6 +117,7 @@ impl<'a> State<'a> {
render_timing: self.renderer.timing_submit.clone(),
adapter_info: self.renderer.adapter_info.clone(),
graphics_config: self.renderer.config_update.clone(),
+ chat: self.chat.clone(),
});
self.renderer
.ui_renderer
@@ -127,6 +135,7 @@ impl<'a> State<'a> {
for p in self.network.packet_recv.try_iter() {
self.downloader.packet(&p)?;
self.tree.packet(&p);
+
match &p {
Packet::PrefabIndex(res) => self.prefab_index_res = Some(res.to_owned()),
Packet::Sound(ob, data) => {
@@ -137,9 +146,13 @@ impl<'a> State<'a> {
}
}
}
+ Packet::Chat(ob, message) => {
+ self.chat.lock().unwrap().incoming(*ob, message.0.clone());
+ }
_ => (),
}
}
+
self.downloader
.update(&self.network)
.context("downloader state")?;
@@ -155,6 +168,7 @@ impl<'a> State<'a> {
}
if let Some(ob) = self.avatar_ob {
+ self.chat.lock().unwrap().update(ob, &self.network);
if self.last_position_tx.elapsed().as_secs_f32() > 0.1 {
self.network.packet_send.send(Packet::Position(
ob,