WIP robot creation in board editor!
- refactor client - now has a _stack_ of current Games, the top of which is active - prevents shutdown of whiteboard when "leaving" to edit source code - add tpers.StaticIndex / inspector.py for interactively querying object graphs
This commit is contained in:
parent
f7c33a23a6
commit
10edbacf86
33
basetoken.py
33
basetoken.py
|
@ -73,7 +73,7 @@ class Terminal(Token):
|
||||||
self.fBlink = fBlink
|
self.fBlink = fBlink
|
||||||
|
|
||||||
def getKey(self):
|
def getKey(self):
|
||||||
return self.client.evKey.receive(self)
|
return self.client.EvKey(self.game).receive(self)
|
||||||
|
|
||||||
def getPrintableKey(self):
|
def getPrintableKey(self):
|
||||||
while True:
|
while True:
|
||||||
|
@ -199,9 +199,14 @@ class Terminal(Token):
|
||||||
|
|
||||||
class LeaveJoinToken(Token):
|
class LeaveJoinToken(Token):
|
||||||
def run(self):
|
def run(self):
|
||||||
|
evLeave = self.game.evSuspend if self.FOnActivate() else self.game.evLeave
|
||||||
|
evJoin = self.game.evActivate if self.FOnActivate() else self.game.evJoin
|
||||||
while True:
|
while True:
|
||||||
Event.selectDg(self, (self.game.evLeave, self.OnLeave), (self.game.evJoin, self.OnJoin))
|
Event.selectDg(self, (evLeave, self.OnLeave), (evJoin, self.OnJoin))
|
||||||
|
|
||||||
|
def FOnActivate(self):
|
||||||
|
return False
|
||||||
|
|
||||||
class AutoJoiner(LeaveJoinToken):
|
class AutoJoiner(LeaveJoinToken):
|
||||||
def InitPersistent(self, owner, *rgclsTok):
|
def InitPersistent(self, owner, *rgclsTok):
|
||||||
Token.InitPersistent(self, owner)
|
Token.InitPersistent(self, owner)
|
||||||
|
@ -234,6 +239,9 @@ class AliveWithPlayers(LeaveJoinToken):
|
||||||
Token.InitTransient(self)
|
Token.InitTransient(self)
|
||||||
self.rgclient = []
|
self.rgclient = []
|
||||||
|
|
||||||
|
def FOnActivate(self):
|
||||||
|
return True
|
||||||
|
|
||||||
def OnLeave(self, client):
|
def OnLeave(self, client):
|
||||||
self.rgclient.remove(client)
|
self.rgclient.remove(client)
|
||||||
if len(self.rgclient) == 0:
|
if len(self.rgclient) == 0:
|
||||||
|
@ -705,9 +713,18 @@ class MiMenuHoriz(MiMenuI):
|
||||||
mi.DrawWithParent(selor, ascr, x, y, wT, miSelected == mi)
|
mi.DrawWithParent(selor, ascr, x, y, wT, miSelected == mi)
|
||||||
x = x + wT
|
x = x + wT
|
||||||
|
|
||||||
def DgProjectMiButton(dgExec):
|
class ProjectedValue(TPrs):
|
||||||
|
def InitPersistent(self, value, dgStName):
|
||||||
|
self.value = value
|
||||||
|
self.dgStName = dgStName
|
||||||
|
def StName(self):
|
||||||
|
return self.dgStName(self.value)
|
||||||
|
def Value(self):
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def DgProjectMiButton(dgExec, dgStName = None):
|
||||||
def DgProject(value):
|
def DgProject(value):
|
||||||
return MiButton(None, lambda: dgExec(value), value)
|
return MiButton(None, lambda: dgExec(value), ProjectedValue(value, dgStName) if dgStName else value)
|
||||||
return DgProject
|
return DgProject
|
||||||
|
|
||||||
class RgmiProjected(TPrs):
|
class RgmiProjected(TPrs):
|
||||||
|
@ -781,13 +798,15 @@ class OvStatic(TokenClient):
|
||||||
|
|
||||||
def Value(self, stName = None):
|
def Value(self, stName = None):
|
||||||
return self.miMenu.Value(stName)
|
return self.miMenu.Value(stName)
|
||||||
|
|
||||||
class OvMenu(OvStatic):
|
class OvMenu(OvStatic):
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
self.miMenu.HandleKey(self.client.evKey.receive(self))
|
self.miMenu.HandleKey(self.client.EvKey(self.game).receive(self))
|
||||||
|
|
||||||
def draw(self, ascr, client):
|
def draw(self, ascr, client):
|
||||||
self.drawI(ascr, client, True)
|
self.drawI(ascr, client, True)
|
||||||
|
|
||||||
class OvPopup(OvStatic):
|
class OvPopup(OvStatic):
|
||||||
def InitPersistent(self, owner, client, miMenu):
|
def InitPersistent(self, owner, client, miMenu):
|
||||||
OvStatic.InitPersistent(self, owner, client, miMenu, self.MIDDLE, "drawable", "menu")
|
OvStatic.InitPersistent(self, owner, client, miMenu, self.MIDDLE, "drawable", "menu")
|
||||||
|
@ -800,7 +819,7 @@ class OvPopup(OvStatic):
|
||||||
self.evShow.receive(self)
|
self.evShow.receive(self)
|
||||||
self.fAwake = True
|
self.fAwake = True
|
||||||
while self.fAwake:
|
while self.fAwake:
|
||||||
key = self.client.evKey.receive(self)
|
key = self.client.EvKey(self.game).receive(self)
|
||||||
if not self.miMenu.HandleKey(key):
|
if not self.miMenu.HandleKey(key):
|
||||||
if key == ansi.K_TAB or key == ansi.K_DEL or key == ' ' or ansi.FEnter(key):
|
if key == ansi.K_TAB or key == ansi.K_DEL or key == ' ' or ansi.FEnter(key):
|
||||||
self.fAwake = False
|
self.fAwake = False
|
||||||
|
|
112
engine.py
112
engine.py
|
@ -184,7 +184,7 @@ class Ownable(TPrs):
|
||||||
tok.die()
|
tok.die()
|
||||||
self.DontPersist()
|
self.DontPersist()
|
||||||
|
|
||||||
@Version(2)
|
@Version(3)
|
||||||
class Game(Ownable):
|
class Game(Ownable):
|
||||||
def InitPersistent(self):
|
def InitPersistent(self):
|
||||||
Ownable.InitPersistent(self)
|
Ownable.InitPersistent(self)
|
||||||
|
@ -194,12 +194,16 @@ class Game(Ownable):
|
||||||
self.rgdgdie = []
|
self.rgdgdie = []
|
||||||
self.evJoin = Event(self)
|
self.evJoin = Event(self)
|
||||||
self.evLeave = Event(self)
|
self.evLeave = Event(self)
|
||||||
|
self.evActivate = Event(self)
|
||||||
|
self.evSuspend = Event(self)
|
||||||
self.mpuser_cldg = {}
|
self.mpuser_cldg = {}
|
||||||
self.CreateRgtok(self.GetRgclsTokPers(), True)
|
self.CreateRgtok(self.GetRgclsTokPers(), True)
|
||||||
|
|
||||||
def InitTransient(self):
|
def InitTransient(self):
|
||||||
self.MakeTransient("fScheduled", False)
|
self.MakeTransient("fScheduled", False)
|
||||||
self.rgclient = []
|
self.rgclientActive = []
|
||||||
|
self.rgclientSuspended = []
|
||||||
|
self.rgclientLeaving = []
|
||||||
self.rgproc = [PTimer(), PEvent(), PDraw(*self.GetRgtagDraw())]
|
self.rgproc = [PTimer(), PEvent(), PDraw(*self.GetRgtagDraw())]
|
||||||
for proc in self.rgproc:
|
for proc in self.rgproc:
|
||||||
proc.setGame(self)
|
proc.setGame(self)
|
||||||
|
@ -240,6 +244,9 @@ class Game(Ownable):
|
||||||
if not fPersist:
|
if not fPersist:
|
||||||
tok.DontPersist()
|
tok.DontPersist()
|
||||||
|
|
||||||
|
def RgclientConnected(self):
|
||||||
|
return self.rgclientActive + self.rgclientSuspended
|
||||||
|
|
||||||
def tagToken(self, token, tag):
|
def tagToken(self, token, tag):
|
||||||
if not (tag in self.mptagTokenset):
|
if not (tag in self.mptagTokenset):
|
||||||
self.mptagTokenset[tag] = set([token])
|
self.mptagTokenset[tag] = set([token])
|
||||||
|
@ -268,10 +275,12 @@ class Game(Ownable):
|
||||||
return rgtoken
|
return rgtoken
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
|
assert len(self.rgclientSuspended) == 0
|
||||||
self.running = False
|
self.running = False
|
||||||
self.fQuit = True
|
self.fQuit = True
|
||||||
|
|
||||||
def finish(self, rc = None):
|
def finish(self, rc = None):
|
||||||
|
assert len(self.rgclientSuspended) == 0
|
||||||
self.running = False
|
self.running = False
|
||||||
self.rc = rc
|
self.rc = rc
|
||||||
class QuitException(Exception):
|
class QuitException(Exception):
|
||||||
|
@ -291,22 +300,44 @@ class Game(Ownable):
|
||||||
proc.process()
|
proc.process()
|
||||||
if not self.running:
|
if not self.running:
|
||||||
self.die()
|
self.die()
|
||||||
for client in self.rgclient:
|
for client in self.rgclientActive:
|
||||||
client.leaveGame(self.rc)
|
if client not in self.rgclientLeaving:
|
||||||
for client in self.rgclient:
|
client.leaveGame(self.rc)
|
||||||
|
deadClients = list(self.rgclientLeaving)
|
||||||
|
del self.rgclientLeaving[:]
|
||||||
|
for client in deadClients:
|
||||||
|
if client in self.rgclientActive:
|
||||||
|
self.rgclientActive.remove(client)
|
||||||
|
if client in self.rgclientSuspended:
|
||||||
|
self.rgclientSuspended.remove(client)
|
||||||
client.postRunStep()
|
client.postRunStep()
|
||||||
finally:
|
finally:
|
||||||
self.fScheduled = False
|
self.fScheduled = False
|
||||||
return self.running
|
return self.running
|
||||||
def joinGame(self,client):
|
def joinGame(self,client):
|
||||||
self.rgclient.append(client)
|
self.rgclientActive.append(client)
|
||||||
self.evJoin.fire(client)
|
self.evJoin.fire(client)
|
||||||
|
self.evActivate.fire(client)
|
||||||
|
|
||||||
def leaveGame(self, client):
|
def leaveGame(self, client):
|
||||||
self.evLeave.fire(client)
|
if self.running:
|
||||||
|
if client in self.rgclientActive:
|
||||||
|
self.evSuspend.fire(client)
|
||||||
|
self.evLeave.fire(client)
|
||||||
|
self.rgclientLeaving.append(client)
|
||||||
|
|
||||||
|
def reactivateClient(self, client):
|
||||||
|
assert client in self.rgclientSuspended
|
||||||
|
self.rgclientSuspended.remove(client)
|
||||||
|
self.rgclientActive.append(client)
|
||||||
|
self.evActivate.fire(client)
|
||||||
|
|
||||||
|
def suspendClient(self, client):
|
||||||
|
assert client in self.rgclientActive
|
||||||
|
self.rgclientActive.remove(client)
|
||||||
|
self.rgclientSuspended.append(client)
|
||||||
|
self.evSuspend.fire(client)
|
||||||
|
|
||||||
def leaveGameI(self, client):
|
|
||||||
self.rgclient.remove(client)
|
|
||||||
def ensureRun(self):
|
def ensureRun(self):
|
||||||
self.running = True
|
self.running = True
|
||||||
if not self.fScheduled:
|
if not self.fScheduled:
|
||||||
|
@ -315,6 +346,9 @@ class Game(Ownable):
|
||||||
def UpgradeFrom(self, versionOld):
|
def UpgradeFrom(self, versionOld):
|
||||||
if versionOld < 2:
|
if versionOld < 2:
|
||||||
self.mpuser_cldg = {}
|
self.mpuser_cldg = {}
|
||||||
|
if versionOld < 3:
|
||||||
|
self.evActivate = Event(self)
|
||||||
|
self.evSuspend = Event(self)
|
||||||
|
|
||||||
# Client data
|
# Client data
|
||||||
@Version(2)
|
@Version(2)
|
||||||
|
@ -336,9 +370,9 @@ class Client(TPrs):
|
||||||
def InitTransient(self):
|
def InitTransient(self):
|
||||||
self.chRun = stackless.channel()
|
self.chRun = stackless.channel()
|
||||||
self.gameCurr = None
|
self.gameCurr = None
|
||||||
|
self.mpgame_evKey = {}
|
||||||
|
self.rggameSuspended = []
|
||||||
self.chCont = None
|
self.chCont = None
|
||||||
self.fRunning = False
|
|
||||||
self.dgJoinGame = None
|
|
||||||
self.rgdgQuit = []
|
self.rgdgQuit = []
|
||||||
self.fQuit = False
|
self.fQuit = False
|
||||||
self.cld = None
|
self.cld = None
|
||||||
|
@ -353,19 +387,33 @@ class Client(TPrs):
|
||||||
if self._runTskRun():
|
if self._runTskRun():
|
||||||
self.gameCurr.ensureRun()
|
self.gameCurr.ensureRun()
|
||||||
def joinGame(self, game):
|
def joinGame(self, game):
|
||||||
assert not self.fRunning, "already running"
|
if not self.gameCurr:
|
||||||
chCont = stackless.channel()
|
chCont = stackless.channel()
|
||||||
self.chRun.send((game, chCont))
|
self.chRun.send((game, chCont))
|
||||||
return chCont.receive()
|
return chCont.receive()
|
||||||
|
else:
|
||||||
|
self.gameCurr.suspendClient(self)
|
||||||
|
self.rggameSuspended.append(self.gameCurr)
|
||||||
|
self.gameCurr = game
|
||||||
|
self.gameCurr.joinGame(self)
|
||||||
|
|
||||||
def leaveGame(self, rc = None):
|
def leaveGame(self, rc = None):
|
||||||
self.fRunning = False
|
|
||||||
self.gameCurr.leaveGame(self)
|
self.gameCurr.leaveGame(self)
|
||||||
self.rc = rc
|
if self.gameCurr in self.mpgame_evKey:
|
||||||
|
del self.mpgame_evKey[self.gameCurr]
|
||||||
|
|
||||||
|
if len(self.rggameSuspended) == 0:
|
||||||
|
self.gameCurr = None
|
||||||
|
self.rc = rc
|
||||||
|
else:
|
||||||
|
self.gameCurr = self.rggameSuspended.pop()
|
||||||
|
self.gameCurr.reactivateClient(self)
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
self.leaveGame(None)
|
while self.gameCurr:
|
||||||
|
self.leaveGame(None)
|
||||||
self.fQuit = True
|
self.fQuit = True
|
||||||
|
|
||||||
def _runTskRun(self):
|
def _runTskRun(self):
|
||||||
"run self.tskRun after it has been scheduled, and await results"
|
"run self.tskRun after it has been scheduled, and await results"
|
||||||
stackless.run()
|
stackless.run()
|
||||||
|
@ -373,20 +421,17 @@ class Client(TPrs):
|
||||||
return False
|
return False
|
||||||
self.gameCurr, self.chCont = self.chRun.receive()
|
self.gameCurr, self.chCont = self.chRun.receive()
|
||||||
self.gameCurr.joinGame(self)
|
self.gameCurr.joinGame(self)
|
||||||
self.fRunning = True
|
|
||||||
if self.dgJoinGame:
|
|
||||||
self.dgJoinGame(self, self.gameCurr)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def postRunStep(self):
|
def postRunStep(self):
|
||||||
if not self.fRunning:
|
if not self.gameCurr:
|
||||||
self.gameCurr.leaveGameI(self)
|
|
||||||
if not self.fQuit:
|
if not self.fQuit:
|
||||||
self.chCont.send(self.rc)
|
self.chCont.send(self.rc)
|
||||||
self.fQuit = not self._runTskRun()
|
self.fQuit = not self._runTskRun()
|
||||||
if self.fQuit:
|
if self.fQuit:
|
||||||
for dgQuit in self.rgdgQuit:
|
for dgQuit in self.rgdgQuit:
|
||||||
dgQuit()
|
dgQuit()
|
||||||
|
del self.rgdgQuit[:]
|
||||||
return self.fQuit
|
return self.fQuit
|
||||||
def beep(self):
|
def beep(self):
|
||||||
pass
|
pass
|
||||||
|
@ -401,9 +446,18 @@ class Client(TPrs):
|
||||||
|
|
||||||
def removeDgQuit(self, dgquit):
|
def removeDgQuit(self, dgquit):
|
||||||
self.rgdgQuit.remove(dgquit)
|
self.rgdgQuit.remove(dgquit)
|
||||||
def Cldg(self, game = None):
|
|
||||||
if game == None:
|
def EvKey(self, game):
|
||||||
game = self.gameCurr
|
if game:
|
||||||
|
if game not in self.mpgame_evKey:
|
||||||
|
self.mpgame_evKey[game] = Event(game)
|
||||||
|
return self.mpgame_evKey[game]
|
||||||
|
|
||||||
|
def KeyPressed(self, ch):
|
||||||
|
if self.gameCurr:
|
||||||
|
self.EvKey(self.gameCurr).fire(ch)
|
||||||
|
|
||||||
|
def Cldg(self, game):
|
||||||
return game.GetCldg(self.cld.user)
|
return game.GetCldg(self.cld.user)
|
||||||
|
|
||||||
class Processor(TPrs):
|
class Processor(TPrs):
|
||||||
|
@ -463,7 +517,7 @@ class PDraw(Processor):
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
if self.game.ms >= self.msDrawAgain:
|
if self.game.ms >= self.msDrawAgain:
|
||||||
for client in self.game.rgclient:
|
for client in self.game.rgclientActive:
|
||||||
ascr = ansi.Ascr()
|
ascr = ansi.Ascr()
|
||||||
for tok in self.game.rgtoken("drawable", self.rgprio):
|
for tok in self.game.rgtoken("drawable", self.rgprio):
|
||||||
try:
|
try:
|
||||||
|
@ -552,8 +606,8 @@ class Token(Taggable):
|
||||||
def runI(self):
|
def runI(self):
|
||||||
try:
|
try:
|
||||||
self.run()
|
self.run()
|
||||||
#except greenlet.GreenletExit:
|
except greenlet.GreenletExit:
|
||||||
# raise
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
print "token script crashed:"
|
print "token script crashed:"
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
7
inspector.py
Normal file
7
inspector.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# to use:
|
||||||
|
# python -i inspector.py
|
||||||
|
# >>> i.Rgclass() ...
|
||||||
|
from whiteboard import *
|
||||||
|
|
||||||
|
o = tpers.Odb.Load('whiteboard.marm')
|
||||||
|
i = tpers.StaticIndex().Populate(o)
|
15
scripting.py
15
scripting.py
|
@ -28,9 +28,10 @@ def RegStmt(clsStmt):
|
||||||
class Botdef(TPrs):
|
class Botdef(TPrs):
|
||||||
def InitPersistent(self, stName, ach, x, y):
|
def InitPersistent(self, stName, ach, x, y):
|
||||||
self.stName = stName
|
self.stName = stName
|
||||||
self.ast = ast
|
self.ach = ach
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
|
self.fPlayer = False
|
||||||
self.syntOnTouch = SyntBlock()
|
self.syntOnTouch = SyntBlock()
|
||||||
|
|
||||||
class Flagdef(TPrs):
|
class Flagdef(TPrs):
|
||||||
|
@ -62,6 +63,9 @@ class Vm(TPrs):
|
||||||
def FFlagSet(self, flagdef):
|
def FFlagSet(self, flagdef):
|
||||||
return self.mpflagdef[flagdef]
|
return self.mpflagdef[flagdef]
|
||||||
|
|
||||||
|
def Fail(self, stMessage, synt):
|
||||||
|
self.Log(Fail(stMessage, synt))
|
||||||
|
|
||||||
def Log(self, fail):
|
def Log(self, fail):
|
||||||
print(fail.stMessage, fail.synt)
|
print(fail.stMessage, fail.synt)
|
||||||
|
|
||||||
|
@ -155,7 +159,7 @@ class Synt(Typeable):
|
||||||
pass
|
pass
|
||||||
def Eval(self, vm):
|
def Eval(self, vm):
|
||||||
"Execute yourself, in the context of vm."
|
"Execute yourself, in the context of vm."
|
||||||
return Fail("Missing information", self)
|
return vm.Fail("Missing information", self)
|
||||||
|
|
||||||
def StypeForChild(self, syntChild):
|
def StypeForChild(self, syntChild):
|
||||||
"Return the stype that should be applied to the given child."
|
"Return the stype that should be applied to the given child."
|
||||||
|
@ -361,7 +365,7 @@ class SyntFlagRef(Synt):
|
||||||
try:
|
try:
|
||||||
return vm.FFlagSet(self.flagdef)
|
return vm.FFlagSet(self.flagdef)
|
||||||
except:
|
except:
|
||||||
return Fail("No such flag", self)
|
return vm.Fail("No such flag", self)
|
||||||
|
|
||||||
class SyntIsFlagSet(SyntDesc):
|
class SyntIsFlagSet(SyntDesc):
|
||||||
desc = [["set"]]
|
desc = [["set"]]
|
||||||
|
@ -422,10 +426,9 @@ class Fail(TPrs):
|
||||||
edit a script while the game is running and see the effect of their changes immediately; this suggests that failures
|
edit a script while the game is running and see the effect of their changes immediately; this suggests that failures
|
||||||
should be logged and the script should continue to run.
|
should be logged and the script should continue to run.
|
||||||
"""
|
"""
|
||||||
def InitPersistent(self, vm, stFailure, synt):
|
def InitPersistent(self, stFailure, synt):
|
||||||
self.stFailure = stFailure
|
self.stFailure = stFailure
|
||||||
self.synt = synt
|
self.synt = synt
|
||||||
vm.Log(self)
|
|
||||||
|
|
||||||
# projection cursor
|
# projection cursor
|
||||||
class Pcur(object):
|
class Pcur(object):
|
||||||
|
@ -880,7 +883,7 @@ class Pov(TokenClient):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
key = self.client.evKey.receive(self)
|
key = self.client.EvKey(self.game).receive(self)
|
||||||
if key == ansi.K_PGDN:
|
if key == ansi.K_PGDN:
|
||||||
self.block.Eval(Vm(self.defs))
|
self.block.Eval(Vm(self.defs))
|
||||||
psel = self.pselstate.PselByClient(self.client)
|
psel = self.pselstate.PselByClient(self.client)
|
||||||
|
|
20
telnet.py
20
telnet.py
|
@ -41,8 +41,6 @@ class AnsiTelnet(protocol.Protocol):
|
||||||
print "created"
|
print "created"
|
||||||
self.ast = None
|
self.ast = None
|
||||||
self.client = client
|
self.client = client
|
||||||
self.evKey = None
|
|
||||||
self.evArrow = None
|
|
||||||
self.Refresh()
|
self.Refresh()
|
||||||
|
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
|
@ -122,27 +120,21 @@ class AnsiTelnet(protocol.Protocol):
|
||||||
print "negotiated!"
|
print "negotiated!"
|
||||||
self.transport.write(ansi.esc + "2J") #cls
|
self.transport.write(ansi.esc + "2J") #cls
|
||||||
self.transport.write(ansi.esc + "=25l") #hide the cursor
|
self.transport.write(ansi.esc + "=25l") #hide the cursor
|
||||||
self.client.dgJoinGame = self.CreateEvents
|
|
||||||
self.client.addDgQuit(self.transport.loseConnection)
|
self.client.addDgQuit(self.transport.loseConnection)
|
||||||
self.client.go(self.factory.fnRun, self)
|
self.client.go(self.factory.fnRun, self)
|
||||||
|
|
||||||
def RcvText(self, text):
|
def RcvText(self, text):
|
||||||
if self.client.evKey:
|
for ch in text:
|
||||||
for ch in text:
|
self.client.KeyPressed(ch)
|
||||||
self.client.evKey.fire(ch)
|
|
||||||
|
|
||||||
mpcode_key = {"A": ansi.K_UP, "B": ansi.K_DOWN, "C": ansi.K_RIGHT, "D": ansi.K_LEFT,
|
mpcode_key = {"A": ansi.K_UP, "B": ansi.K_DOWN, "C": ansi.K_RIGHT, "D": ansi.K_LEFT,
|
||||||
"K": ansi.K_END, "H": ansi.K_HOME, "V": ansi.K_PGUP, "U": ansi.K_PGDN }
|
"K": ansi.K_END, "H": ansi.K_HOME, "V": ansi.K_PGUP, "U": ansi.K_PGDN }
|
||||||
|
|
||||||
def RcvAnsi(self, code, rgarg):
|
def RcvAnsi(self, code, rgarg):
|
||||||
if self.client.evKey:
|
if code in self.mpcode_key:
|
||||||
if code in self.mpcode_key:
|
self.client.KeyPressed(self.mpcode_key[code])
|
||||||
self.client.evKey.fire(self.mpcode_key[code])
|
else:
|
||||||
else:
|
print "unrecognized code", code, rgarg
|
||||||
print "unrecognized code", code, rgarg
|
|
||||||
|
|
||||||
def CreateEvents(self, client, game):
|
|
||||||
client.evKey = engine.Event(game)
|
|
||||||
|
|
||||||
def Draw(self, ascr):
|
def Draw(self, ascr):
|
||||||
self.transport.write(self.ascr.AstDiff(ascr))
|
self.transport.write(self.ascr.AstDiff(ascr))
|
||||||
|
|
58
tpers.py
58
tpers.py
|
@ -319,3 +319,61 @@ def _unpickle_method(func_name, obj, cls):
|
||||||
import copy_reg
|
import copy_reg
|
||||||
import types
|
import types
|
||||||
copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)
|
copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)
|
||||||
|
|
||||||
|
def hashable(v):
|
||||||
|
try:
|
||||||
|
hash(v)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
class StaticIndex(TPrs):
|
||||||
|
def InitPersistent(self, fIncludeTemp = False):
|
||||||
|
self.mpv_a_rge = {}
|
||||||
|
self.rgv = set()
|
||||||
|
self.fIncludeTemp = fIncludeTemp
|
||||||
|
|
||||||
|
def FPersist(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def AddEAV(self, e, a, v):
|
||||||
|
if v not in self.mpv_a_rge:
|
||||||
|
self.mpv_a_rge[v] = {}
|
||||||
|
a_rge = self.mpv_a_rge[v]
|
||||||
|
if a not in a_rge:
|
||||||
|
a_rge[a] = []
|
||||||
|
a_rge[a].append(e)
|
||||||
|
|
||||||
|
def Populate(self, v, a = (), e = None):
|
||||||
|
if hashable(v):
|
||||||
|
if e:
|
||||||
|
self.AddEAV(e, a, v)
|
||||||
|
if v in self.rgv:
|
||||||
|
return self
|
||||||
|
self.rgv.add(v)
|
||||||
|
if isinstance(v, TPrs):
|
||||||
|
attrs = set(v._persistent.keys())
|
||||||
|
if self.fIncludeTemp:
|
||||||
|
attrs = attrs.union(set(v.__dict__.keys()))
|
||||||
|
for attr in attrs:
|
||||||
|
child = getattr(v, attr)
|
||||||
|
self.Populate(child, (attr,), v)
|
||||||
|
elif isinstance(v, clsList) or isinstance(v, clsTuple):
|
||||||
|
for ichild, child in enumerate(v):
|
||||||
|
self.Populate(child, a + (ichild,), e)
|
||||||
|
elif isinstance(v, clsSet):
|
||||||
|
for child in v:
|
||||||
|
self.Populate(child, a, e)
|
||||||
|
elif isinstance(v, clsDict):
|
||||||
|
for k, child in v.items():
|
||||||
|
self.Populate(child, a + (k,), e)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def Rgclass(self):
|
||||||
|
return set([v.__class__ for v in self.rgv])
|
||||||
|
|
||||||
|
def RgvWithClass(self, cls):
|
||||||
|
return [v for v in self.rgv if isinstance(v, cls)]
|
||||||
|
|
||||||
|
def Rgref(self, v):
|
||||||
|
return self.mpv_a_rge.get(v)
|
||||||
|
|
198
whiteboard.py
198
whiteboard.py
|
@ -20,6 +20,7 @@ from basetoken import *
|
||||||
from tpers import *
|
from tpers import *
|
||||||
from datetime import *
|
from datetime import *
|
||||||
from util import *
|
from util import *
|
||||||
|
from scripting import Botdef, Flagdef, Defs, PselState, Pov
|
||||||
import telnet
|
import telnet
|
||||||
import time
|
import time
|
||||||
import login
|
import login
|
||||||
|
@ -129,8 +130,13 @@ class Drawing(Ownable):
|
||||||
def SetTimestamp(self):
|
def SetTimestamp(self):
|
||||||
self.dtLastModified = datetime.now()
|
self.dtLastModified = datetime.now()
|
||||||
|
|
||||||
@Version(3)
|
@Version(4)
|
||||||
class Board(Drawing):
|
class Board(Drawing):
|
||||||
|
def InitPersistent(self, owner, stName, user, rglayer=None, dtLastModified=None):
|
||||||
|
super(Board, self).InitPersistent(owner, stName, user, rglayer=rglayer, dtLastModified=dtLastModified)
|
||||||
|
self.defs = Defs()
|
||||||
|
self.layerObj = self.rglayer[0]
|
||||||
|
|
||||||
def StType(self):
|
def StType(self):
|
||||||
return "Board"
|
return "Board"
|
||||||
def W(self): return config.W
|
def W(self): return config.W
|
||||||
|
@ -139,6 +145,10 @@ class Board(Drawing):
|
||||||
def draw(self, ascr):
|
def draw(self, ascr):
|
||||||
for layer in reversed(self.rglayer):
|
for layer in reversed(self.rglayer):
|
||||||
ascr.PutAscr(layer.ascr)
|
ascr.PutAscr(layer.ascr)
|
||||||
|
|
||||||
|
def DrawObjectDefs(self, ascr):
|
||||||
|
for botdef in self.defs.rgbotdef:
|
||||||
|
ascr.PutAch(botdef.ach, botdef.x, botdef.y)
|
||||||
|
|
||||||
def Save(self):
|
def Save(self):
|
||||||
fn = config.DIR_ANSI + "/" + "_".join([str(x) for x in time.localtime()])
|
fn = config.DIR_ANSI + "/" + "_".join([str(x) for x in time.localtime()])
|
||||||
|
@ -158,6 +168,9 @@ class Board(Drawing):
|
||||||
self.user = gameWB.user
|
self.user = gameWB.user
|
||||||
if versionOld < 3:
|
if versionOld < 3:
|
||||||
self.chat = Chat()
|
self.chat = Chat()
|
||||||
|
if versionOld < 4:
|
||||||
|
self.defs = Defs()
|
||||||
|
self.layerObj = self.rglayer[0]
|
||||||
|
|
||||||
class Sprite(Drawing):
|
class Sprite(Drawing):
|
||||||
def InitPersistent(self, owner, stName, user, w, h):
|
def InitPersistent(self, owner, stName, user, w, h):
|
||||||
|
@ -225,19 +238,22 @@ class Chat(TPrs):
|
||||||
def InitTransient(self):
|
def InitTransient(self):
|
||||||
TPrs.InitTransient(self)
|
TPrs.InitTransient(self)
|
||||||
self.cchl = 100
|
self.cchl = 100
|
||||||
self.DetachFromGame()
|
self.MakeTransient("game", None)
|
||||||
|
self.MakeTransient("evChat", None)
|
||||||
|
|
||||||
def InitPersistent(self):
|
def InitPersistent(self):
|
||||||
TPrs.InitPersistent(self)
|
TPrs.InitPersistent(self)
|
||||||
self.rgchl = []
|
self.rgchl = []
|
||||||
|
|
||||||
def AttachToGame(self, game):
|
def AttachToGame(self, game):
|
||||||
self.game = game
|
with self.SetTransiently():
|
||||||
self.evChat = Event(game)
|
self.game = game
|
||||||
|
self.evChat = Event(game)
|
||||||
|
|
||||||
def DetachFromGame(self):
|
def DetachFromGame(self):
|
||||||
self.game = None
|
with self.SetTransiently():
|
||||||
self.evChat = None
|
self.game = None
|
||||||
|
self.evChat = None
|
||||||
|
|
||||||
def Add(self, chl):
|
def Add(self, chl):
|
||||||
if len(chl.st) > 0:
|
if len(chl.st) > 0:
|
||||||
|
@ -248,8 +264,10 @@ class Chat(TPrs):
|
||||||
|
|
||||||
def CChl(self):
|
def CChl(self):
|
||||||
return len(self.rgchl)
|
return len(self.rgchl)
|
||||||
|
|
||||||
def CUsers(self):
|
def CUsers(self):
|
||||||
return len(self.game.rgclient)
|
return len(self.game.RgclientConnected())
|
||||||
|
|
||||||
def DrawMsg(self, ascr, x, y, w, h, colBg=ansi.BLACK, ichl=0):
|
def DrawMsg(self, ascr, x, y, w, h, colBg=ansi.BLACK, ichl=0):
|
||||||
yDraw = y + h - 1
|
yDraw = y + h - 1
|
||||||
for chl in self.rgchl[ichl:]:
|
for chl in self.rgchl[ichl:]:
|
||||||
|
@ -274,8 +292,8 @@ class Chat(TPrs):
|
||||||
|
|
||||||
def DrawUsers(self, ascr, x, y, w, h, colBg=ansi.BLACK, iuser=0):
|
def DrawUsers(self, ascr, x, y, w, h, colBg=ansi.BLACK, iuser=0):
|
||||||
yDraw = y
|
yDraw = y
|
||||||
for client in sorted(self.game.rgclient, lambda c1, c2: cmp(c1.Cldg().iclient, c2.Cldg().iclient))[iuser:]:
|
for client in sorted(self.game.RgclientConnected(), lambda c1, c2: cmp(c1.Cldg(self.game).iclient, c2.Cldg(self.game).iclient))[iuser:]:
|
||||||
ascr.PutSt("{0:{1}}".format(str(client.Cldg().iclient) + ") " + client.cld.user, w), x, yDraw, ansi.WHITE, colBg)
|
ascr.PutSt("{0:{1}}".format(str(client.Cldg(self.game).iclient) + ") " + client.cld.user, w), x, yDraw, ansi.WHITE, colBg)
|
||||||
yDraw = yDraw + 1
|
yDraw = yDraw + 1
|
||||||
if yDraw == y + h:
|
if yDraw == y + h:
|
||||||
break
|
break
|
||||||
|
@ -320,19 +338,38 @@ class Cursor(TokenClient):
|
||||||
miQuit = MiButton("Back to Menu", self.client.leaveGame)
|
miQuit = MiButton("Back to Menu", self.client.leaveGame)
|
||||||
self.cf = self.MenuDrawing(miFg, miBg, miChars, miQuit)
|
self.cf = self.MenuDrawing(miFg, miBg, miChars, miQuit)
|
||||||
self.miChat = MiMenu([None, MiChat(self.client, 13, self.game.drawing.chat), MiTypein(self.SendMsg), None, miQuit, None])
|
self.miChat = MiMenu([None, MiChat(self.client, 13, self.game.drawing.chat), MiTypein(self.SendMsg), None, miQuit, None])
|
||||||
self.rgmiLayer = RgmiProjected(self.game.drawing.rglayer, DgProjectMiButton(self.SelectLayer))
|
self.rgmiLayer = RgmiProjected(self.game.drawing.rglayer, DgProjectMiButton(self.SelectLayer, self.StLayerName))
|
||||||
self.miLayers = self.MenuLayers(miQuit)
|
self.miLayers = self.MenuLayers(miQuit)
|
||||||
self.ovPopup = OvPopup(self, self.client, MiTab.MiTabbed(["Drawing", self.cf], [self.StLayerTab(), self.miLayers], ["Chat", self.miChat]))
|
self.ovPopup = OvPopup(self, self.client, MiTab.MiTabbed(["Drawing", self.cf], [self.StLayerTab(), self.miLayers], ["Chat", self.miChat]))
|
||||||
miStatus = MiMenuHoriz([MiStatic("Hit <Tab> for menu"), MiValue(miChars)])
|
miStatus = MiMenuHoriz([MiDgText(self.StStatus), MiValue(miChars)])
|
||||||
miStatus.ListenForNotice(self.miChat)
|
miStatus.ListenForNotice(self.miChat)
|
||||||
self.ovStatus = OvStatic(self, self.client, miStatus, OvStatic.BOTTOM)
|
self.ovStatus = OvStatic(self, self.client, miStatus, OvStatic.BOTTOM)
|
||||||
|
|
||||||
|
def StLayerName(self, layer):
|
||||||
|
return ('[Bot] ' if layer == self.game.drawing.layerObj else '') + layer.StName()
|
||||||
|
|
||||||
|
def StStatus(self):
|
||||||
|
stStatus = "<Tab>: Menu"
|
||||||
|
if self.GetLayer() == self.game.drawing.layerObj:
|
||||||
|
botdef = self.BotdefAtPos(self.pos)
|
||||||
|
if botdef:
|
||||||
|
stStatus += " | <Enter>: Edit bot"
|
||||||
|
elif self.game.drawing.layerObj.ascr.GetAch(self.pos.X(), self.pos.Y()) != ansi.achBlank:
|
||||||
|
stStatus += " | <Enter>: Make bot"
|
||||||
|
return stStatus
|
||||||
|
|
||||||
|
def BotdefAtPos(self, pos):
|
||||||
|
for botdef in self.game.drawing.defs.rgbotdef:
|
||||||
|
if botdef.x == pos.X() and botdef.y == pos.Y():
|
||||||
|
return botdef
|
||||||
|
|
||||||
def MenuDrawing(self, miFg, miBg, miChars, miQuit):
|
def MenuDrawing(self, miFg, miBg, miChars, miQuit):
|
||||||
return MiMenu([None, miFg, miBg, None, miChars, None, MiButton("Save", self.Save), None, miQuit, None])
|
return MiMenu([None, miFg, miBg, None, miChars, None, MiButton("Save", self.Save), None, miQuit, None])
|
||||||
|
|
||||||
def MenuLayers(self, miQuit):
|
def MenuLayers(self, miQuit):
|
||||||
return MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Layer", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown),
|
return MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Layer", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown),
|
||||||
None, MiToggle("Show One"), None, MiStatic("Rename selected layer:"), MiTypein(self.RenameLayer, "LayerName", 80), None, miQuit, None]))
|
None, MiToggle("Show One"), MiButton("Set as bot layer", self.SetBotLayer), None,
|
||||||
|
MiStatic("Rename selected layer:"), MiTypein(self.RenameLayer, "LayerName", 80), None, miQuit, None]))
|
||||||
def StLayerTab(self): return "Layers"
|
def StLayerTab(self): return "Layers"
|
||||||
def Save(self):
|
def Save(self):
|
||||||
self.game.drawing.Save()
|
self.game.drawing.Save()
|
||||||
|
@ -345,7 +382,8 @@ class Cursor(TokenClient):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def GetLayer(self):
|
def GetLayer(self):
|
||||||
return self.ovPopup.GetSelection("layer").Value()
|
selLayer = self.ovPopup.GetSelection("layer")
|
||||||
|
return selLayer.Value().Value() if selLayer else None
|
||||||
|
|
||||||
def NewLayer(self):
|
def NewLayer(self):
|
||||||
ilayer = 1
|
ilayer = 1
|
||||||
|
@ -373,6 +411,9 @@ class Cursor(TokenClient):
|
||||||
self.GetLayer().SetName(st)
|
self.GetLayer().SetName(st)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def SetBotLayer(self):
|
||||||
|
self.game.drawing.layerObj = self.GetLayer()
|
||||||
|
|
||||||
def blinkCursor(self, fBlink):
|
def blinkCursor(self, fBlink):
|
||||||
self.fBlink = fBlink
|
self.fBlink = fBlink
|
||||||
if not fBlink and self.cDontBlink > 0:
|
if not fBlink and self.cDontBlink > 0:
|
||||||
|
@ -391,7 +432,7 @@ class Cursor(TokenClient):
|
||||||
def run(self):
|
def run(self):
|
||||||
with self.game.drawing.chat.evChat.oob(self, self.OnChat):
|
with self.game.drawing.chat.evChat.oob(self, self.OnChat):
|
||||||
while True:
|
while True:
|
||||||
key = self.client.evKey.receive(self)
|
key = self.client.EvKey(self.game).receive(self)
|
||||||
fDontBlink = True
|
fDontBlink = True
|
||||||
if key == ansi.K_LEFT:
|
if key == ansi.K_LEFT:
|
||||||
self.pos.Left()
|
self.pos.Left()
|
||||||
|
@ -419,6 +460,8 @@ class Cursor(TokenClient):
|
||||||
self.Skip(self.pos.Up)
|
self.Skip(self.pos.Up)
|
||||||
elif key == ansi.K_PGDN:
|
elif key == ansi.K_PGDN:
|
||||||
self.Skip(self.pos.Down)
|
self.Skip(self.pos.Down)
|
||||||
|
elif key == ansi.K_NEWLINE or key == ansi.K_RETURN:
|
||||||
|
self.EditBot()
|
||||||
elif ansi.FKeyPrintable(key):
|
elif ansi.FKeyPrintable(key):
|
||||||
if key.isdigit():
|
if key.isdigit():
|
||||||
self.PutWb(chr(self.cf.Value("Characters")[IchFromCh(key)]))
|
self.PutWb(chr(self.cf.Value("Characters")[IchFromCh(key)]))
|
||||||
|
@ -466,6 +509,41 @@ class Cursor(TokenClient):
|
||||||
def FDrawCursor(self):
|
def FDrawCursor(self):
|
||||||
return self.fBlink or self.cDontBlink > 0
|
return self.fBlink or self.cDontBlink > 0
|
||||||
|
|
||||||
|
def EditBot(self):
|
||||||
|
if self.GetLayer() == self.game.drawing.layerObj:
|
||||||
|
botdef = self.BotdefAtPos(self.pos)
|
||||||
|
ach = self.game.drawing.layerObj.ascr.GetAch(self.pos.X(), self.pos.Y())
|
||||||
|
fNewBot = ach != ansi.achBlank if not botdef else False
|
||||||
|
if not fNewBot and not botdef:
|
||||||
|
return
|
||||||
|
if fNewBot:
|
||||||
|
botdef = Botdef('Bot ' + str(len(self.game.drawing.defs.rgbotdef) + 1) + ' (' + ansi.Ach(ach).ch + ')', ach, self.pos.X(), self.pos.Y())
|
||||||
|
|
||||||
|
evDone = Event(self.game)
|
||||||
|
def DgDone(val):
|
||||||
|
return lambda: evDone.fire(val)
|
||||||
|
|
||||||
|
miBotName = MiTypein(None, "BotName", 80)
|
||||||
|
miBotName.SetValue(botdef.stName)
|
||||||
|
miMenu = MiMenu([None,
|
||||||
|
MiStatic("Bot Name"), miBotName, None,
|
||||||
|
MiToggle("Is Player", botdef.fPlayer), None,
|
||||||
|
MiButton("Save", DgDone(True)), MiButton("Cancel", DgDone(False)), None,
|
||||||
|
MiButton("Edit Code (live)", lambda: self.client.joinGame(self.game.GameSyntEdit(botdef.syntOnTouch))), None])
|
||||||
|
|
||||||
|
ov = OvMenu(self, self.client, miMenu, OvMenu.MIDDLE)
|
||||||
|
try:
|
||||||
|
result = evDone.receive(self)
|
||||||
|
finally:
|
||||||
|
ov.die()
|
||||||
|
if result:
|
||||||
|
botdef.stName = miBotName.Value()
|
||||||
|
botdef.fPlayer = miMenu.MiByName("Is Player").Value()
|
||||||
|
if fNewBot:
|
||||||
|
self.game.drawing.defs.rgbotdef.append(botdef)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def draw(self, ascr, client):
|
def draw(self, ascr, client):
|
||||||
if self.FDrawCursor():
|
if self.FDrawCursor():
|
||||||
if client == self.client:
|
if client == self.client:
|
||||||
|
@ -475,7 +553,7 @@ class Cursor(TokenClient):
|
||||||
chCursor = chr(177)
|
chCursor = chr(177)
|
||||||
self.Put(chCursor, ascr, *self.XzYzScreenPic())
|
self.Put(chCursor, ascr, *self.XzYzScreenPic())
|
||||||
elif self.fBlink:
|
elif self.fBlink:
|
||||||
self.Put(str(self.client.Cldg().iclient)[0], ascr, *self.XzYzScreenPic())
|
self.Put(str(self.client.Cldg(self.game).iclient)[0], ascr, *self.XzYzScreenPic())
|
||||||
|
|
||||||
class CursorSprite(Cursor):
|
class CursorSprite(Cursor):
|
||||||
def InitPersistent(self, game, client):
|
def InitPersistent(self, game, client):
|
||||||
|
@ -492,7 +570,9 @@ class CursorSprite(Cursor):
|
||||||
return MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Frame", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown),
|
return MiMenu(Rgseq([None], self.rgmiLayer, [None, MiButton("New Frame", self.NewLayer), MiButton("Move up", self.LayerUp), MiButton("Move down", self.LayerDown),
|
||||||
None, MiStatic("Rename selected frame:"), MiTypein(self.RenameLayer, "LayerName", 80), None, MiButton("Animate", self.Animate), None, miQuit, None]))
|
None, MiStatic("Rename selected frame:"), MiTypein(self.RenameLayer, "LayerName", 80), None, MiButton("Animate", self.Animate), None, miQuit, None]))
|
||||||
|
|
||||||
|
def StStatus(self): return "Hit <Tab> for menu"
|
||||||
def StLayerTab(self): return "Frames"
|
def StLayerTab(self): return "Frames"
|
||||||
|
|
||||||
def NewLayer(self):
|
def NewLayer(self):
|
||||||
stLayer = "Frame " + str(len(self.game.drawing.rglayer) + 1)
|
stLayer = "Frame " + str(len(self.game.drawing.rglayer) + 1)
|
||||||
layer = self.GetLayer()
|
layer = self.GetLayer()
|
||||||
|
@ -521,10 +601,14 @@ class WhiteboardDraw(TokenClient):
|
||||||
|
|
||||||
def draw(self, ascr, client):
|
def draw(self, ascr, client):
|
||||||
if client == self.client:
|
if client == self.client:
|
||||||
|
fDrawObjects = True
|
||||||
if self.owner.miLayers.Value("Show One"):
|
if self.owner.miLayers.Value("Show One"):
|
||||||
ascr.PutAscr(self.owner.GetLayer().ascr)
|
ascr.PutAscr(self.owner.GetLayer().ascr)
|
||||||
|
fDrawObjects = self.owner.GetLayer() == self.owner.layerObj
|
||||||
else:
|
else:
|
||||||
self.game.drawing.draw(ascr)
|
self.game.drawing.draw(ascr)
|
||||||
|
if fDrawObjects:
|
||||||
|
self.game.drawing.DrawObjectDefs(ascr)
|
||||||
|
|
||||||
class SpriteDraw(TokenClient):
|
class SpriteDraw(TokenClient):
|
||||||
def InitPersistent(self, owner, client):
|
def InitPersistent(self, owner, client):
|
||||||
|
@ -671,10 +755,10 @@ class Joiner(LeaveJoinToken):
|
||||||
self.board = self.game.drawing
|
self.board = self.game.drawing
|
||||||
|
|
||||||
def OnJoin(self, client):
|
def OnJoin(self, client):
|
||||||
with client.Cldg().SetTransiently() as cldg:
|
with client.Cldg(self.game).SetTransiently() as cldg:
|
||||||
cldg.iclient = -1
|
cldg.iclient = -1
|
||||||
iclient = 1
|
iclient = 1
|
||||||
rgiclient = [clientT.Cldg().iclient for clientT in self.game.rgclient]
|
rgiclient = [clientT.Cldg(self.game).iclient for clientT in self.game.RgclientConnected()]
|
||||||
while iclient in rgiclient:
|
while iclient in rgiclient:
|
||||||
iclient = iclient + 1
|
iclient = iclient + 1
|
||||||
cldg.iclient = iclient
|
cldg.iclient = iclient
|
||||||
|
@ -813,7 +897,29 @@ class GameLogin(Game):
|
||||||
def GetRgclsTokTrans(self):
|
def GetRgclsTokTrans(self):
|
||||||
return [[AutoJoiner, login.LoginTerm]]
|
return [[AutoJoiner, login.LoginTerm]]
|
||||||
|
|
||||||
@Version(6)
|
class Mpsubgame(TPrs):
|
||||||
|
def InitPersistent(self, game, dgMakeGame):
|
||||||
|
self.game = game
|
||||||
|
self.dgMakeGame = dgMakeGame
|
||||||
|
self.mpkey_subgame = {}
|
||||||
|
|
||||||
|
def SubgameFromKey(self, key):
|
||||||
|
if not (key in self.mpkey_subgame):
|
||||||
|
subgame = self.dgMakeGame(key)
|
||||||
|
subgame.rgdgdie.append(Partial(self.KillSubgame, key))
|
||||||
|
self.mpkey_subgame[key] = subgame
|
||||||
|
return self.mpkey_subgame[key]
|
||||||
|
|
||||||
|
def KillSubgame(self, key):
|
||||||
|
del self.mpkey_subgame[key]
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return key in self.mpkey_subgame
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.mpkey_subgame[key]
|
||||||
|
|
||||||
|
@Version(7)
|
||||||
class GameLobby(Game):
|
class GameLobby(Game):
|
||||||
def InitPersistent(self):
|
def InitPersistent(self):
|
||||||
self.rgproject = []
|
self.rgproject = []
|
||||||
|
@ -821,30 +927,37 @@ class GameLobby(Game):
|
||||||
|
|
||||||
def InitTransient(self):
|
def InitTransient(self):
|
||||||
Game.InitTransient(self)
|
Game.InitTransient(self)
|
||||||
self.mpdrawing_game = {}
|
self.mpdrawing_game = Mpsubgame(self, self.MakeGameFromDrawing)
|
||||||
|
self.mpdrawingsynt_game = Mpsubgame(self, self.MakeGameSyntEdit)
|
||||||
|
|
||||||
def GetRgclsTokTrans(self):
|
def GetRgclsTokTrans(self):
|
||||||
return [[AutoJoiner, Lobby]]
|
return [[AutoJoiner, Lobby]]
|
||||||
|
|
||||||
def GameFromDrawing(self, drawing):
|
def GameFromDrawing(self, drawing):
|
||||||
if not (drawing in self.mpdrawing_game):
|
return self.mpdrawing_game.SubgameFromKey(drawing)
|
||||||
if drawing.StType() == "Board":
|
|
||||||
game = GameWB(self, drawing)
|
|
||||||
elif drawing.StType() == "Sprite":
|
|
||||||
game = GameSprEdit(self, drawing)
|
|
||||||
else:
|
|
||||||
assert False, "Lobby not prepared to deal with drawing of type " + drawing.StType()
|
|
||||||
game.rgdgdie.append(Partial(self.KillBoard, drawing))
|
|
||||||
self.mpdrawing_game[drawing] = game
|
|
||||||
return game
|
|
||||||
return self.mpdrawing_game[drawing]
|
|
||||||
|
|
||||||
|
def MakeGameFromDrawing(self, drawing):
|
||||||
|
if drawing.StType() == "Board":
|
||||||
|
return GameWB(self, drawing)
|
||||||
|
elif drawing.StType() == "Sprite":
|
||||||
|
return GameSprEdit(self, drawing)
|
||||||
|
else:
|
||||||
|
assert False, "Lobby not prepared to deal with drawing of type " + drawing.StType()
|
||||||
|
|
||||||
|
# we accidentally persisted references to this method that are immediately removed by Chat.InitTransient()
|
||||||
def KillBoard(self, drawing):
|
def KillBoard(self, drawing):
|
||||||
del self.mpdrawing_game[drawing]
|
pass
|
||||||
|
|
||||||
|
def GameFromSynt(self, drawing, synt):
|
||||||
|
return self.mpdrawingsynt_game.SubgameFromKey((drawing, synt))
|
||||||
|
|
||||||
|
def MakeGameSyntEdit(self, drawing_synt):
|
||||||
|
drawing, synt = drawing_synt
|
||||||
|
return GameSyntEdit(drawing, synt)
|
||||||
|
|
||||||
def CclientDrawing(self, drawing):
|
def CclientDrawing(self, drawing):
|
||||||
if drawing in self.mpdrawing_game:
|
if drawing in self.mpdrawing_game:
|
||||||
return len(self.mpdrawing_game[drawing].rgclient)
|
return len(self.mpdrawing_game[drawing].RgclientConnected())
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def StNameProject(self, project):
|
def StNameProject(self, project):
|
||||||
|
@ -883,7 +996,12 @@ class GameLobby(Game):
|
||||||
project.rgdrawing.append(board)
|
project.rgdrawing.append(board)
|
||||||
del self.rgboard
|
del self.rgboard
|
||||||
self.rgproject = [project]
|
self.rgproject = [project]
|
||||||
self.mpuser_cldg = {} # ugh, upgrading parent classes is broken in our model :(
|
|
||||||
|
# ugh, upgrading parent classes is broken in our model :(
|
||||||
|
if versionOld < 6:
|
||||||
|
Game.UpgradeFrom(self, 1)
|
||||||
|
elif versionOld < 7:
|
||||||
|
Game.UpgradeFrom(self, 2)
|
||||||
|
|
||||||
class GameWB(Game):
|
class GameWB(Game):
|
||||||
def InitPersistent(self, gameLobby, board):
|
def InitPersistent(self, gameLobby, board):
|
||||||
|
@ -905,6 +1023,18 @@ class GameWB(Game):
|
||||||
|
|
||||||
def GetRgtagDraw(self):
|
def GetRgtagDraw(self):
|
||||||
return ["background", "solid", "cursor", "menu", "msgscroller"]
|
return ["background", "solid", "cursor", "menu", "msgscroller"]
|
||||||
|
|
||||||
|
def GameSyntEdit(self, synt):
|
||||||
|
return self.gameLobby.GameFromSynt(self.drawing, synt)
|
||||||
|
|
||||||
|
class GameSyntEdit(Game):
|
||||||
|
def InitPersistent(self, board, synt):
|
||||||
|
Game.InitPersistent(self)
|
||||||
|
self.board = board
|
||||||
|
self.synt = synt
|
||||||
|
|
||||||
|
def GetRgclsTokTrans(self):
|
||||||
|
return [[PselState, self.board.defs, self.synt], [AutoJoiner, [Pov, self.board.defs, self.synt]]]
|
||||||
|
|
||||||
class GameSprEdit(GameWB):
|
class GameSprEdit(GameWB):
|
||||||
def ClsCursor(self):
|
def ClsCursor(self):
|
||||||
|
|
Loading…
Reference in a new issue