These are chat archives for rust-lang/rust

21st
May 2016
mhsjlw
@mhsjlw
May 21 2016 00:18
hi, why when I create the player outside of the if statement then successfully modify the name attribute can I not reuse it inside of the 0x0d statement... ? (the value is "steve" the default value meaning it was not actually changed)
fn handle_packet(packet: Packet, conn: &mut TcpStream, mutex_world: &Arc<Mutex<World>>) {
  let mut player = Player {name: "steve".to_string(), x: 0, y: 0, z: 0, yaw: 0, pitch: 0, stream: conn};
  if packet.packet_id == 0x00 {
    let parsed = packet.parse_player_ident();
    player.name = parsed.username;
    println!("{} has joined the game", player.name);

    player.stream.send_server_ident("Server".to_string(), "Welcome to my Server".to_string());
    player.stream.send_level_init();

    let mut level = mutex_world.lock().unwrap();
    level.send_world(player.stream);

    player.stream.send_pos(5 * 32, 25 * 32, 5 * 32, 5, 5, -1);
    } else if packet.packet_id == 0x08 {
      let parsed = packet.parse_position_and_orientation();
      //println!("player has moved");
    } else if packet.packet_id == 0x05 {
      let parsed = packet.parse_set_block();
      println!("player has setblock");
    } else if packet.packet_id == 0x0d {
      let parsed = packet.parse_message();
      println!("<{}> {}", player.name, parsed.message);
    }
}
do I not change it 'globally', just for inside the statement ?
Erik Hedvall
@Ogeon
May 21 2016 10:12
You are not changing it outside any branch
mhsjlw
@mhsjlw
May 21 2016 10:16
how can I do that?
because once I get the data I want it to be changed so I can access it again
(From another branch)
Erik Hedvall
@Ogeon
May 21 2016 10:18
I'm not sure how you want it to work. What you have now is something that takes a packet, creates a new player, and picks one of the branches, based in its id.
Zakarum
@omni-viral
May 21 2016 10:25
@mhsjlw where exactly in code do you see that name hasn't been changed?
In the last else if?
Of course it is not changed there. Cause you change it only in first if branch.
Erik Hedvall
@Ogeon
May 21 2016 10:26
Is the player meant to be global? In that case you want to take it as a parameter to handle_packet.
Zakarum
@omni-viral
May 21 2016 10:27
I see there is indentation problem
else if blocks have 2 more spaces than first if block
As if those else if should be nested in first if blocks
Maybe they should? That's would explain why @mhsjlw expect changed name to be printed in last println!
mhsjlw
@mhsjlw
May 21 2016 10:30
HM
t
lol my keyboard
Sorry, yeah I expect it to change in the first
that always happens first
Zakarum
@omni-viral
May 21 2016 10:33
So what this code supposed to do?
Crete player on first packet with id 0. Then use it on next packets ?
Erik Hedvall
@Ogeon
May 21 2016 10:33
Is it mean to be like this: get a packet -> execute one of the branches -> get a packet -> execute one of the branches -> ..., while remembering the player changes?
Zakarum
@omni-viral
May 21 2016 10:33
If that's true - you have to save created player somewhere
In the World maybe
And then acquire it for there
But you can't save Player object with pointer to TcpStream
mhsjlw
@mhsjlw
May 21 2016 10:36
@Ogeon yup!
Erik Hedvall
@Ogeon
May 21 2016 10:37
Yeah, then your general structure is good, but the player has to be saved to and acquired from outside the function
Zakarum
@omni-viral
May 21 2016 10:38
And remove stream field
And add some id: u64 field instead
Erik Hedvall
@Ogeon
May 21 2016 10:39
That depends on how things works. The username may be the id
Zakarum
@omni-viral
May 21 2016 10:39
If you use mio then you can use Token associated with stream
@Ogeon Maybe. If each packet contains name
Erik Hedvall
@Ogeon
May 21 2016 10:40
I don't know the protocol
Zakarum
@omni-viral
May 21 2016 10:40
So do I
Erik Hedvall
@Ogeon
May 21 2016 10:40
Alright, then :smile:
Zakarum
@omni-viral
May 21 2016 10:40
But field stream have to be removed. No matter what
Erik Hedvall
@Ogeon
May 21 2016 10:41
That's probably correct, given that there is only one stream
Zakarum
@omni-viral
May 21 2016 10:41
@Ogeon I don't think there is one stream. It is TcpStream after all. Should be one for each player
Erik Hedvall
@Ogeon
May 21 2016 10:41
It's probably correct in any case
I meant, unless there is one connection per player, but never mind
Zakarum
@omni-viral
May 21 2016 10:44
He can go and store all his streams in Arc<Mutex<TcpStream>> also. This way he could store stream inside Player structure. But I can't see much use of it
mhsjlw
@mhsjlw
May 21 2016 10:44
@Ogeon I get a player ID packet
I put that in a new player structure
now I can know the username of the packets I'm getting
*player sending the packets
and I store a tcp stream in each player
Hence player.stream.*
Zakarum
@omni-viral
May 21 2016 10:46
@mhsjlw As I said. You can't store it as you do it right now
mhsjlw
@mhsjlw
May 21 2016 10:48
@SCareAngel how should I?
In the end I'd like a map of player structs that are currently connected to the server that are indexable by their connection (so I can go from packet stream -> player struct)
If that makes no sense, tell me please, and I'll do something else
Zakarum
@omni-viral
May 21 2016 10:50
@mhsjlw That depends. Do you use mio::TcpStream or std::net::TcpStream
mhsjlw
@mhsjlw
May 21 2016 10:50
std::new::TcpStream
*net
Zakarum
@omni-viral
May 21 2016 10:50
So you use blocking streams then?
mhsjlw
@mhsjlw
May 21 2016 10:51
Yeah, but I have a thread for each connection
Should I be async?
(non-blocking)
Zakarum
@omni-viral
May 21 2016 10:51
You can do both way.
Which ever you prefer
mhsjlw
@mhsjlw
May 21 2016 10:52
I think I'll stick with blocking for now
Zakarum
@omni-viral
May 21 2016 10:52
So you have a thread for each TcpStream. This thread owns that stream I presume.
mhsjlw
@mhsjlw
May 21 2016 10:52
Yup
I'm sure I've probably got some edgy lifetime and mutability though (for passing around)
Still trying to get a hang of that
Zakarum
@omni-viral
May 21 2016 10:55
Then you should generate UID for each connection along with clone of TcpStream.
And put that UID in your handle_packet as argument
That's way you can map players by UID
mhsjlw
@mhsjlw
May 21 2016 10:57
yeah that's good because I need to do that in the future anyway
Zakarum
@omni-viral
May 21 2016 10:57
And player itself will contain TcpStream
mhsjlw
@mhsjlw
May 21 2016 10:57
each player has an 'entity id'
use std::net::TcpStream;

