1 | # |
||
2 | # Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/] |
||
3 | # |
||
4 | # This file is part of Outer Space. |
||
5 | # |
||
6 | # Outer Space is free software; you can redistribute it and/or modify |
||
7 | # it under the terms of the GNU General Public License as published by |
||
8 | # the Free Software Foundation; either version 2 of the License, or |
||
9 | # (at your option) any later version. |
||
10 | # |
||
11 | # Outer Space is distributed in the hope that it will be useful, |
||
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | # GNU General Public License for more details. |
||
15 | # |
||
16 | # You should have received a copy of the GNU General Public License |
||
17 | # along with Outer Space; if not, write to the Free Software |
||
18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||
19 | # |
||
20 | |||
21 | from igeclient import IClient, IClientDB |
||
22 | from ige.ospace import Const |
||
23 | from ige.ospace import Rules |
||
24 | from ige.IDataHolder import IDataHolder |
||
25 | import ige, gdata, osci, math, time |
||
26 | from ige import log |
||
27 | |||
28 | # module globals |
||
29 | cmdProxy = None |
||
30 | db = None |
||
31 | lastUpdate = -1 |
||
32 | server = None |
||
33 | nonexistingObj = {} |
||
34 | options = None |
||
35 | |||
36 | def initialize(aServer, anOptions): |
||
37 | global server, options |
||
38 | server = aServer |
||
39 | options = anOptions |
||
40 | initCmdProxy() |
||
41 | |||
42 | def initCmdProxy(): |
||
43 | global cmdProxy, server |
||
44 | if not cmdProxy: |
||
45 | proxy = None |
||
46 | if gdata.config.proxy.http != None: |
||
47 | proxy = gdata.config.proxy.http |
||
48 | cmdProxy = IClient.IClient(server, proxy, None, None, 'OSClient/%s' % ige.version.versionString) |
||
49 | |||
50 | ## Authentication |
||
51 | |||
52 | def login(gameid, login, password): |
||
53 | cmdProxy.connect() |
||
54 | if cmdProxy.login(gameid, login, password): |
||
55 | return 1 |
||
56 | return 0 |
||
57 | |||
58 | def logout(): |
||
59 | global db, lastUpdate |
||
60 | if cmdProxy and cmdProxy.logged: |
||
61 | cmdProxy.logout() |
||
62 | saveDB() |
||
63 | db = None |
||
64 | lastUpdate = -1 |
||
65 | |||
66 | def saveDB(): |
||
67 | if db: |
||
68 | log.message('OSClient', 'Saving database') |
||
69 | db.save() |
||
70 | |||
71 | ## Updater |
||
72 | |||
73 | def updateDatabase(clearDB = 0): |
||
74 | try: |
||
75 | return updateDatabaseUnsafe(clearDB) |
||
76 | except: |
||
77 | log.warning("Cannot update database") |
||
78 | return updateDatabaseUnsafe(clearDB = 1, force = 1) |
||
79 | |||
80 | def updateDatabaseUnsafe(clearDB = 0, force = 0): |
||
81 | """Update database by fetching data from the server.""" |
||
82 | global lastUpdate, nonexistingObj, db |
||
83 | # get real turn |
||
84 | result = cmdProxy.getIntroInfo(Const.OID_UNIVERSE) |
||
85 | if not db: |
||
86 | db = IClientDB.IClientDB(result.cid, result.turn, options.configDir, cmdProxy.gameID) |
||
87 | if clearDB: |
||
88 | db.clear() |
||
89 | db.turn = result.turn |
||
90 | # |
||
91 | if db.turn <= lastUpdate and not force: |
||
92 | return |
||
93 | log.message('IClient', 'Updating...') |
||
94 | lastUpdate = db.turn |
||
95 | nonexistingObj.clear() |
||
96 | current = 0 |
||
97 | max = 1 |
||
98 | # compute total objects to be fetched |
||
99 | max += 6 # clear map, get messages, ... |
||
100 | current += 1 |
||
101 | # delete selected objects |
||
102 | # reset combatCounters |
||
103 | for objID in db.keys(): |
||
104 | obj = db[objID] |
||
105 | if hasattr(obj, "combatCounter"): |
||
106 | obj.combatCounter = 0 |
||
107 | View Code Duplication | if not hasattr(obj, 'type'): |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
108 | del db[objID] |
||
109 | elif obj.type == Const.T_FLEET: |
||
110 | del db[objID] |
||
111 | elif hasattr(obj, 'owner') and obj.owner == db.playerID \ |
||
112 | and objID != db.playerID: |
||
113 | # delete player's objects |
||
114 | del db[objID] |
||
115 | else: |
||
116 | if hasattr(obj, "scanPwr"): obj.scanPwr = 0 |
||
117 | if hasattr(obj, "scannerPwr"): obj.scannerPwr = 0 |
||
118 | # update player |
||
119 | db[db.playerID] = get(db.playerID) |
||
120 | player = db[db.playerID] |
||
121 | # update from scanner's map |
||
122 | scannerMap = cmdProxy.getScannerMap(db.playerID) |
||
123 | for objID in scannerMap: |
||
124 | db[objID] = scannerMap[objID] |
||
125 | # update player's planets and fleets |
||
126 | for obj in cmdProxy.multiGetInfo(1, player.planets[:] + player.fleets[:]): |
||
127 | db[obj.oid] = obj |
||
128 | # finished |
||
129 | log.message('IClient', 'Update finished.') |
||
130 | |||
131 | ## Basic functions |
||
132 | |||
133 | View Code Duplication | def get(objID, forceUpdate = 0, noUpdate = 0, canBePublic = 1, publicOnly = 0): |
|
0 ignored issues
–
show
|
|||
134 | global nonexistingObj |
||
135 | if nonexistingObj.has_key(objID) and not forceUpdate: |
||
136 | return None |
||
137 | if noUpdate: |
||
138 | return db.get(objID, None) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
139 | if (db.needsUpdate(objID) or forceUpdate) and not publicOnly: |
||
140 | try: |
||
141 | db[objID] = cmdProxy.getInfo(objID) |
||
142 | except ige.SecurityException: |
||
143 | if canBePublic: |
||
144 | db[objID] = cmdProxy.getPublicInfo(objID) |
||
145 | else: |
||
146 | return db.get(objID, None) |
||
147 | except ige.NoSuchObjectException: |
||
148 | if db.has_key(objID): |
||
149 | del db[objID] |
||
150 | nonexistingObj[objID] = None |
||
151 | return None |
||
152 | if (db.needsUpdate(objID) or forceUpdate) and publicOnly: #for when the data you need is never anything but public |
||
153 | try: |
||
154 | db[objID] = cmdProxy.getPublicInfo(objID) |
||
155 | except ige.NoSuchObjectException: |
||
156 | if db.has_key(objID): |
||
157 | del db[objID] |
||
158 | nonexistingObj[objID] = None |
||
159 | return None |
||
160 | return db[objID] |
||
161 | |||
162 | def updateIDs(objIDs): |
||
163 | delete = objIDs[:] |
||
164 | for obj in cmdProxy.multiGetInfo(1, objIDs): |
||
165 | db[obj.oid] = obj |
||
166 | delete.remove(obj.oid) |
||
167 | for objID in delete: |
||
168 | if db.has_key(objID): |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
169 | del db[objID] |
||
170 | |||
171 | View Code Duplication | def getRelationTo(objID): |
|
0 ignored issues
–
show
|
|||
172 | obj = getPlayer() |
||
173 | if obj.oid == objID: |
||
174 | return Const.REL_UNITY |
||
175 | if objID == Const.OID_NONE: |
||
176 | return Const.REL_UNDEF |
||
177 | dipl = obj.diplomacyRels.get(objID, None) |
||
178 | if dipl: |
||
179 | return dipl.relation |
||
180 | else: |
||
181 | return obj.defaultRelation |
||
182 | |||
183 | def getTurn(): |
||
184 | return db.turn |
||
185 | |||
186 | def getFullTechInfo(techID): |
||
187 | player = db[db.playerID] |
||
188 | return Rules.techs[techID] |
||
189 | |||
190 | def getTechInfo(techID): |
||
191 | player = db[db.playerID] |
||
192 | tech = Rules.techs[techID] |
||
193 | # player possess this technology |
||
194 | if player.techs.has_key(techID): |
||
195 | return tech |
||
196 | |||
197 | if tech.fullInfo: |
||
198 | return tech |
||
199 | |||
200 | # player can research this technology |
||
201 | canResearch = 1 |
||
202 | if player.race not in tech.researchRaces: |
||
203 | canResearch = 0 |
||
204 | for tmpTechID, improvement in tech.researchRequires: |
||
205 | if not player.techs.has_key(tmpTechID) or player.techs[tmpTechID] < improvement: |
||
206 | canResearch = 0 |
||
207 | break |
||
208 | for stratRes in tech.researchReqSRes: |
||
209 | if player.stratRes.get(stratRes, 0) < 1: |
||
210 | canResearch = 0 |
||
211 | break |
||
212 | for tmpTechID in player.techs: |
||
213 | if techID in Rules.techs[tmpTechID].researchDisables: |
||
214 | canResearch = 0 |
||
215 | break |
||
216 | if tech.level > player.techLevel: |
||
217 | canResearch = 0 |
||
218 | |||
219 | if canResearch: |
||
220 | result = IDataHolder() |
||
221 | result.partialData = None |
||
222 | for attr in ['name', 'isDiscovery', 'isStructure', |
||
223 | 'isProject', 'isShipEquip', 'isShipHull', 'researchMod', |
||
224 | 'researchTurns', 'textPreRsrch', 'researchRequires', 'subtype', |
||
225 | "researchReqSRes", "researchDisables", "level", "researchRaces"]: |
||
226 | setattr(result, attr, getattr(tech, attr)) |
||
227 | return result |
||
228 | # player should know only basic params about tech |
||
229 | result = IDataHolder() |
||
230 | result.partialData = None |
||
231 | for attr in ["name", "researchRequires", "subtype", "level", "researchRaces"]: |
||
232 | setattr(result, attr, getattr(tech, attr)) |
||
233 | return result |
||
234 | |||
235 | def getAllTechIDs(): |
||
236 | return Rules.techs.keys() |
||
237 | |||
238 | def getPlayerID(): |
||
239 | return db.playerID |
||
240 | |||
241 | def getPlayer(): |
||
242 | return db[db.playerID] |
||
243 | |||
244 | View Code Duplication | def getDiplomacyWith(contactID): |
|
0 ignored issues
–
show
|
|||
245 | obj = getPlayer() |
||
246 | dipl = obj.diplomacyRels.get(contactID, None) |
||
247 | if not dipl: |
||
248 | # make default |
||
249 | dipl = IDataHolder() |
||
250 | dipl.type = Const.T_DIPLREL |
||
251 | dipl.pacts = { |
||
252 | Const.PACT_ALLOW_CIVILIAN_SHIPS: [Const.PACT_ACTIVE, Const.PACT_ALLOW_CIVILIAN_SHIPS] |
||
253 | } |
||
254 | dipl.relation = obj.defaultRelation |
||
255 | dipl.relChng = 0 |
||
256 | dipl.lastContact = 0 |
||
257 | dipl.stats = None |
||
258 | dipl.contactType = Const.CONTACT_NONE |
||
259 | obj.diplomacyRels[playerID] = dipl |
||
260 | return dipl |
||
261 | |||
262 |