summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: da841335622be617212ded6e6649d2dfb71ff2a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use clap::Parser;
use futures_util::future::OptionFuture;
use mt_net::{ReceiverExt, SenderExt, ToCltPkt, ToSrvPkt};
use std::pin::Pin;
use std::time::Duration;
use tokio::time::{sleep, Sleep};

#[derive(Parser, Debug)]
#[clap(version, about, long_about = None)]
struct Args {
    /// Server address. Format: address:port
    #[clap(value_parser)]
    address: String,

    /// Quit QUIT_AFTER seconds after authentication
    #[clap(short, long, value_parser)]
    quit_after: Option<f32>,

    /// Player name
    #[clap(short, long, value_parser, default_value = "texmodbot")]
    username: String,

    /// Password
    #[clap(short, long, value_parser, default_value = "owo")]
    password: String,
}

#[tokio::main]
async fn main() {
    let Args {
        address,
        quit_after,
        username,
        password,
    } = Args::parse();

    let (tx, mut rx, worker) = mt_net::connect(&address).await.unwrap();

    let mut auth = mt_auth::Auth::new(tx.clone(), username, password, "en_US");
    let worker = tokio::spawn(worker.run());

    let mut quit_sleep: Option<Pin<Box<Sleep>>> = None;

    loop {
        tokio::select! {
            pkt = rx.recv() => match pkt {
                None => break,
                Some(Err(e)) => eprintln!("{e}"),
                Some(Ok(pkt)) => {
                    use ToCltPkt::*;

                    auth.handle_pkt(&pkt).await;

                    match pkt {
                        NodeDefs(defs) => {
                            defs.0
                                .values()
                                .flat_map(|def| {
                                    std::iter::empty()
                                        .chain(&def.tiles)
                                        .chain(&def.special_tiles)
                                        .chain(&def.overlay_tiles)
                                })
                                .map(|tile| &tile.texture.name)
                                .for_each(|texture| {
                                    if !texture.is_empty() {
                                        println!("{texture}");
                                    }
                                });

                            quit_sleep = quit_after.and_then(|x| {
                                if x >= 0.0 {
                                    Some(Box::pin(sleep(Duration::from_secs_f32(x))))
                                } else {
                                    None
                                }
                            });
                        }
                        Kick(reason) => {
                            eprintln!("kicked: {reason}");
                        }
                        _ => {}
                    }
                }
            },
            _ = auth.poll() => {
                tx
                    .send(&ToSrvPkt::CltReady {
                        major: 0,
                        minor: 0,
                        patch: 0,
                        reserved: 0,
                        version: "https://github.com/LizzyFleckenstein03/texmodbot".into(),
                        formspec: 4,
                    })
                    .await
                    .unwrap();
            },
            Some(_) = OptionFuture::from(quit_sleep.as_mut()) => {
                tx.close();
            }
            _ = tokio::signal::ctrl_c() => {
                tx.close();
            }
        }
    }

    worker.await.unwrap();
}