pub struct Player<'a> {
  pub name: String,
  pub x: u32,
  pub y: u32,
  pub z: u32,
  pub yaw: u8,
  pub pitch: u8,
  pub stream: &'a mut TcpStream
}
that's my player struct right now
'a is a lifetime thing, not exactly sure what it does, but it removed errors :P
Zakarum
@omni-viral
May 21 2016 10:58
Remove 'a and change stream: &'a mut TcpStream to stream: TcpStream
Use TcpStream::try_clone function to store stream in Player
mhsjlw
@mhsjlw
May 21 2016 11:00
let mut player = Player {name: "steve".to_string(), x: 0, y: 0, z: 0, yaw: 0, pitch: 0, stream: conn.try_copy()};
but not that
try_clone i mean
Zakarum
@omni-viral
May 21 2016 11:00
let mut player = Player {name: "steve".to_string(), x: 0, y: 0, z: 0, yaw: 0, pitch: 0, stream: try!(conn.try_copy())};
since try_clone returns Result<TcpStream, std::io::Error>
mhsjlw
@mhsjlw
May 21 2016 11:00
fn main() {
  let mut mc_world = World::new(10, 10, 10);

  for i in 0..10 {
    for i1 in 0..10 {
      for i2 in 0..10 {
         mc_world.set_block(i, i1, i2, 0x01);
      }
    }
  }

  let mutex_world = Arc::new(Mutex::new(mc_world));

  let mut acceptor = TcpListener::bind("127.0.0.1:25565").unwrap();
  println!("Rust listening on port *:25565");

  for connection in acceptor.incoming(){
    let mutex_world_clone = mutex_world.clone();
    thread::spawn(move || {
      handle_connection(connection.unwrap(), &mutex_world_clone);
    });
  }
}

