Skip to content

Commit

Permalink
LinkLists now correctly serialize.
Browse files Browse the repository at this point in the history
  • Loading branch information
timo committed May 21, 2009
1 parent 14bedb4 commit 22ac33a
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 29 deletions.
56 changes: 42 additions & 14 deletions lib/gamestate.py
Expand Up @@ -25,6 +25,8 @@ def __init__(self, other):
global serializeKnowledgeBase
if type(other) in serializeKnowledgeBase:
self.knowndata = serializeKnowledgeBase[type(other)]
if other.typename not in typeKnowledgeBase:
typeKnowledgeBase[other.typename] = type(other)
self.so = other

def __enter__(self):
Expand All @@ -44,7 +46,7 @@ def __exit__(self, a, b, c):
"statevars_format": self.so.statevars_format,
"tuples": self.so.tuples,
"links": self.so.links,
"len": struct.calcsize(self.so.statevars_format}
"len": struct.calcsize(self.so.statevars_format)}
serializeKnowledgeBase[type(self.so)] = d

# using this object with the "with" statement, the type of the included vars
Expand Down Expand Up @@ -121,10 +123,11 @@ def serialize(self):

def getSerializeType(self, dataFragment):
type, data = dataFragment[:2], dataFragment[2:]
print `dataFragment`, `type`, `data`
if type in typeKnowledgeBase:
obj = typeKnowledgeBase[type]()
obj = typeKnowledgeBase[type]
else:
print "got unknown type:", `type`
print "got unknown type:", `type`, `typeKnowledgeBase`

return obj

Expand All @@ -147,20 +150,25 @@ def deserialize(self, data):
odata = data
self.clock, data = struct.unpack("!i", data[:4])[0], data [4:]
while len(data) > 0:
print "string is:", `data`
obj = self.getSerializeType(data)
data = data[2:]

# cut the next N bytes out of the data.
if isinstance(obj, LinkList):
if obj == LinkList:
# the first integer of the thingie is the number of items in the list,
# so we add 4 bytes for the first integer and 4 for each following one.
objlen = struct.unpack("!2i", data[:8])[1] * 4 + 4
print struct.unpack("!2i", data[2:10])
objlen = struct.unpack("!2i", data[2:10])[1] * 4 + 8
else:
objlen = self.getSerializedLen(data)
data = data[2:]
objdat, data = data[:objlen], data[objlen:]

obj = obj()

obj.bind(self)
try:
print "deserializing a", `obj`, "from", `objdat`
obj.deserialize(objdat)
except:
print "could not deserialize", `odata`, "- chunk:", `objdat`
Expand Down Expand Up @@ -204,6 +212,8 @@ def control(self, commands):
for id, cmd in commands:
self.getById(id).command(cmd)

def __repr__(self):
return "<GameState at clock %d containing: %s>" % (self.clock, `self.objects`)

# the base class for a State Object, that also implements the serialization
# black magic.
Expand Down Expand Up @@ -399,7 +409,7 @@ def __repr__(self):

class LinkList(StateObject):
typename = "ll"
def __init__(self, statedata):
def __init__(self, statedata = None):
self.links = []
self.work = []
self.state = None
Expand All @@ -409,22 +419,40 @@ def __init__(self, statedata):
self.deserialize(statedata)

def serialize(self):
pass
data = struct.pack("!2i", self.id, len(self.links))
data += struct.pack(*(["!" + str(len(self.links)) + "i"] + [link.id for link in self.links]))
return data

def deserialize(self, data):
self.id, amount = struct.unpack("!2i", data[:8])
data = data[8:]
del self.links[:]
while data:
chunk, data = data[:4], data[4:]
self.work.append(lambda: self.links.append(Link(self.state.getById(struct.unpack("!i", chunk)))))

if self.state:
for wo in self.work:
wo()
self.work = []
print "adding", `chunk`
self.work.append(lambda: self.links.append(Link(self.state.getById(struct.unpack("!i", chunk)[0]))))

def pre_serialize(self): pass
def post_deserialize(self): pass

def assureLink(self, v):
if isinstance(v, Link):
return v
else:
return Link(v)

def __setitem__(self, x, v):
self.links[x] = self.assureLink(v)

def __getitem__(self, x): return self.links[x]
def __delitem__(self, x): del self.links[x]
def append(self, v): self.links.append(self.assureLink(v))

def __repr__(self):
return "<LinkList of %s>" % (`self.links`)

typeKnowledgeBase["ll"] = LinkList

# the StateHistory object saves a backlog of GameState objects in order to
# interpret input data at the time it happened, even if received with a
# latency. this allows for fair treatment of all players, except for cheaters,
Expand Down
15 changes: 5 additions & 10 deletions lib/stateobjects.py
@@ -1,5 +1,5 @@
from __future__ import with_statement
from gamestate import StateObject, stateVars, prescribedType, Link, typeKnowledgeBase
from gamestate import StateObject, stateVars, prescribedType, Link
from stuffdb import itemDb

class PlayerState(StateObject):
Expand All @@ -13,15 +13,15 @@ def __init__(self, data = None):
self.maxHealth = 20
self.magic = 10.0
self.maxMagic = 10
self.item = Link()
self.items = Link()
with prescribedType(self, "b"):
self.team = 0

if data:
self.deserialize(data)

def __repr__(self):
return "<PlayerState H%f/%d M%f/%d holding %s>" % (self.health, self.maxHealth, self.magic, self.maxMagic, self.item.__repr__())
return "<PlayerState H%f/%d M%f/%d holding %s>" % (self.health, self.maxHealth, self.magic, self.maxMagic, `self.items`)

def tick(self, dt):
pass
Expand All @@ -32,8 +32,6 @@ def collide(self, other, vec):
def command(self, cmd):
pass

typeKnowledgeBase["pc"] = PlayerState

class ItemState(StateObject):
typename = "it"
def __init__(self, statedata = None):
Expand All @@ -49,9 +47,8 @@ def __init__(self, statedata = None):
self.translateSerializedData()

def translateSerializedData(self):
itemDb.initItem(self)

typeKnowledgeBase["it"] = ItemState
pass
#itemDb.initItem(self)

class IntrinsicState(StateObject):
typename = "in"
Expand All @@ -70,5 +67,3 @@ def tick(self, dt):
self.lifetimeLeft -= dt
if self.lifetimeLeft < 0:
self.die = True

typeKnowledgeBase["in"] = IntrinsicState
15 changes: 10 additions & 5 deletions lib/stuffdb.py
Expand Up @@ -12,15 +12,20 @@ def initItem(self, obj):
itemDb = objectdb()

class Item(object):
drink = None
equip = None
meleeDamage = 1
def assimilate(self, other):
other.melee = self.melee
other.thrown = self.thrown
other.thrownDistance =
other.drink = self.drink
other.equip = self.equip

def melee(self, user):

dmg = 0
if user.hasIntrinsic(self.meleeIntrinsic):
dmg += 1
return self.meleeDamage + dmg

class Weapon(Item):
def __init__(self):


pass
26 changes: 26 additions & 0 deletions test.py
@@ -0,0 +1,26 @@
from lib.gamestate import *
from lib.stateobjects import *

def run():
gs = GameState()
pl = PlayerState()
gs.spawn(pl)

pli = LinkList()
gs.spawn(pli)
pl.items.proxy_set(pli)

for i in range(5):
it = ItemState()
gs.spawn(it)
pl.items.append(it)

gstr = gs.serialize()
print `gstr`

gs2 = GameState(gstr)

print `gs`
print `gs2`

run()

0 comments on commit 22ac33a

Please sign in to comment.