aboutsummaryrefslogtreecommitdiff
path: root/mud.py
blob: 9a06023d578d12186545251217e004f4825bc291 (plain) (blame)
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
import traceback
import uuid

from twisted.internet.protocol import Factory

from auth import Auth
from database import DbSession
from netclass import netclass_root, jsonconverter
from servermessage import ServerMessage, ServerMessageStream

import pong
import save
from messagehandler import handlers

class MudConnection(ServerMessageStream):
	def __init__(self, factory, addr):
		self.factory = factory
		self.addr = addr
		self.authsession = None
		super().__init__()
	def connectionMade(self):
		self.dbsession = DbSession()
		
		self.pong = pong.PongState(self)
		
		self.auth = Auth(self.dbsession, self.addr.host)
		print(f"{self.addr.host} connected.")
		self.send_message("Welcome", str(uuid.uuid4()))
		
		# If the server shuts down, all the clients that were left open
		# will reconnect as soon as it comes back on.  But, they don't
		# bother to re-authenticate on their own, so the server has to
		# prompt them to save to get the copy of the auth token that is
		# in the save.  When the client joins on its own startup,
		# and authenticates anyway, hopefully this won't matter...
		#self.run_command("sos.save")
		# but it is commented out cause the lua script doesn't work
	def connectionLost(self, reason):
		print(f"{self.addr.host} disconnected.")
		self.closing = True
		self.pong.leave()
		self.dbsession.close()
	def serverMessageReceived(self, message):
		if message.Name not in ["pong_mp_setballpos", "pong_mp_setopponenty"]:
			print(f"{self.addr.host}: {message.Name}({repr(message.Contents)})")
		if message.Name in handlers:
			try:
				handlers[message.Name](self, message.Contents)
				self.dbsession.commit()
			except:
				self.dbsession.rollback()
				self.error(traceback.format_exc())
				traceback.print_exc()
		else:
			self.error(f"Unimplemented message {message.Name}.  Thanks for using Shift Gears!")
	
	def send_message(self, name, contents = None, guid = None):
		if contents is not None and not isinstance(contents, str):
			contents = jsonconverter.to_json(contents)
		guid = str(guid)
		self.sendServerMessage(ServerMessage(name, contents, guid))
	
	def error(self, message):
		# The content of the Error message is deserialised at the other
		# end as an Exception, but only the Message member is read.
		self.send_message("Error", {"ClassName":"System.Exception","Message":message,"Data":None,"InnerException":None,"HelpURL":None,"StackTraceString":None,"RemoteStackTraceString":None,"RemoteStackIndex":0,"ExceptionMethod":None,"HResult":-2146233088,"Source":None})
	
	# executes Lua code on the client...its that easy
	def run(self, script):
		self.send_message("run", {"script": script})
	
	# executes a ShiftOS command on the client
	def run_command(self, cmd):
		# We don't use trm_invokecommand because it expects the prompt
		# to be sent to it before the command and it's not always
		# feasible to figure out what the prompt is.
		self.run(f"sos.runCommand({repr(cmd)})")
	
	def infobox(self, msg, title = "MUD"):
		self.invoke_command("infobox.show" + jsonconverter.to_json({"title": title, "msg": msg}))

class MudConnectionFactory(Factory):
	def __init__(self):
		self.pong = pong.PongMatchmaking()
	def buildProtocol(self, addr):
		return MudConnection(self, addr)