fn handle_connection(mut conn: TcpStream, mutex_world: &Arc<Mutex<World>>) {
  loop {
    let packet = Packet::receive(&mut conn);

    match packet {
      Ok(packet) => handle_packet(packet, &mut conn, mutex_world),
      Err(error) => println!("error: {}", error),
    }
  }
}

fn handle_packet(packet: Packet, conn: &mut TcpStream, mutex_world: &Arc<Mutex<World>>) {
  let mut player = Player {name: "steve".to_string(), x: 0, y: 0, z: 0, yaw: 0, pitch: 0, stream: conn.try_clone()};
  if packet.packet_id == 0x00 {
    let parsed = packet.parse_player_ident();
    player.name = parsed.username;
    println!("{} has joined the game", player.name);

    player.stream.send_server_ident("A Minecraft Server".to_string(), "Welcome to my Minecraft Server".to_string());
    player.stream.send_level_init();

    let mut level = mutex_world.lock().unwrap();
    level.send_world(player.stream);

    player.stream.send_pos(5 * 32, 25 * 32, 5 * 32, 5, 5, -1);
    } else if packet.packet_id == 0x08 {
      let parsed = packet.parse_position_and_orientation();
      //println!("player has moved");
    } else if packet.packet_id == 0x05 {
      let parsed = packet.parse_set_block();
      println!("player has setblock");
    } else if packet.packet_id == 0x0d {
      let parsed = packet.parse_message();
      println!("<{}> {}", player.name, parsed.message);
    }
}
that's my whole file
(unincluding imports)
Zakarum
@omni-viral
May 21 2016 11:01
All you handle_... functions should return Result<_, std::io::Error>
mhsjlw
@mhsjlw
May 21 2016 11:01
so I need to try!()
right ?
Zakarum
@omni-viral
May 21 2016 11:01
yeap
mhsjlw
@mhsjlw
May 21 2016 11:01
ok
also wait
if I don't have this stream as immutable now
*if I do i mean
then how can I write to it ?
src/main.rs:66:22: 66:35 error: mismatched types:
 expected `&mut std::net::tcp::TcpStream`,
    found `std::net::tcp::TcpStream`
(expected &-ptr,
    found struct `std::net::tcp::TcpStream`) [E0308]
src/main.rs:66     level.send_world(player.stream);
Zakarum
@omni-viral
May 21 2016 11:02
You have ownership of this stream
level.send_world(&mut player.stream);
mhsjlw
@mhsjlw
May 21 2016 11:02
ah
Zakarum
@omni-viral
May 21 2016 11:03
player must be mutable in this context
mhsjlw
@mhsjlw
May 21 2016 11:03
error: no method named `try_copy` found for type `&mut std::net::tcp::TcpStream` in the current scope
src/main.rs:56   let mut player = Player {name: "steve".to_string(), x: 0, y: 0, z: 0, yaw: 0, pitch: 0, eid: 0, stream: try!(conn.try_copy())};
                                                                                                                                   ^~~~~~~~~~
src/main.rs:56:107: 56:128 note: in this expansion of try! (defined in <std macros>)
<std macros>:5:8: 6:42 error: mismatched types:
 expected `()`,
    found `core::result::Result<_, _>`
(expected (),
    found enum `core::result::Result`) [E0308]
<std macros>:5 return $ crate:: result:: Result:: Err (
<std macros>:6 $ crate:: convert:: From:: from ( err ) ) } } )
src/main.rs:56:107: 56:128 note: in this expansion of try! (defined in <std macros>)
<std macros>:5:8: 6:42 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to 2 previous errors
Could not compile `rust-classic`.

