aboutsummaryrefslogtreecommitdiff
path: root/client/src/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/client.rs')
-rw-r--r--client/src/client.rs128
1 files changed, 128 insertions, 0 deletions
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);
+ }
+}