aboutsummaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/Cargo.toml14
-rw-r--r--client/src/client.rs128
-rw-r--r--client/src/main.rs21
-rw-r--r--client/src/window.rs39
4 files changed, 200 insertions, 2 deletions
diff --git a/client/Cargo.toml b/client/Cargo.toml
index 09c50c3..ab58a0f 100644
--- a/client/Cargo.toml
+++ b/client/Cargo.toml
@@ -4,3 +4,17 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+log = "0.4.22"
+env_logger = "0.11.6"
+anyhow = "1.0.95"
+arrayvec = "0.5.2"
+warn = ">=0.1.1,<0.3.0"
+
+winit = "0.30.8"
+
+twgame = { path = "../../twgame/twgame" }
+twgpu = { path = "../../twgpu/twgpu" }
+libtw2-gamenet-ddnet = { path = "../../libtw2/gamenet/ddnet" }
+libtw2-event-loop = { path = "../../libtw2/event-loop" }
+libtw2-packer = { path = "../../libtw2/packer" }
+libtw2-snapshot = { path = "../../libtw2/snapshot" } \ No newline at end of file
diff --git a/client/src/client.rs b/client/src/client.rs
new file mode 100644
index 0000000..0db4389
--- /dev/null
+++ b/client/src/client.rs
@@ -0,0 +1,128 @@
+use anyhow::Result;
+use arrayvec::ArrayVec;
+use libtw2_event_loop::{
+ Addr, Application, Chunk, ConnlessChunk, Loop, PeerId, SocketLoop, Timeout,
+};
+use libtw2_gamenet_ddnet::{
+ enums::{Team, VERSION},
+ msg::{
+ self, Game, System, SystemOrGame,
+ game::{ClSetTeam, ClStartInfo},
+ system::{EnterGame, Info, Ready},
+ },
+};
+use libtw2_packer::{Unpacker, with_packer};
+use log::warn;
+use std::{
+ fmt::{self, Debug},
+ net::{IpAddr, Ipv4Addr},
+};
+
+pub struct Client {}
+impl Client {
+ pub fn new() -> Result<Self> {
+ let mut sloop = SocketLoop::client();
+ sloop.connect(Addr {
+ ip: IpAddr::V4(Ipv4Addr::LOCALHOST),
+ port: 8303,
+ });
+ sloop.run(ClientNetwork {});
+ Ok(Self {})
+ }
+}
+
+pub struct ClientNetwork {}
+impl<L: Loop> Application<L> for ClientNetwork {
+ fn needs_tick(&mut self) -> Timeout {
+ Timeout::inactive()
+ }
+
+ fn on_tick(&mut self, loop_: &mut L) {}
+
+ fn on_packet(&mut self, loop_: &mut L, chunk: Chunk) {
+ let pid = chunk.pid;
+ let msg;
+ match msg::decode(&mut Warn(chunk.data), &mut Unpacker::new(chunk.data)) {
+ Ok(m) => msg = m,
+ Err(err) => {
+ warn!("decode error {:?}:", err);
+ return;
+ }
+ }
+ eprintln!("{msg:?}");
+ match msg {
+ SystemOrGame::System(System::MapChange(map)) => {
+ loop_.sends(pid, Ready);
+ }
+ SystemOrGame::System(System::ConReady(..)) => {
+ loop_.sendg(pid, ClStartInfo {
+ name: b"testclient",
+ clan: b"metamuffin",
+ country: -1,
+ skin: b"limekittygirl",
+ use_custom_color: true,
+ color_body: 0xFF00FF,
+ color_feet: 0x550055,
+ });
+ }
+ SystemOrGame::Game(Game::SvReadyToEnter(..)) => {
+ loop_.sends(pid, EnterGame);
+ loop_.sendg(pid, ClSetTeam { team: Team::Red });
+ }
+ _ => {}
+ }
+ }
+
+ fn on_connless_packet(&mut self, loop_: &mut L, chunk: ConnlessChunk) {}
+
+ fn on_connect(&mut self, loop_: &mut L, pid: PeerId) {
+ todo!()
+ }
+
+ fn on_ready(&mut self, loop_: &mut L, pid: PeerId) {
+ loop_.sends(pid, Info {
+ version: VERSION.as_bytes(),
+ password: Some(b""),
+ });
+ loop_.flush(pid);
+ }
+
+ fn on_disconnect(&mut self, loop_: &mut L, pid: PeerId, remote: bool, reason: &[u8]) {}
+}
+
+// Copied straight from libtw2/downloader/src/main.rs by heinrich5991, MIT-or-Apache-2.0
+trait LoopExt: Loop {
+ fn sends<'a, S: Into<System<'a>>>(&mut self, pid: PeerId, msg: S) {
+ fn inner<L: Loop + ?Sized>(msg: System, pid: PeerId, loop_: &mut L) {
+ let mut buf: ArrayVec<[u8; 2048]> = ArrayVec::new();
+ with_packer(&mut buf, |p| msg.encode(p).unwrap());
+ loop_.send(Chunk {
+ pid,
+ vital: true,
+ data: &buf,
+ })
+ }
+ inner(msg.into(), pid, self)
+ }
+ fn sendg<'a, G: Into<Game<'a>>>(&mut self, pid: PeerId, msg: G) {
+ fn inner<L: Loop + ?Sized>(msg: Game, pid: PeerId, loop_: &mut L) {
+ let mut buf: ArrayVec<[u8; 2048]> = ArrayVec::new();
+ with_packer(&mut buf, |p| msg.encode(p).unwrap());
+ loop_.send(Chunk {
+ pid,
+ vital: true,
+ data: &buf,
+ })
+ }
+ inner(msg.into(), pid, self)
+ }
+}
+impl<L: Loop> LoopExt for L {}
+
+struct Warn<'a>(&'a [u8]);
+
+impl<'a, W: Debug> warn::Warn<W> for Warn<'a> {
+ fn warn(&mut self, w: W) {
+ warn!("{:?}", w);
+ }
+}
diff --git a/client/src/main.rs b/client/src/main.rs
index e7a11a9..02b9055 100644
--- a/client/src/main.rs
+++ b/client/src/main.rs
@@ -1,3 +1,20 @@
-fn main() {
- println!("Hello, world!");
+use anyhow::Result;
+use client::Client;
+use window::WindowState;
+use winit::event_loop::EventLoop;
+
+pub mod window;
+pub mod client;
+
+fn main() -> Result<()> {
+ env_logger::init_from_env("LOG");
+
+ Client::new()?;
+
+
+ // let evloop = EventLoop::new()?;
+ // evloop.run_app(&mut WindowState::new())?;
+
+
+ Ok(())
}
diff --git a/client/src/window.rs b/client/src/window.rs
new file mode 100644
index 0000000..f003574
--- /dev/null
+++ b/client/src/window.rs
@@ -0,0 +1,39 @@
+use winit::{
+ application::ApplicationHandler,
+ event::WindowEvent,
+ event_loop::ActiveEventLoop,
+ window::{Window, WindowAttributes, WindowId},
+};
+
+pub struct WindowState {
+ window: Option<Window>,
+}
+
+impl WindowState {
+ pub fn new() -> Self {
+ Self { window: None }
+ }
+}
+impl ApplicationHandler for WindowState {
+ fn resumed(&mut self, event_loop: &ActiveEventLoop) {
+ self.window = Some(
+ event_loop
+ .create_window(WindowAttributes::default().with_maximized(true))
+ .unwrap(),
+ )
+ }
+
+ fn window_event(
+ &mut self,
+ event_loop: &ActiveEventLoop,
+ window_id: WindowId,
+ event: WindowEvent,
+ ) {
+ if let Some(win) = &self.window {
+ match event {
+ WindowEvent::RedrawRequested => {}
+ _ => (),
+ }
+ }
+ }
+}