galtack_loadable.py: back to MIT license (thanks Phil)
[galtack.git] / galtack / net_client_old.py
blob9e1b419eea387a23a35e9c96d1e644e27718a49d
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4 Galcon networking - old client protocol implementation.
6 This file is only used for reference and can safely be deleted.
7 """
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.
34 ### FR OLD CODE
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
42 self.digest = digest
43 self.name = name
44 self.client = client
45 self.address = address
46 self.port = port
47 # self.received = []
48 self.awaiting_ack = dict()
49 self.id = 3
50 self.players = dict()
51 self.game = False
52 self.universe = None
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")])
62 def resend(self, id):
63 cmd, timer = self.awaiting_ack[int(id)]
64 self.send_command(cmd)
66 def send_commands(self, cmds):
67 if not cmds:
68 return
69 # print "PRESEND: %s" % (cmds,)
70 id_cmds = []
71 for cmd in cmds:
73 if cmd[0] not in self.awaiting_ack:
74 self.id += 1
75 cmd = (self.id,) + cmd
76 else:
77 self.awaiting_ack.pop(cmd[0])
79 if cmd[1] == 1:
80 d = reactor.callLater(1, self.resend, cmd[0])
81 self.awaiting_ack[cmd[0]] = cmd, d
83 id_cmds.append(cmd)
84 cmds = id_cmds
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 ])
100 for cmd in cmds:
101 # if cmd[0] in self.received:
102 # continue
103 # self.received.append(cmd[0])
104 cmd[2] = cmd[2].replace("[", "_").replace("]", "_")
105 rest = ()
106 if len(cmd) == 4:
107 rest = cmd[3].split('\t')
108 f = getattr(self, "recv_%s" % cmd[2], self.default)
109 if f == self.default:
110 f(cmd[2], rest)
111 else:
112 f(*rest)
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):
126 # print "ACK: %"
127 cmd, timer = self.awaiting_ack.pop(int(id), (None, None))
128 if timer:
129 timer.cancel()
132 def recv_message(self, sender, msg):
133 self.client.galcon_recv_message(self.server_name, sender, msg)
135 def recv_players(self, *players):
136 if self.players:
137 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)
157 def recv_stop(self):
158 self.game = False
159 self.players_details = None
160 self.universe = None
161 self.client.galcon_recv_stop(self.server_name)
163 def recv_start(self, players, time, universe):
164 self.game = True
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):
182 if is_delta:
183 type = 'planet'
184 junk, rest = line.split('\t', 1)
185 else:
186 type, rest = line.split('\t', 1)
188 if type == 'user':
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)
196 if is_delta:
197 if not rest.strip():
198 continue
199 id = str(i+1)
200 p = self.universe['planets'][id]
201 x,y,prod = p['x'], p['y'], p['prod']
202 if not owner_id:
203 owner_id = p['owner_id']
205 delta['planets'][id] = {
206 'id': id,
207 'x': x,
208 'y': y,
209 'owner_id': owner_id,
210 'prod': prod,
211 'troops': troops
213 return delta
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