summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2019-09-23 09:18:42 +0200
committertroido <troido@protonmail.com>2019-09-23 09:18:42 +0200
commit62c810b6f8ef7c3feca62637b8361a3386fa43d8 (patch)
tree5b2f8748808bcba23630927f593e64495a147d57
parent864335ea6007dbfebe87ff717aeec8478ca10ec5 (diff)
picking up the project again. Not sure what I changed, but it seemed wise to commit
-rw-r--r--Cargo.toml2
-rwxr-xr-xclientinet.py57
-rw-r--r--src/gameserver.rs97
-rw-r--r--src/main.rs15
-rw-r--r--src/server/gameserver.rs1
-rw-r--r--src/simpleworld.rs74
6 files changed, 198 insertions, 48 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 2ceed55..27af7a0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,4 +12,4 @@ nix = "0.13"
libc = "0.2"
users = "0.8"
json = "0.11.13"
-
+specs = "0.14.3"
diff --git a/clientinet.py b/clientinet.py
new file mode 100755
index 0000000..f4f4887
--- /dev/null
+++ b/clientinet.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+
+import socket
+import sys
+import threading
+import json
+import getpass
+
+
+def send(sock, msg):
+ length = len(msg)
+ header = length.to_bytes(4, byteorder="big")
+ totalmsg = header + msg
+ sock.sendall(totalmsg)
+
+def receive(sock):
+ header = recvall(sock, 4) #sock.recv(4)
+ length = int.from_bytes(header, byteorder="big")
+ return recvall(sock, length)
+
+def recvall(sock, length):
+ chunks = []
+ bytes_recd = 0
+ while bytes_recd < length:
+ chunk = sock.recv(min(length - bytes_recd, 4096))
+ if chunk == b'':
+ break
+ #raise RuntimeError("socket connection broken")
+ chunks.append(chunk)
+ bytes_recd = bytes_recd + len(chunk)
+ return b''.join(chunks)
+
+
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+sock.connect(("localhost", 1234))
+
+def listen():
+ while True:
+ d = receive(sock)
+ if len(d) == 0:
+ print("Connection closed by server", file=sys.stdout)
+ return
+ print(str(d, "utf-8"))
+
+threading.Thread(target=listen, daemon=True).start()
+
+if len(sys.argv) >= 2:
+ name = sys.argv[1]
+else:
+ name = getpass.getuser()
+print(name)
+
+send(sock, bytes(json.dumps(["name", name]), "utf-8"))
+
+for line in sys.stdin:
+ send(sock, bytes(json.dumps(["chat", line.strip()]), "utf-8"))
diff --git a/src/gameserver.rs b/src/gameserver.rs
index 76ffbd6..2412e28 100644
--- a/src/gameserver.rs
+++ b/src/gameserver.rs
@@ -9,81 +9,98 @@ use json::JsonValue;
use super::server::Server;
-pub enum Message {
+enum Message {
Name(String),
Chat(String),
- Input,
+ Input(JsonValue),
Invalid(String)
}
-pub struct GameServer<T: Server> {
- players: HashMap<usize, String>,
- connections: HashMap<String, usize>,
- server: T
+pub enum Action {
+ Join(String),
+ Leave(String),
+ Input(String, JsonValue)
}
-impl<T: Server> GameServer<T> {
- pub fn new(server: T) -> GameServer<T> {
+pub struct GameServer {
+ players: HashMap<(usize, usize), String>,
+ connections: HashMap<String, (usize, usize)>,
+ servers: Vec<Box<Server>>
+}
+
+impl GameServer {
+ pub fn new(servers: Vec<Box<Server>>) -> GameServer {
GameServer {
players: HashMap::new(),
connections: HashMap::new(),
- server
+ servers
}
}
- pub fn update(&mut self) {
- self.accept_connections();
- self.receive_messages();
- }
-
- fn accept_connections(&mut self) {
- let _joined = self.server.accept_pending_connections();
- }
-
- fn receive_messages(&mut self) {
+ pub fn update(&mut self) -> Vec<Action>{
+ for server in self.servers.iter_mut(){
+ let _ = server.accept_pending_connections();
+ }
- let (messages, left) = self.server.recv_pending_messages();
- for (id, message) in messages {
- self.handle_message(id, parse_message(&message));
+ let mut actions: Vec<Action> = Vec::new();
+ let mut input = Vec::new();
+ for (serverid, server) in self.servers.iter_mut().enumerate(){
+ let (messages, left) = server.recv_pending_messages();
+ input.push((serverid, messages, left));
}
- for id in left {
- self.remove_connection(id);
+ for (serverid, messages, left) in input {
+ for (id, message) in messages {
+ let r = self.handle_message((serverid, id), parse_message(&message));
+ if let Some(action) = r {
+ actions.push(action);
+ }
+ }
+ for id in left {
+ if let Some(name) = self.players.remove(&(serverid, id)){
+ self.connections.remove(&name);
+ self.broadcast_message(&format!("{} disconnected", name));
+ actions.push(Action::Leave(name.clone()));
+ }
+ }
}
+ actions
}
- fn send_error(&mut self, id: usize, errname: &str, err_text: &str) -> Result<(), io::Error>{
- self.server.send(id, &json::stringify(json::array!["error", errname, err_text]))
+ fn send_error(&mut self, (serverid, connectionid): (usize, usize), errname: &str, err_text: &str) -> Result<(), io::Error>{
+ self.servers[serverid].send(connectionid, &json::stringify(json::array!["error", errname, err_text]))
}
pub fn broadcast_message(&mut self, text: &str){
println!("{}", text);
let jsontext = json::stringify(json::array!["message", text]);
- for (id, _name) in &self.players {
- let _ = self.server.send(*id, &jsontext);
+ for ((serverid, id), _name) in &self.players {
+ let _ = self.servers[*serverid].send(*id, &jsontext);
}
}
- pub fn handle_message(&mut self, id: usize, msg: Message) {
+ fn handle_message(&mut self, (serverid, connectionid): (usize, usize), msg: Message) -> Option<Action> {
+ let id = (serverid, connectionid);
match msg {
Message::Name(name) => {
let (firstchar, username) = name.split_at(1);
if firstchar == "~"{
- if Some(username.to_string()) != self.server.get_name(id) {
+ if Some(username.to_string()) != self.servers[serverid].get_name(connectionid) {
let _ = self.send_error(id, "invalidname", &format!("A tilde name must match your username"));
- return;
+ return None;
}
}
if self.players.contains_key(&id) {
let _ = self.send_error(id, "invalidaction", &format!("You can not change your name"));
- return;
+ return None;
}
if self.connections.contains_key(&name) {
let _ = self.send_error(id, "nametaken", &format!("Another connections to this player exists already"));
- return;
+ return None;
}
self.broadcast_message(&format!("{} connected", name));
self.players.insert(id, name.clone());
- self.connections.insert(name, id);
+ self.connections.insert(name.clone(), id);
+ Some(Action::Join(name))
}
Message::Chat(text) => {
if let Some(name) = self.players.get(&id) {
@@ -91,20 +108,16 @@ impl<T: Server> GameServer<T> {
} else {
let _ = self.send_error(id, "invalidaction", &format!("Set a name before you send other messages"));
}
+ None
}
- Message::Input => { () }
+ Message::Input(_) => { None }
Message::Invalid(text) => {
let _ = self.send_error(id, "invalidmessage", &format!("Invalid: {}", text));
+ None
}
}
}
- pub fn remove_connection(&mut self, id: usize) {
- if let Some(name) = self.players.remove(&id){
- self.connections.remove(&name);
- self.broadcast_message(&format!("{} disconnected", name));
- }
- }
}
@@ -133,7 +146,7 @@ fn parse_message(msg: &str) -> Message {
}
"input" => {
- Message::Input
+ Message::Input(arr[1].clone())
}
_ => {
Message::Invalid(format!("unknown messsage type {:?}", msgtype).to_string())
diff --git a/src/main.rs b/src/main.rs
index ff60460..a9cd76b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,25 +3,32 @@
use std::thread::sleep;
use std::time::Duration;
use std::path::Path;
+// use std::net::SocketAddr;
pub mod server;
pub mod gameserver;
+pub mod simpleworld;
use self::gameserver::GameServer;
use self::server::unixserver::UnixServer;
+use self::server::tcpserver::TcpServer;
+use self::server::Server;
fn main() {
-// let addr = "127.0.0.1:1234".parse().unwrap();
let addr = Path::new("\0rustifarm");
+ let unixserver = UnixServer::new(&addr).expect("binding unix server failed");
- let socketserver = UnixServer::new(&addr).expect("binding server failed");
+ let addr = "127.0.0.1:1234".parse().unwrap();
+ let inetserver = TcpServer::new(&addr).expect("binding inet server failed");
- let mut gameserver = GameServer::new(socketserver);
- println!("listening on {:?}", addr);
+ let servers: Vec<Box<Server>> = vec![Box::new(unixserver), Box::new(inetserver)];
+ let mut gameserver = GameServer::new(servers);
+
+// println!("listening on {:?}", addr);
// let mut players: HashMap<usize, String> = HashMap::new();
diff --git a/src/server/gameserver.rs b/src/server/gameserver.rs
deleted file mode 100644
index 8b13789..0000000
--- a/src/server/gameserver.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/simpleworld.rs b/src/simpleworld.rs
new file mode 100644
index 0000000..1621ee2
--- /dev/null
+++ b/src/simpleworld.rs
@@ -0,0 +1,74 @@
+
+use std::collections::HashMap;
+use std::collections::HashSet;
+
+#[derive(PartialEq, Eq, Hash, Clone, Copy)]
+struct Pos (i32, i32);
+
+
+struct Room {
+ objects :HashMap<Pos, HashSet<GameObject>>,
+ pub area :(Pos, Pos),
+ players :HashMap<String, GameObject>
+}
+
+
+impl Room {
+
+ pub fn new(area :(Pos, Pos)) -> Room {
+ Room {
+ objects: HashMap::new(),
+ area: area,
+ players: HashMap::new()
+ }
+ }
+
+
+ pub fn get_sprites(&self, pos :&Pos) -> Vec<String> {
+ match self.objects.get(pos) {
+ Some(objs) => {objs.iter().map(|o| o.sprite.clone()).collect()}
+ None => {Vec::new()}
+ }
+ }
+
+// let mut sprites :Vec<String> = Vec::new();
+// for maybe_obj in self.objects.get((x, y))
+// sprites.push
+
+
+ pub fn draw(&self) -> (Vec<usize>, Vec<Vec<String>>) {
+ let (minp, maxp) = &self.area;
+ let Pos(xmin, ymin) = *minp;
+ let Pos(xmax, ymax) = *maxp;
+ let width = xmax - xmin;
+ let height = ymax - ymin;
+ let size = width * height;
+ let mut values :Vec<usize>= Vec::with_capacity(size as usize);
+ let mut mapping = Vec::with_capacity(size as usize);
+ for y in ymin..ymax {
+ for x in xmin..xmax {
+ values.push(mapping.len());
+ mapping.push(self.get_sprites(&Pos(x, y)));
+ }
+ }
+ return (values, mapping)
+ }
+}
+
+
+struct GameObject {
+ pos :Pos,
+// name :&str,
+ sprite :String
+}
+
+impl GameObject {
+
+ pub fn new(sprite :&str, pos :Pos) -> GameObject {
+ GameObject {
+ pos: pos,
+ sprite: sprite.to_string()
+ }
+ }
+
+}