diff --git a/config.py b/config.py
index be94e15..433dade 100644
--- a/config.py
+++ b/config.py
@@ -1,14 +1,26 @@
+import json
+import os
+
+def override(fn):
+ with open(fn, 'rt') as f:
+ for k, v in json.load(f).iteritems():
+ globals()[k] = v
+
+# Default configuration options follow - they can be overridden with a JSON file
+
# Port to run the telnet server on.
PORT_TELNET = 19999
-# Port to run the flash policy server on. Set to None to turn off.
-PORT_FLASHPOLICY = 20001
+# Port to run the command server on. Used to trigger saving.
+PORT_CMDSERVER = 20002
# Hostname to bind servers on. Leave as "" for all.
BIND_HOSTNAME = ""
+
# width and height; default 80x25
W = 80
H = 25
# directory to save ANSI pictures to. leave as "." for current directory. no trailing slash required. "" == /
-DIR_ANSI = "/home/jeremy/sites/marmots/ansi"
+DIR_ANSI = "."
+
# authorization. Options are "Noop" (make up a username, no password), "Drupal" (fetches from MySQL Drupal database),
#"DrupalBcrypt" (fetches from MySQL Drupal database hacked to bcrypt the md5 hash - basically just Glorious Trainwrecks)
AUTH = "Noop"
@@ -18,5 +30,5 @@ AUTH = "Noop"
#drupaldb_password = "password"
#drupaldb_host = "localhost"
-# Port to run the command server on. Set to None to turn off. Only set this port for testing: it will allow anyone to take down the server!
-PORT_CMDSERVER = 20002
+# Path to the object database to load / save
+ODBPATH = "whiteboard.marm"
diff --git a/telnet.py b/telnet.py
index 42d8bce..dbaa8c5 100644
--- a/telnet.py
+++ b/telnet.py
@@ -158,13 +158,6 @@ class AnsiFactory(ServerFactory):
print "built protocol for ", addr
return p
-class FlashPolicy(basic.LineReceiver):
- delimiter = '\0'
-
- def lineReceived(self,line):
- if line == "":
- self.sendLine("")
-
class CmdProtocol(basic.LineReceiver):
def connectionMade(self):
if self.transport.getHost().host != "127.0.0.1":
@@ -172,7 +165,7 @@ class CmdProtocol(basic.LineReceiver):
self.transport.loseConnection()
def lineReceived(self, line):
- self.transport.write(self.factory.fnCmd(line) + self.delimiter)
+ self.transport.write(self.factory.fnCmd(line).encode('utf-8') + self.delimiter)
class CmdFactory(ServerFactory):
def __init__(self, fnCmd):
@@ -185,13 +178,7 @@ class CmdFactory(ServerFactory):
def RunServer(fnRun):
log.startLogging(sys.stdout)
-
- factoryPolicy = Factory()
- factoryPolicy.protocol = FlashPolicy
-
reactor.listenTCP(config.PORT_TELNET, AnsiFactory(fnRun), 50, config.BIND_HOSTNAME)
- if config.PORT_FLASHPOLICY:
- reactor.listenTCP(config.PORT_FLASHPOLICY, factoryPolicy, 50, config.BIND_HOSTNAME)
reactor.run()
def RunCmdServer(fnCmd):
diff --git a/tpers.py b/tpers.py
index b7c4c39..8478a61 100644
--- a/tpers.py
+++ b/tpers.py
@@ -273,3 +273,34 @@ class TPT(clsTuple):
def __reduce__(self):
return (MkTransparent, (tuple([MkPersistable(x) for x in self]),))
+
+class Partial(object):
+ def __init__(self, method, *args, **kwargs):
+ self.method = method
+ self.args = args
+ self.kwargs = kwargs
+
+ def __call__(self, *args, **kwargs):
+ mergedkwargs = self.kwargs.copy()
+ mergedkwargs.update(kwargs)
+ return self.method(*(self.args + args), **mergedkwargs)
+
+def _pickle_method(method):
+ func_name = method.im_func.__name__
+ obj = method.im_self
+ cls = method.im_class
+ return _unpickle_method, (func_name, obj, cls)
+
+def _unpickle_method(func_name, obj, cls):
+ for cls in cls.mro():
+ try:
+ func = cls.__dict__[func_name]
+ except KeyError:
+ pass
+ else:
+ break
+ return func.__get__(obj, cls)
+
+import copy_reg
+import types
+copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)
diff --git a/whiteboard.py b/whiteboard.py
index 6a01ad5..ae6b7d7 100644
--- a/whiteboard.py
+++ b/whiteboard.py
@@ -7,6 +7,7 @@ import telnet
import time
import login
import weakref
+import sys
class Layer(TPrs):
def InitPersistent(self, ascr, stName):
@@ -816,13 +817,14 @@ class GameLobby(Game):
game = GameSprEdit(self, drawing)
else:
assert False, "Lobby not prepared to deal with drawing of type " + drawing.StType()
- def KillBoard():
- del self.mpdrawing_game[drawing]
- game.rgdgdie.append(KillBoard)
+ game.rgdgdie.append(Partial(self.KillBoard, drawing))
self.mpdrawing_game[drawing] = game
return game
return self.mpdrawing_game[drawing]
+ def KillBoard(self, drawing):
+ del self.mpdrawing_game[drawing]
+
def CclientDrawing(self, drawing):
if drawing in self.mpdrawing_game:
return len(self.mpdrawing_game[drawing].rgclient)
@@ -892,4 +894,6 @@ class GameSprEdit(GameWB):
return CursorSprite
if __name__ == "__main__":
- Run(RunnerWB, "whiteboard.marm")
+ if len(sys.argv) > 1:
+ config.override(sys.argv[1])
+ Run(RunnerWB, config.ODBPATH)