To learn more, run the command again with --verbose.
try copy doesn't exist?
Zakarum
@omni-viral
May 21 2016 11:03
try_clone
mhsjlw
@mhsjlw
May 21 2016 11:03
ah
I've still got that mismatched type
Zakarum
@omni-viral
May 21 2016 11:04
change handle_packet return type
to Result<(), std::io::Error>
And add Ok(()) to the end of the function
mhsjlw
@mhsjlw
May 21 2016 11:05
to the end of the function?
after the if blocks?
Zakarum
@omni-viral
May 21 2016 11:05
Yeap
mhsjlw
@mhsjlw
May 21 2016 11:06
fn handle_packet(packet: Packet, conn: &mut TcpStream, mutex_world: &Arc<Mutex<World>>) -> Result<(), std::io::Error> {
  let mut player = Player {name: "steve".to_string(), x: 0, y: 0, z: 0, yaw: 0, pitch: 0, eid: 0, stream: try!(conn.try_clone())};
  if packet.packet_id == 0x00 {
    let parsed = try!(packet.parse_player_ident());
    player.name = parsed.username;
    println!("{} has joined the game", player.name);

    try!(player.stream.send_server_ident("A Minecraft Server".to_string(), "Welcome to my Minecraft Server".to_string()));
    try!(player.stream.send_level_init());

    let mut level = mutex_world.lock().unwrap();
    try!(level.send_world(&mut player.stream));

    try!(player.stream.send_pos(5 * 32, 25 * 32, 5 * 32, 5, 5, -1));
    } else if packet.packet_id == 0x08 {
      let parsed = packet.parse_position_and_orientation();
      //println!("player has moved");
    } else if packet.packet_id == 0x05 {
      let parsed = packet.parse_set_block();
      println!("player has setblock");
    } else if packet.packet_id == 0x0d {
      let parsed = packet.parse_message();
      println!("<{}> {}", player.name, parsed.message);
    }

  Ok()
}
that just blows up with errors
I need something in the Ok()
Zakarum
@omni-viral
May 21 2016 11:06
Ok(())
mhsjlw
@mhsjlw
May 21 2016 11:06
and all those try!() are doing things
hmm
Zakarum
@omni-viral
May 21 2016 11:07
Why you did add try! everywhere?
mhsjlw
@mhsjlw
May 21 2016 11:07
I need to extract the result from each one?
@mhsjlw
so I need to try!()
right ?
@SCareAngel
yeap
I guess I read that wrong :P
Zakarum
@omni-viral
May 21 2016 11:08
@mhsjlw you need try!(...) only that is Result<V, E>
mhsjlw
@mhsjlw
May 21 2016 11:09
ok
Zakarum
@omni-viral
May 21 2016 11:09
conn.try_clone() returns Result<TcpStream, io::Error>. So you try! it and get TcpStream
mhsjlw
@mhsjlw
May 21 2016 11:10
ok rust is pretty pissed right now
xD
   Compiling rust-classic v0.1.0 (file:///home/mhsjlw/Documents/rust-classic)
src/main.rs:48:5: 51:6 error: match arms have incompatible types:
 expected `core::result::Result<(), std::io::error::Error>`,
    found `()`
(expected enum `core::result::Result`,
    found ()) [E0308]
src/main.rs:48     match packet {
src/main.rs:49       Ok(packet) => handle_packet(packet, &mut conn, mutex_world),
src/main.rs:50       Err(error) => println!("error: {}", error),
src/main.rs:51     }
src/main.rs:48:5: 51:6 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:50:21: 50:49 note: match arm with an incompatible type
src/main.rs:50       Err(error) => println!("error: {}", error),
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:50:21: 50:49 note: in this expansion of println! (defined in <std macros>)
error: aborting due to previous error
Could not compile `rust-classic`.
mismatching stuff
because we don't handle the returns
Erik Hedvall
@Ogeon
May 21 2016 11:12
That's because handle_packet returns a Result, while println! returns ()
mhsjlw
@mhsjlw
May 21 2016 11:12
hm
Zakarum
@omni-viral
May 21 2016 11:12
match packet {
    Ok(packet) => handle_packet(packet, &mut conn, mutex_world),
    Err(error) => { println!("error: {}", error); Err(error) }
}
Erik Hedvall
@Ogeon
May 21 2016 11:12
match will return the result from the chosen branch, so it has to be the same in each
mhsjlw
@mhsjlw
May 21 2016 11:12
@Ogeon yeah that makes sense
also, it's funny I saw the conversation yesterday about rust the game
and I actually saw someone write hacks for a video game in rust
i was like, ha
aimbot and a thing where you can see through walls
all in rust
:D
I can't remember
Zakarum
@omni-viral
May 21 2016 11:15
Also, try this
match packet.map(|p| handle_packet(p, &mut  conn, mutex_world) {
    Err(err) => { println!("error: {}", err); }
    _ => {}
}
mhsjlw
@mhsjlw
May 21 2016 11:15
  Compiling rust-classic v0.1.0 (file:///home/mhsjlw/Documents/rust-classic)
src/main.rs:57:3: 57:4 error: incorrect close delimiter: `}`
src/main.rs:57   }
                 ^
src/main.rs:53:21: 53:22 note: unclosed delimiter
src/main.rs:53     match packet.map(|p| handle_packet(p, &mut  conn, mutex_world) {
                                   ^
Could not compile `rust-classic`.

To learn more, run the command again with --verbose.
it doesn't like that
Erik Hedvall
@Ogeon
May 21 2016 11:15
I would do something like this:
fn handle_connection(mut conn: TcpStream, mutex_world: &Arc<Mutex<World>>) {
  loop {
    let packet = Packet::receive(&mut conn);
    let result = packet.and_then(|packet| handle_packet(packet, &mut conn, mutex_world));
    if let Err(error) = result {
     println!("error: {}", error),
    }
  }
}
Zakarum
@omni-viral
May 21 2016 11:16
@Ogeon yeah
I messed up a little
mhsjlw
@mhsjlw
May 21 2016 11:16
ok well hmm
the name still doesn't update
what did we decide to do about that
I'll push to github
Zakarum
@omni-viral
May 21 2016 11:17
Save your player
Erik Hedvall
@Ogeon
May 21 2016 11:17
There's still the problem with the player only existing within handle_packet
Zakarum
@omni-viral
May 21 2016 11:17
Right now you create player in handle_packet and destroy it there
mhsjlw
@mhsjlw
May 21 2016 11:17
@SCareAngel ah, really ?
Zakarum
@omni-viral
May 21 2016 11:17
Yeap
mhsjlw
@mhsjlw
May 21 2016 11:17
I didn't know it destroyed it
darn
Zakarum
@omni-viral
May 21 2016 11:18
you create it as local variable
local variables are destroyed when go out of scope
except if it moved
mhsjlw
@mhsjlw
May 21 2016 11:18
yeah
Zakarum
@omni-viral
May 21 2016 11:18
so you should move it
mhsjlw
@mhsjlw
May 21 2016 11:18
so we want to return it
then move it
yeah
Zakarum
@omni-viral
May 21 2016 11:18
to some safer place
Zakarum
@omni-viral
May 21 2016 11:18
in the World
mhsjlw
@mhsjlw
May 21 2016 11:19
all my code is now there ^
Daniel Collin
@emoon
May 21 2016 16:45
Maybe not super important in this case but you could change so send_server_ident takes &str instead of String so you don’t need to construct the Strings (which will allocate memory) (and you wouldn’t need to do .to_string() also)
kena
@knz
May 21 2016 20:00
hi guys, I'm a teacher at a university (and incidentally the author of "rust for functional programmers") and I'd like to sponsor a small research by one of my students on a new git tool -- something to improve how a new programmer learns a large code base when they join a new project (like new Rust contributors!). I'd love it if you could support this by filling this small research questionnaire for him: https://docs.google.com/forms/d/1oDBqxqf6AmyRpG07P3QgIMDSQwowoxRo-yBEdxORWXk/viewform
thanks!
Peter Atashian
@retep998
May 21 2016 22:19
oh shit, what the heck happened to gitter
suddenly new UI