2 # -*- coding: utf-8 -*-
4 GalTacK networking - client-side universe bookkeeping.
6 # Copyright (C) 2007 Felix Rabe <public@felixrabe.textdriven.com>
7 # Copyright (C) 2007 Michael Carter
9 # Permission is hereby granted, free of charge, to any person obtaining a
10 # copy of this software and associated documentation files (the
11 # "Software"), to deal in the Software without restriction, including
12 # without limitation the rights to use, copy, modify, merge, publish,
13 # distribute, sublicense, and/or sell copies of the Software, and to permit
14 # persons to whom the Software is furnished to do so, subject to the
15 # following conditions:
17 # The above copyright notice and this permission notice shall be included
18 # in all copies or substantial portions of the Software.
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
25 # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
26 # THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 # Recommended line length or text width: 75 characters.
33 from galtack
.net_client_base
import *
36 class GaltackClientPlayerTrackerMixin(GaltackClientBackCallerMixin
):
38 GaltackClient that keeps track of players.
41 def __init__(self
, *a
, **kw
):
42 super(GaltackClientPlayerTrackerMixin
, self
).__init
__(*a
, **kw
)
43 self
.player_info_dict
= {}
44 self
.player_ingame_info_dict
= {}
45 self
.register_command_callback("players", self
.__cmd
_players
)
46 self
.register_command_callback("start", self
.__cmd
_start
)
47 self
.register_command_callback("stop", self
.__cmd
_stop
)
49 def __cmd_players(self
, command
):
50 recv_players
= command
[3:]
51 self
.player_info_dict
= {}
52 for player
in recv_players
:
54 self
.player_info_dict
[s
[0]] = PlayerPlayersInfo(*s
)
56 def __cmd_start(self
, command
):
57 self
.player_ingame_info_dict
= {}
58 for player
in command
[3].split(';'):
60 self
.player_ingame_info_dict
[s
[0]] = PlayerStartInfo(*s
)
62 def __cmd_stop(self
, command
):
63 self
.player_ingame_info_dict
= {}
66 class GaltackClientGameTrackerMixin(GaltackClientBackCallerMixin
):
68 GaltackClient that keeps track of the game state (running or not).
71 def __init__(self
, *a
, **kw
):
72 super(GaltackClientGameTrackerMixin
, self
).__init
__(*a
, **kw
)
73 self
.game_running
= False
74 self
.register_command_callback("start", self
.__cmd
_start
)
75 self
.register_command_callback("stop", self
.__cmd
_stop
)
77 def __cmd_start(self
, command
):
78 self
.game_running
= True
80 def __cmd_stop(self
, command
):
81 self
.game_running
= False
84 class UniverseB64Data(object):
86 Core data structure representing the universe data encoded in Base64,
97 def __init__(self
, b64string
= None):
99 if b64string
is not None:
100 self
._raw
_data
= self
.__decode
(b64string
)
102 for line
in (li
.split("\t") for li
in self
._raw
_data
.split("\n")):
103 if line
[0] == "planet":
104 self
.planets
.append(PlanetB64Info(*line
[1:]))
106 if line
[0] == "user":
107 self
.users
.append(PlayerB64Info(*line
[1:]))
109 if line
[0] == "options":
110 self
.options
= OptionB64Info(*line
[1:])
112 if line
[0] == "version":
113 self
.version
= int(line
[1])
115 if len(line
) == 1 and line
[0] == "":
117 raise Exception, "unrecognized format"
119 def _reset_stuff(self
):
121 self
._version
_updated
= False
128 d
= UniverseB64Data()
129 d
._raw
_data
= copy
.copy(self
._raw
_data
)
130 d
._version
_updated
= copy
.copy(self
._version
_updated
)
131 d
.version
= copy
.copy(self
.version
)
132 d
.options
= copy
.copy(self
.options
)
133 d
.users
= map(copy
.copy
, self
.users
)
134 d
.planets
= map(copy
.copy
, self
.planets
)
137 def update(self
, b64string
):
138 self
._raw
_data
= self
.__decode
(b64string
)
140 for line
in (li
.split("\t") for li
in self
._raw
_data
.split("\n")):
141 if len(line
) == self
.LINE_LEN
["planet"]:
142 p
= self
.planets
[planet_index
]
143 for i
, field
in enumerate(line
[1:]):
144 if not field
: continue
149 raise Exception, "unrecognized format %r" % line
152 def __decode(b64string
):
153 return zlib
.decompress(base64
.b64decode(b64string
))
156 class GaltackClientUniverseTrackerMixin(GaltackClientBackCallerMixin
):
158 GaltackClient that keeps its idea of the GalTacK universe up-to-date.
161 def __init__(self
, *a
, **kw
):
162 super(GaltackClientUniverseTrackerMixin
, self
).__init
__(*a
, **kw
)
164 self
.register_command_callback("start", self
.__cmd
_start
)
165 self
.register_command_callback("delta", self
.__cmd
_delta
)
166 self
.register_command_callback("stop", self
.__cmd
_stop
)
170 return zlib
.decompress(base64
.b64decode(data
))
172 def __cmd_start(self
, command
):
173 if len(command
) < 4: return None
174 self
.players_start
= [l
.split(",") for l
in command
[3].split(";")]
175 if len(command
) < 6: return None
176 self
.u64data
= UniverseB64Data(command
[5])
179 def __cmd_delta(self
, command
):
180 if not hasattr(self
, "u64data"):
181 print "whoops, no u64data"
183 self
.u64data
.update(command
[3])
185 def __cmd_stop(self
, command
):