Huge update and added more protocol handling to the mudserver.py
Showing
8 changed files
with
277 additions
and
32 deletions
... | @@ -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(): | ... | ... |
commands/score.txt
0 → 100644
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, "") | ... | ... |
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment