fb785eda by Barry

Huge update and added more protocol handling to the mudserver.py

1 parent 51c565a0
...@@ -7,7 +7,7 @@ def look(id, mud, players, tokens): ...@@ -7,7 +7,7 @@ def look(id, mud, players, tokens):
7 del tokens[0] 7 del tokens[0]
8 if len(tokens) == 0: 8 if len(tokens) == 0:
9 mud.send_message(id, room_data.get('title'), color=['bold', 'green']) 9 mud.send_message(id, room_data.get('title'), color=['bold', 'green'])
10 mud.send_message(id, room_data.get('description'), color='green') 10 mud.send_message(id, room_data.get('description'), line_ending='\r\n\r\n', color='green')
11 else: 11 else:
12 subject = tokens[0] 12 subject = tokens[0]
13 items = room_data.get('look_items') 13 items = room_data.get('look_items')
...@@ -46,12 +46,13 @@ def look(id, mud, players, tokens): ...@@ -46,12 +46,13 @@ def look(id, mud, players, tokens):
46 if len(playershere) > 0: 46 if len(playershere) > 0:
47 mud.send_message(id, "%boldPlayers here:%reset {}".format(", ".join(playershere))) 47 mud.send_message(id, "%boldPlayers here:%reset {}".format(", ".join(playershere)))
48 48
49 # send player a message containing the list of exits from this room 49 mud.send_message(id, "%boldObvious Exits:%reset ", line_ending='')
50 mud.send_message(id, "%boldObvious Exits:%reset {}".format(", ".join(room_data.get('exits')))) 50 mud.send_list(id, room_data.get('exits'), "go")
51 51
52 # send player a message containing the list of exits from this room 52 # send player a message containing the list of exits from this room
53 if len(room_data.get('inventory')) > 0: 53 if len(room_data.get('inventory')) > 0:
54 mud.send_message(id, "%boldItems here:%reset {}".format(", ".join(room_data.get('inventory').keys()))) 54 mud.send_message(id, "%boldItems here:%reset ", line_ending='')
55 mud.send_list(id, room_data.get('inventory').keys(), "look")
55 56
56 # send player a message containing the list of players in the room 57 # send player a message containing the list of players in the room
57 for mon_name, monster in room_monsters.items(): 58 for mon_name, monster in room_monsters.items():
......
1 def score(id, players, mud):
2 from math import floor
3
4 mud.send_message(id, " %green+----------------------------=Score=---------------------------+", nowrap=True)
5 hp = str("%d/%d" % (floor(players[id]['hp']), floor(players[id]['maxhp']))).center(12, ' ')
6 mp = str("%d/%d" % (floor(players[id]['mp']), floor(players[id]['maxmp']))).center(12, ' ')
7 sta = str("%d/%d" % (floor(players[id]['sta']), floor(players[id]['maxsta']))).center(12, ' ')
8
9 mud.send_message(id, " %%green|%%reset%%bold%%white%s%%reset%%green|" % (players[id]["name"].center(62),), nowrap=True)
10 mud.send_message(id, " %green+--------------------------------------------------------------+", nowrap=True)
11 mud.send_message(id, " %%green|%%reset %%cyanHP:%%reset %%white[%s]%%reset %%green|%%reset %%cyanMP:%%reset %%white[%s]%%reset %%green|%%reset %%cyanST:%%reset %%white[%s]%%reset %%green|%%reset" % (hp, mp, sta), nowrap=True)
12
13
14 # output = """
15 # --------------------------------------------
16 # HP: {hp} Max HP: {maxhp}
17 # MP: {mp} Max MP: {maxmp}
18 # Sta: {sta} Max Sta: {maxsta}
19 # Experience: {exp}
20 # Skills:""".format(hp=floor(players[id]['hp']),
21 # mp=floor(players[id]['mp']),
22 # maxhp=floor(players[id]['maxhp']),
23 # maxmp=floor(players[id]['maxmp']),
24 # sta=floor(players[id]['sta']),
25 # maxsta=floor(players[id]['maxsta']),
26 # exp=0)
27 # mud.send_message(id, output)
28
29 mud.send_message(id, " %green+---------------------------=Skills=---------------------------+", nowrap=True)
30 skills = ["skillasdfasdfasdfasdf", "skill 2 sdfg sdfg", "Skill 3 asdf ewrewwr"]
31 for skill in skills:
32 mud.send_message(id, " %%green|%%reset %s%%green|%%reset" % (skill.ljust(61),), nowrap=True)
33
34 mud.send_message(id, " %green+--------------------------------------------------------------+", nowrap=True)
35
36
37
38 score(id, players, mud)
39 del score
...\ No newline at end of file ...\ No newline at end of file
...@@ -2,6 +2,8 @@ def who(id, players, mud): ...@@ -2,6 +2,8 @@ def who(id, players, mud):
2 mud.send_message(id, "") 2 mud.send_message(id, "")
3 mud.send_message(id, "-------- {} Players Currently Online --------".format(len(players))) 3 mud.send_message(id, "-------- {} Players Currently Online --------".format(len(players)))
4 for pid, player in players.items(): 4 for pid, player in players.items():
5 if player["name"] is None:
6 continue
5 mud.send_message(id, " " + player["name"]) 7 mud.send_message(id, " " + player["name"])
6 mud.send_message(id, "---------------------------------------------".format(len(players))) 8 mud.send_message(id, "---------------------------------------------".format(len(players)))
7 mud.send_message(id, "") 9 mud.send_message(id, "")
......
1 { 1 {
2 "name": null, 2 "name": null,
3 "password": null,
3 "room": null, 4 "room": null,
4 "inventory": {}, 5 "inventory": {},
5 "prompt": "hp %hp mp %mp> ", 6 "prompt": "hp %hp mp %mp> ",
......
...@@ -11,6 +11,7 @@ from math import floor ...@@ -11,6 +11,7 @@ from math import floor
11 from sys import platform 11 from sys import platform
12 12
13 from mudserver import MudServer 13 from mudserver import MudServer
14 from commandhandler import CommandHandler
14 from utils import load_object_from_file, save_object_to_file 15 from utils import load_object_from_file, save_object_to_file
15 16
16 if 'esp' in platform: 17 if 'esp' in platform:
...@@ -47,6 +48,8 @@ def show_prompt(pid): ...@@ -47,6 +48,8 @@ def show_prompt(pid):
47 48
48 tick = 0.0 49 tick = 0.0
49 spawn = 0.0 50 spawn = 0.0
51 cmd_handler = CommandHandler()
52
50 # main game loop. We loop forever (i.e. until the program is terminated) 53 # main game loop. We loop forever (i.e. until the program is terminated)
51 while True: 54 while True:
52 if 'esp' in platform: 55 if 'esp' in platform:
...@@ -104,6 +107,8 @@ while True: ...@@ -104,6 +107,8 @@ while True:
104 for line in f: 107 for line in f:
105 mud.send_message(id, line, "\r") 108 mud.send_message(id, line, "\r")
106 # send the new player a prompt for their name 109 # send the new player a prompt for their name
110 #bytes_to_send = bytearray([mud._TN_INTERPRET_AS_COMMAND, mud._TN_WONT, mud._ECHO])
111 #mud.raw_send(id, bytes_to_send)
107 mud.send_message(id, "What is your name?") 112 mud.send_message(id, "What is your name?")
108 113
109 # go through any recently disconnected players 114 # go through any recently disconnected players
...@@ -148,9 +153,21 @@ while True: ...@@ -148,9 +153,21 @@ while True:
148 already_logged_in = True 153 already_logged_in = True
149 if already_logged_in: 154 if already_logged_in:
150 continue 155 continue
151 loaded_player = load_object_from_file("players/{}.json".format(command))
152 if loaded_player is None:
153 players[id]["name"] = command 156 players[id]["name"] = command
157
158 mud.remote_echo(id, False)
159 mud.send_message(id, "Enter Password: ")
160
161 elif players[id]["password"] is None:
162 if command.strip() == '' or command is None:
163 mud.send_message(id, "Invalid Password")
164 continue
165
166 # TODO: Write password shadow file
167
168 loaded_player = load_object_from_file("players/{}.json".format(players[pid]["name"]))
169 if loaded_player is None:
170 players[id]["password"] = True
154 players[id]["room"] = "Tavern" 171 players[id]["room"] = "Tavern"
155 else: 172 else:
156 players[id] = loaded_player 173 players[id] = loaded_player
...@@ -160,21 +177,20 @@ while True: ...@@ -160,21 +177,20 @@ while True:
160 # send each player a message to tell them about the new player 177 # send each player a message to tell them about the new player
161 mud.send_message(pid, "{} entered the game".format(players[id]["name"])) 178 mud.send_message(pid, "{} entered the game".format(players[id]["name"]))
162 179
180 mud.remote_echo(id, True)
163 # send the new player a welcome message 181 # send the new player a welcome message
164 mud.send_message(id, "\r\n\r\nWelcome to the game, {}. ".format(players[id]["name"]) + 182 mud.send_message(id, "\r\n\r\nWelcome to the game, {}. ".format(players[id]["name"]) +
165 "\r\nType 'help' for a list of commands. Have fun!\r\n\r\n") 183 "\r\nType 'help' for a list of commands. Have fun!\r\n\r\n")
166 184
167 # send the new player the description of their current room 185 # send the new player the description of their current room
168 186
169 mud.send_message(id, load_object_from_file('rooms/' + players[id]["room"] + '.json')['description']) 187 cmd_handler.parse(id, 'look', '', mud, players)
170 188 show_prompt(id)
171 else: 189 else:
172 from commandhandler import CommandHandler
173 if 'esp' in platform: 190 if 'esp' in platform:
174 collect() 191 collect()
175 cmd_handler = CommandHandler()
176 192
177 handler_results = cmd_handler.parse(id, command, params, mud, players) 193 cmd_handler.parse(id, command, params, mud, players)
178 show_prompt(id) 194 show_prompt(id)
179 195
180 # Start WIFI Setup 196 # Start WIFI Setup
......
...@@ -3,7 +3,7 @@ def run_mobs(players, mud): ...@@ -3,7 +3,7 @@ def run_mobs(players, mud):
3 3
4 from utils import load_object_from_file, save_object_to_file, calc_att, get_att 4 from utils import load_object_from_file, save_object_to_file, calc_att, get_att
5 for pid, player in players.items(): 5 for pid, player in players.items():
6 if not player['name']: 6 if not player['password']:
7 continue 7 continue
8 if player['mp'] < player['maxmp']: 8 if player['mp'] < player['maxmp']:
9 players[pid]['mp'] += player['mpr'] 9 players[pid]['mp'] += player['mpr']
......
...@@ -12,6 +12,7 @@ import socket ...@@ -12,6 +12,7 @@ import socket
12 import select 12 import select
13 import time 13 import time
14 import sys 14 import sys
15 import struct
15 16
16 from utils import get_color, get_color_list, multiple_replace 17 from utils import get_color, get_color_list, multiple_replace
17 18
...@@ -58,17 +59,34 @@ class MudServer(object): ...@@ -58,17 +59,34 @@ class MudServer(object):
58 _READ_STATE_NORMAL = 1 59 _READ_STATE_NORMAL = 1
59 _READ_STATE_COMMAND = 2 60 _READ_STATE_COMMAND = 2
60 _READ_STATE_SUBNEG = 3 61 _READ_STATE_SUBNEG = 3
62 _READ_NAWS = 4
63 _READ_MSDP = 5
64
65 _ECHO = 1
66 _NAWS = 31
67 _MSDP = 69
68 _MSSP = 70
69 _MXP = 91
70
71 _MSSP_VAR = 1
72 _MSSP_VAL = 2
73
74 _MSDP_VAR = 1
75 _MSDP_VAL = 2
76 _MSDP_TABLE_OPEN = 3
77 _MSDP_TABLE_CLOSE = 4
78 _MSDP_ARRAY_OPEN = 5
79 _MSDP_ARRAY_CLOSE = 6
61 80
62 # Command codes used by Telnet protocol 81 # Command codes used by Telnet protocol
63 # See _process_sent_data function 82 # See _process_sent_data function
64 _TN_INTERPRET_AS_COMMAND = 255 83 _TN_IAC = 255
65 _TN_ARE_YOU_THERE = 246
66 _TN_WILL = 251
67 _TN_WONT = 252
68 _TN_DO = 253
69 _TN_DONT = 254 84 _TN_DONT = 254
70 _TN_SUBNEGOTIATION_START = 250 85 _TN_DO = 253
71 _TN_SUBNEGOTIATION_END = 240 86 _TN_WONT = 252
87 _TN_WILL = 251
88 _TN_SUB_START = 250
89 _TN_SUB_END = 240
72 90
73 # socket used to listen for new clients 91 # socket used to listen for new clients
74 _listen_socket = None 92 _listen_socket = None
...@@ -81,6 +99,9 @@ class MudServer(object): ...@@ -81,6 +99,9 @@ class MudServer(object):
81 # list of newly-added occurences 99 # list of newly-added occurences
82 _new_events = [] 100 _new_events = []
83 101
102 start_time = time.time()
103
104
84 def __init__(self): 105 def __init__(self):
85 """Constructs the MudServer object and starts listening for 106 """Constructs the MudServer object and starts listening for
86 new players. 107 new players.
...@@ -96,8 +117,7 @@ class MudServer(object): ...@@ -96,8 +117,7 @@ class MudServer(object):
96 117
97 # set a special option on the socket which allows the port to be 118 # set a special option on the socket which allows the port to be
98 # immediately without having to wait 119 # immediately without having to wait
99 self._listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 120 self._listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
100 1)
101 121
102 # bind the socket to an ip address and port. Port 23 is the standard 122 # bind the socket to an ip address and port. Port 23 is the standard
103 # telnet port which telnet clients will use, however on some platforms 123 # telnet port which telnet clients will use, however on some platforms
...@@ -183,7 +203,7 @@ class MudServer(object): ...@@ -183,7 +203,7 @@ class MudServer(object):
183 # return the info list 203 # return the info list
184 return retval 204 return retval
185 205
186 def send_message(self, to, message, line_ending='\r\n', color=None): 206 def send_message(self, to, message, line_ending='\r\n', color=None, nowrap=False):
187 """Sends the text in the 'message' parameter to the player with 207 """Sends the text in the 'message' parameter to the player with
188 the id number given in the 'to' parameter. The text will be 208 the id number given in the 'to' parameter. The text will be
189 printed out in the player's terminal. 209 printed out in the player's terminal.
...@@ -191,6 +211,9 @@ class MudServer(object): ...@@ -191,6 +211,9 @@ class MudServer(object):
191 # we make sure to put a newline on the end so the client receives the 211 # we make sure to put a newline on the end so the client receives the
192 # message on its own line 212 # message on its own line
193 message = multiple_replace(message, get_color_list()) 213 message = multiple_replace(message, get_color_list())
214 if nowrap:
215 lines = [message]
216 else:
194 chunks, chunk_size = len(message), 80 #len(x)/4 217 chunks, chunk_size = len(message), 80 #len(x)/4
195 lines = [message[i:i + chunk_size] for i in range(0, chunks, chunk_size)] 218 lines = [message[i:i + chunk_size] for i in range(0, chunks, chunk_size)]
196 if color: 219 if color:
...@@ -214,6 +237,28 @@ class MudServer(object): ...@@ -214,6 +237,28 @@ class MudServer(object):
214 # stop listening for new clients 237 # stop listening for new clients
215 self._listen_socket.close() 238 self._listen_socket.close()
216 239
240 def send_list(self, clid, list_items, command=''):
241 if self._clients[clid].MXP_ENABLED:
242 output = ""
243 if command != '':
244 command = command + ' '
245 for idx, item in enumerate(list_items):
246 if idx > 0:
247 output += ", "
248 output += "<send \"{}&text;\">{}</send>".format(command, item)
249 self.mxp_secure(clid, output)
250 else:
251 self.send_message(clid, ', '.join(list_items))
252
253 def mxp_secure(self, clid, message):
254 bytes_to_send = bytearray("\x1b[1z{}\x1b[6z\r\n".format(message), 'utf-8')
255 client_socket = self._clients[clid].socket
256 client_socket.sendall(bytes_to_send)
257
258 def raw_send(self, clid, bytes_to_send):
259 client_socket = self._clients[clid].socket
260 client_socket.sendall(bytes_to_send)
261
217 def _attempt_send(self, clid, data): 262 def _attempt_send(self, clid, data):
218 # python 2/3 compatability fix - convert non-unicode string to unicode 263 # python 2/3 compatability fix - convert non-unicode string to unicode
219 if sys.version < '3' and type(data) != unicode: 264 if sys.version < '3' and type(data) != unicode:
...@@ -266,11 +311,24 @@ class MudServer(object): ...@@ -266,11 +311,24 @@ class MudServer(object):
266 # 'recv' will return immediately without waiting 311 # 'recv' will return immediately without waiting
267 joined_socket.setblocking(False) 312 joined_socket.setblocking(False)
268 313
314
269 # construct a new _Client object to hold info about the newly connected 315 # construct a new _Client object to hold info about the newly connected
270 # client. Use 'nextid' as the new client's id number 316 # client. Use 'nextid' as the new client's id number
271 self._clients[self._nextid] = MudServer._Client(joined_socket, addr[0], 317 self._clients[self._nextid] = MudServer._Client(joined_socket, addr[0],
272 "", time.time()) 318 "", time.time())
273 319
320 MSSP_REQUEST = bytearray([self._TN_IAC, self._TN_WILL, self._MSSP])
321 joined_socket.sendall(MSSP_REQUEST)
322
323 # MSDP_REQUEST = bytearray([self._TN_IAC, self._TN_WILL, self._MSDP])
324 # joined_socket.sendall(MSDP_REQUEST)
325
326 MXP_REQUEST = bytearray([self._TN_IAC, self._TN_WILL, self._MXP])
327 joined_socket.sendall(MXP_REQUEST)
328
329 NAWS_REQUEST = bytes([self._TN_IAC, self._TN_DO, self._NAWS])
330 joined_socket.sendall(NAWS_REQUEST)
331
274 # add a new player occurence to the new events list with the player's 332 # add a new player occurence to the new events list with the player's
275 # id number 333 # id number
276 self._new_events.append((self._EVENT_NEW_PLAYER, self._nextid)) 334 self._new_events.append((self._EVENT_NEW_PLAYER, self._nextid))
...@@ -317,7 +375,7 @@ class MudServer(object): ...@@ -317,7 +375,7 @@ class MudServer(object):
317 375
318 try: 376 try:
319 # read data from the socket, using a max length of 4096 377 # read data from the socket, using a max length of 4096
320 data = cl.socket.recv(1024).decode("latin1") 378 data = cl.socket.recv(4096)
321 379
322 # process the data, stripping out any special Telnet commands 380 # process the data, stripping out any special Telnet commands
323 message = self._process_sent_data(cl, data) 381 message = self._process_sent_data(cl, data)
...@@ -357,6 +415,52 @@ class MudServer(object): ...@@ -357,6 +415,52 @@ class MudServer(object):
357 # player's id number 415 # player's id number
358 self._new_events.append((self._EVENT_PLAYER_LEFT, clid)) 416 self._new_events.append((self._EVENT_PLAYER_LEFT, clid))
359 417
418 def remote_echo(self, clid, enable=True):
419 if enable:
420 bytes_to_send = bytearray([self._TN_IAC, self._TN_WONT, self._ECHO])
421 else:
422 bytes_to_send = bytearray([self._TN_IAC, self._TN_WILL, self._ECHO])
423 client_socket = self._clients[clid].socket
424 client_socket.sendall(bytes_to_send)
425
426 def _send_mssp(self, client):
427 byte_data = bytearray([self._TN_IAC, self._TN_SUB_START, self._MSSP, self._MSSP_VAR])
428 byte_data.extend(b'PLAYERS')
429 byte_data.append(self._MSSP_VAL)
430 byte_data.extend(str(len(self._clients)).encode())
431 byte_data.append(self._MSSP_VAR)
432 byte_data.extend(b'UPTIME')
433 byte_data.append(self._MSSP_VAL)
434 byte_data.extend(str(time.time() - self.start_time).encode())
435 byte_data.append(self._MSSP_VAR)
436 byte_data.extend(b'NAME')
437 byte_data.append(self._MSSP_VAL)
438 byte_data.extend(b'WeeMud')
439 byte_data.extend([self._TN_IAC, self._TN_SUB_END])
440
441 print("SENDING MSSP")
442 print(byte_data)
443 client.socket.sendall(byte_data)
444
445 # def _send_msdp_array(self, client, var, vals):
446 # byte_data = bytearray([self._TN_IAC, self._TN_SUB_START, self._MSDP, self._MSDP_VAR])
447 # byte_data.extend(var)
448 # byte_data.extend([self._MSDP_VAL, self._MSDP_ARRAY_OPEN])
449 # for val in vals:
450 # byte_data.append(self._MSDP_VAL)
451 # byte_data.extend(val)
452 # byte_data.extend([self._MSDP_ARRAY_CLOSE, self._TN_IAC, self._TN_SUB_END])
453 # print("SENDING ARRAY")
454 # out = ""
455 # out2 = ""
456 # for b in byte_data:
457 # out += " " + str(b)
458 # out2 += " " + chr(b)
459 # print(out)
460 # print(out2)
461 # print(byte_data.hex())
462 # client.socket.sendall(byte_data)
463
360 def _process_sent_data(self, client, data): 464 def _process_sent_data(self, client, data):
361 465
362 # the Telnet protocol allows special command codes to be inserted into 466 # the Telnet protocol allows special command codes to be inserted into
...@@ -364,12 +468,22 @@ class MudServer(object): ...@@ -364,12 +468,22 @@ class MudServer(object):
364 # any of these codes, but we must at least detect and skip over them 468 # any of these codes, but we must at least detect and skip over them
365 # so that we don't interpret them as text data. 469 # so that we don't interpret them as text data.
366 # More info on the Telnet protocol can be found here: 470 # More info on the Telnet protocol can be found here:
367 # http://pcmicro.com/netfoss/telnet.html 471 # http://pcmicro.com/netfoss/telnet.htm
368 472
369 # start with no message and in the normal state 473 # start with no message and in the normal state
370 message = None 474 message = None
371 state = self._READ_STATE_NORMAL 475 state = self._READ_STATE_NORMAL
372 476
477 out = ""
478 out2 = ""
479 for b in data:
480 out += " " + str(b)
481 out2 += " " + chr(b)
482 print(out)
483 print(out2)
484 option_data = bytearray()
485 option_state = 0
486 option_support = 0
373 # go through the data a character at a time 487 # go through the data a character at a time
374 for c in data: 488 for c in data:
375 489
...@@ -381,13 +495,13 @@ class MudServer(object): ...@@ -381,13 +495,13 @@ class MudServer(object):
381 # if we received the special 'interpret as command' code, 495 # if we received the special 'interpret as command' code,
382 # switch to 'command' state so that we handle the next 496 # switch to 'command' state so that we handle the next
383 # character as a command code and not as regular text data 497 # character as a command code and not as regular text data
384 if ord(c) == self._TN_INTERPRET_AS_COMMAND: 498 if c == self._TN_IAC:
385 state = self._READ_STATE_COMMAND 499 state = self._READ_STATE_COMMAND
386 500
387 # if we get a newline character, this is the end of the 501 # if we get a newline character, this is the end of the
388 # message. Set 'message' to the contents of the buffer and 502 # message. Set 'message' to the contents of the buffer and
389 # clear the buffer 503 # clear the buffer
390 elif c == "\n": 504 elif chr(c) == "\n":
391 message = client.buffer 505 message = client.buffer
392 client.buffer = "" 506 client.buffer = ""
393 507
...@@ -395,13 +509,13 @@ class MudServer(object): ...@@ -395,13 +509,13 @@ class MudServer(object):
395 # types them. So if we get a backspace character, this is where 509 # types them. So if we get a backspace character, this is where
396 # the user has deleted a character and we should delete the 510 # the user has deleted a character and we should delete the
397 # last character from the buffer. 511 # last character from the buffer.
398 elif c == "\x08": 512 elif chr(c) == "\x08":
399 client.buffer = client.buffer[:-1] 513 client.buffer = client.buffer[:-1]
400 514
401 # otherwise it's just a regular character - add it to the 515 # otherwise it's just a regular character - add it to the
402 # buffer where we're building up the received message 516 # buffer where we're building up the received message
403 else: 517 else:
404 client.buffer += c 518 client.buffer += chr(c)
405 519
406 # command state 520 # command state
407 elif state == self._READ_STATE_COMMAND: 521 elif state == self._READ_STATE_COMMAND:
...@@ -410,16 +524,41 @@ class MudServer(object): ...@@ -410,16 +524,41 @@ class MudServer(object):
410 # that the following characters are a list of options until 524 # that the following characters are a list of options until
411 # we're told otherwise. We switch into 'subnegotiation' state 525 # we're told otherwise. We switch into 'subnegotiation' state
412 # to handle this 526 # to handle this
413 if ord(c) == self._TN_SUBNEGOTIATION_START: 527 if c == self._TN_SUB_START:
414 state = self._READ_STATE_SUBNEG 528 state = self._READ_STATE_SUBNEG
415 529
416 # if the command code is one of the 'will', 'wont', 'do' or 530 # if the command code is one of the 'will', 'wont', 'do' or
417 # 'dont' commands, the following character will be an option 531 # 'dont' commands, the following character will be an option
418 # code so we must remain in the 'command' state 532 # code so we must remain in the 'command' state
419 elif ord(c) in (self._TN_WILL, self._TN_WONT, self._TN_DO, 533 elif c in (self._TN_WILL, self._TN_WONT, self._TN_DO,
420 self._TN_DONT): 534 self._TN_DONT):
535 option_support = c
421 state = self._READ_STATE_COMMAND 536 state = self._READ_STATE_COMMAND
422 537
538 elif c == self._MXP:
539 if option_support == self._TN_DO:
540 print("MXP Enabled")
541 client.MXP_ENABLED = True
542 # Enable for mushclient "on command"
543 byte_data = bytearray([self._TN_IAC, self._TN_SUB_START, self._MXP, self._TN_IAC, self._TN_SUB_END])
544 client.socket.sendall(byte_data)
545 else:
546 print("MXP Disabled")
547 client.MXP_ENABLED = False
548 state = self._READ_STATE_NORMAL
549
550 elif c == self._MSSP:
551 if option_support == self._TN_DO:
552 self._send_mssp(client)
553 state = self._READ_STATE_NORMAL
554
555 # elif c == self._MSDP:
556 # if option_support == self._TN_DO:
557 # client.MSDP_ENABLED = True
558 # else:
559 # client.MSDP_ENABLED = False
560 # state = self._READ_STATE_NORMAL
561
423 # for all other command codes, there is no accompanying data so 562 # for all other command codes, there is no accompanying data so
424 # we can return to 'normal' state. 563 # we can return to 'normal' state.
425 else: 564 else:
...@@ -431,8 +570,55 @@ class MudServer(object): ...@@ -431,8 +570,55 @@ class MudServer(object):
431 # if we reach an 'end of subnegotiation' command, this ends the 570 # if we reach an 'end of subnegotiation' command, this ends the
432 # list of options and we can return to 'normal' state. 571 # list of options and we can return to 'normal' state.
433 # Otherwise we must remain in this state 572 # Otherwise we must remain in this state
434 if ord(c) == self._TN_SUBNEGOTIATION_END: 573 if c == self._TN_SUB_END:
574 if option_state == self._READ_NAWS:
575 height = 30
576 width = 100
577 height, width = struct.unpack('>hh', option_data)
578 if height > 0:
579 client.height = height
580 if width > 0:
581 client.width = width
582 print("Got NAWS Width: %d Height: %d" % (client.width, client.height))
583 option_state = 0
584 option_data = bytearray()
585 # elif option_state == self._READ_MSDP:
586 # print("GOT MSDP")
587 # print(option_data)
588 # if option_data[0] == self._MSDP_VAR:
589 # var = ''
590 # val = ''
591 # val_started = False
592 # for v in option_data[1:]:
593 # print(v)
594 # if v == self._TN_IAC:
595 # break
596 # if v == self._MSDP_VAL:
597 # val_started = True
598 # continue
599 # if val_started:
600 # val += chr(v)
601 # else:
602 # var += chr(v)
603 # print("VAR: " + var)
604 # print("VAL: " + val)
605 # if var == "LIST" and val == "COMMANDS":
606 # vals = [b"LIST", b"REPORT", b"SEND"]
607 # self._send_msdp_array(client, b"COMMANDS", vals)
608
435 state = self._READ_STATE_NORMAL 609 state = self._READ_STATE_NORMAL
436 610
611 # if c == self._MSDP:
612 # option_state = self._READ_MSDP
613 # option_data = bytearray()
614
615 if c == self._NAWS:
616 option_state = self._READ_NAWS
617 option_data = bytearray()
618
619 # if option_state in [self._READ_NAWS, self._READ_MSDP] and c not in [self._MSDP, self._NAWS] and c != self._TN_IAC:
620 if option_state in [self._READ_NAWS] and c not in [self._NAWS] and c != self._TN_IAC:
621 option_data.append(c)
622
437 # return the contents of 'message' which is either a string or None 623 # return the contents of 'message' which is either a string or None
438 return message 624 return message
......
1 {"name": "test", "room": "Room001", "inventory": {"candle": 1}, "prompt": "h %hp m %mp s %st> ", "aliases": {}, "hp": 74, "mp": 5.0, "sta": 1.2000000000000361, "aa": "1d2", "mpr": 0.25, "star": 0.4, "maxhp": 953, "maxmp": 10, "maxsta": 10, "weapon": "sword", "sp": {"fireball": {"cost": 5, "dmg": "2d4", "desc": "A fireball blasts from your fingertips striking the target"}}, "at": {"kick": {"cost": 5, "dmg": "2d4", "desc": "You unleash a powerful kick"}}}
...\ No newline at end of file ...\ No newline at end of file
1 {"name": "test", "password": true, "room": "Tavern", "inventory": {"candle": 1}, "prompt": "h %hp m %mp s %st> ", "aliases": {}, "hp": 74, "mp": 10.0, "sta": 10.00000000000004, "aa": "1d2", "mpr": 0.25, "star": 0.4, "maxhp": 953, "maxmp": 10, "maxsta": 10, "weapon": "sword", "sp": {"fireball": {"cost": 5, "dmg": "2d4", "desc": "A fireball blasts from your fingertips striking the target"}}, "at": {"kick": {"cost": 5, "dmg": "2d4", "desc": "You unleash a powerful kick"}}}
...\ No newline at end of file ...\ No newline at end of file
......