diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/Cargo.toml | 14 | ||||
-rw-r--r-- | client/src/client.rs | 128 | ||||
-rw-r--r-- | client/src/main.rs | 21 | ||||
-rw-r--r-- | client/src/window.rs | 39 |
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 => {} + _ => (), + } + } + } +} |