2 # -*- coding: utf-8 -*-
4 Galcon networking - old client protocol implementation.
6 This file is only used for reference and can safely be deleted.
8 # Copyright (C) 2007 Felix Rabe <public@felixrabe.textdriven.com>
9 # Copyright (C) 2007 Michael Carter
11 # Permission is hereby granted, free of charge, to any person obtaining a
12 # copy of this software and associated documentation files (the
13 # "Software"), to deal in the Software without restriction, including
14 # without limitation the rights to use, copy, modify, merge, publish,
15 # distribute, sublicense, and/or sell copies of the Software, and to permit
16 # persons to whom the Software is furnished to do so, subject to the
17 # following conditions:
19 # The above copyright notice and this permission notice shall be included
20 # in all copies or substantial portions of the Software.
22 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
27 # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
28 # THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 # Recommended line length or text width: 75 characters.
36 class GalconUDPProtocol(DatagramProtocol
):
37 header
= "[HEADER]\tpasswd\t%s\n[HEADER]\tsecret\t%s\n[HEADER]\tname\t%s\n"
38 def __init__(self
, client
, address
, port
, server_name
, digest
, server_password
, name
, user_password
):
39 self
.server_name
= server_name
40 self
.server_password
= server_password
41 self
.user_password
= user_password
45 self
.address
= address
48 self
.awaiting_ack
= dict()
53 self
.players_details
= None
55 def decode(self
, data
):
56 return zlib
.decompress(base64
.decodestring(data
))
58 def startProtocol(self
):
59 self
.transport
.connect(self
.address
, self
.port
)
60 self
.send_commands([(1, "[RESET]"), (1, "[RESET]"), (1, "version", "0.18.0")])
63 cmd
, timer
= self
.awaiting_ack
[int(id)]
64 self
.send_command(cmd
)
66 def send_commands(self
, cmds
):
69 # print "PRESEND: %s" % (cmds,)
73 if cmd
[0] not in self
.awaiting_ack
:
75 cmd
= (self
.id,) + cmd
77 self
.awaiting_ack
.pop(cmd
[0])
80 d
= reactor
.callLater(1, self
.resend
, cmd
[0])
81 self
.awaiting_ack
[cmd
[0]] = cmd
, d
85 packet
= self
.header
% (self
.server_password
, self
.digest
, self
.name
) + '\n'.join(['\t'.join([str(i
) for i
in cmd
]) for cmd
in cmds
]) + '\n'
86 self
.transport
.write(packet
)
87 # print "SEND: %s" % packet.replace("\n", "\\n").replace("\t", "\\t")
89 def send_command(self
, cmd
):
90 self
.send_commands([cmd
])
92 def datagramReceived(self
, datagram
, host
):
93 # print "RECV: %s" % datagram
94 cmds
= [ line
.split('\t', 3) for line
in datagram
.split('\n') ]
95 cmds
= [ i
for i
in cmds
if len(i
) > 1 ]
96 # print "RECV: %s" % (cmds,)
97 to_ack
= [ cmd
[0] for cmd
in cmds
if cmd
[1] == '1' ]
98 self
.send_commands([(0, "[ACK]", id) for id in to_ack
])
101 # if cmd[0] in self.received:
103 # self.received.append(cmd[0])
104 cmd
[2] = cmd
[2].replace("[", "_").replace("]", "_")
107 rest
= cmd
[3].split('\t')
108 f
= getattr(self
, "recv_%s" % cmd
[2], self
.default
)
109 if f
== self
.default
:
114 def default(self
, cmd
, *data
):
115 print "DEFAULT HANDLER: COMMAND [%s]: %s" % (cmd
, data
,)
117 def recv_version(self
, data
):
118 # print "GOT VERSION"
119 self
.send_command((1, "login"))
121 def recv_topic(self
, topic
):
122 # print "TOPIC IS %s" % topic
123 self
.client
.galcon_recv_topic(self
.server_name
, topic
)
125 def recv__ACK_(self
, id):
127 cmd
, timer
= self
.awaiting_ack
.pop(int(id), (None, None))
132 def recv_message(self
, sender
, msg
):
133 self
.client
.galcon_recv_message(self
.server_name
, sender
, msg
)
135 def recv_players(self
, *players
):
138 for player
in players
:
139 num
, name
, junk1
, junk2
, state
, junk3
, junk4
, color
= player
.split(',')
140 self
.players
[name
] = (name
, state
, color
)
141 self
.client
.galcon_recv_players(self
.server_name
, players
)
143 def recv__PING_(self
):
144 self
.client
.galcon_recv_ping(self
.server_name
)
146 def recv__CLOSE_(self
):
147 self
.client
.galcon_recv_close(self
.server_name
)
150 def recv_mfleet(self
, *args
):
151 self
.client
.galcon_recv_mfleet(self
.server_name
, *args
)
153 def recv_redirect(self
, *args
):
154 self
.client
.galcon_recv_redirect(self
.server_name
, *args
)
159 self
.players_details
= None
161 self
.client
.galcon_recv_stop(self
.server_name
)
163 def recv_start(self
, players
, time
, universe
):
165 self
.players_details
= {}
166 self
.universe
= { 'players': {}, 'planets': {}, 'options': None }
167 for player
in players
.split(';'):
168 num
, name
, junk
, color
= player
.split(',')
169 self
.players_details
[num
] = name
, num
, color
171 universe_data
= self
.decode(universe
)
172 lines
= universe_data
.split('\n')
173 self
.universe
['options'] = lines
[1].split('\t')
174 delta
= self
.parse_state(lines
[2:])
175 self
.universe
['players'].update(delta
['players'])
176 self
.universe
['planets'].update(delta
['planets'])
177 self
.client
.galcon_recv_start(self
.server_name
, self
.universe
)
179 def parse_state(self
, state_lines
, is_delta
=False):
180 delta
= {'players': {}, 'planets': {} }
181 for i
, line
in enumerate(state_lines
):
184 junk
, rest
= line
.split('\t', 1)
186 type, rest
= line
.split('\t', 1)
189 id, rest
= rest
.split('\t', 1)
190 delta
['players'][id] = {
191 'name': self
.players_details
[id][0],
192 'id': self
.players_details
[id][1],
193 'color': self
.players_details
[id][2], }
194 elif type == 'planet':
195 id, x
, y
, owner_id
, prod
, troops
, junk
= rest
.split('\t', 6)
200 p
= self
.universe
['planets'][id]
201 x
,y
,prod
= p
['x'], p
['y'], p
['prod']
203 owner_id
= p
['owner_id']
205 delta
['planets'][id] = {
209 'owner_id': owner_id
,
215 def recv_delta(self
, delta
):
216 universe_delta
= self
.decode(delta
)
217 planets
= universe_delta
.split('\n')[-len(self
.universe
['planets']):]
218 delta
= self
.parse_state(planets
, True)
219 self
.universe
['planets'].update(delta
['planets'])
220 self
.client
.galcon_recv_delta(self
.server_name
, self
.universe
)
222 def recv_options(self
, option_string
):
223 print "option string: %r" % option_string