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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/usr/bin/env node
const net = require("net");
const util = require("util");
if (process.argv.length != 4) {
console.log("Usage: ./main.js <hostname> <port>");
console.log("Pass address of doomrooms server as arguments.");
process.exit(1);
}
const GAME_ID = "tictactoe-tom";
const GAME_NAME = "Tic Tac Toe";
{
let id = 0;
function uniqid() {
return id++;
}
}
function lineReader(conn, lineCb) {
let buffer = "";
conn.on("data", (data) => {
buffer += data.toString();
let idx = buffer.indexOf("\n");
while (idx != -1) {
lineCb(buffer.slice(0, idx));
buffer = buffer.slice(idx + 1);
idx = buffer.indexOf("\n");
}
});
}
class Message {
constructor(/*...*/) {
if (typeof arguments[0] == "number") this.makeReply(...arguments);
else this.makeCommand(...arguments);
}
makeCommand(method, ...args) {
this.isCommand = true;
this.method = method;
this.args = args;
this.id = uniqid();
}
makeReply(id, res, err) {
this.isCommand = false;
this.id = id;
this.res = res;
this.err = err;
}
toJSON() {
if (this.isCommand) {
return JSON.stringify({
method: this.method,
args: this.args,
id: this.id,
});
} else {
return JSON.stringify({
res: this.res,
err: this.err,
id: this.id,
});
}
}
}
class Connection {
constructor(conn, msgCb) {
this.conn = conn;
lineReader(conn, (line) => {
let obj;
try {
obj = JSON.parse(line);
} catch (e) {
console.log("Invalid JSON received: " + line);
return;
}
if (obj.res || obj.err) {
const msg = new Message(obj.id, obj.res, obj.err);
if (this.replyHandlers[msg.id]) {
this.replyHandlers[msg.id](msg);
this.replyHandlers[msg.id] = null;
} else {
console.log("Reply for unexpected message id " + msg.id);
}
} else {
msgCb(new Message(obj.method, ...obj.args));
}
});
this.replyHandlers = {};
}
send(msg, replyCb) {
const data = msg.toJSON();
console.log("Writing to conn: " + data);
this.conn.write(data + "\n");
if (replyCb && msg.isCommand) {
this.replyHandlers[msg.id] = replyCb;
}
}
}
function messageHandler(msg) {
console.log("Message: " + util.inspect(msg));
}
const conn = new Connection(net.createConnection(+process.argv[3], process.argv[2]), messageHandler);
conn.conn.on("connect", () => {
console.log("Connected to roomserver");
conn.conn.on("end", () => {
console.log("Connection with roomserver unexpectedly closed!");
});
setInterval(() => {
conn.send(new Message("ping"), (msg) => console.log("Ping reply: " + util.inspect(msg)));
}, 30000);
conn.send(new Message("make-game", GAME_ID, GAME_NAME), (msg) => console.log(msg));
});
|