Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2017
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.92 KB | None | 0 0
  1. # ./addons/eventscripts/_libs/python/cfglib.py
  2.  
  3. import es
  4. import os.path
  5. from configobj import ConfigObj
  6.  
  7. import psyco
  8. psyco.full()
  9.  
  10.  
  11. class AddonCFG(object):
  12. """ Class for handling addon .cfg files """
  13.  
  14. TYPE_TEXT = 0
  15. TYPE_CVAR = 1
  16. TYPE_COMMAND = 2
  17.  
  18. gamedir = str(es.ServerVar('eventscripts_gamedir')).replace('\\', '/')
  19.  
  20. """ Begin AddonCFG """
  21.  
  22. def __init__(self, cfgpath, indention=3):
  23. self.cfgpath = cfgpath.replace('\\', '/')
  24. self.indention = indention
  25.  
  26. self.cfglist = []
  27. self.commands = set()
  28. self.cvars = {}
  29.  
  30. """ Public functions """
  31.  
  32. def text(self, text, comment=True):
  33. """ Adds the given text to the config """
  34. if not text.strip(): comment = False
  35. self.cfglist.append((self.TYPE_TEXT, ('// ' if comment else '') + str(text) + '\n'))
  36.  
  37. def cvar(self, name, default, description=''):
  38. """ Adds the named cvar to the config and returns a ServerVar instance """
  39. var = self.cvars[name] = (name, default, description)
  40. self.cfglist.append((self.TYPE_CVAR, var))
  41.  
  42. return es.ServerVar(name, default, description)
  43.  
  44. def command(self, name):
  45. """ Designates a place for the named server command in the config """
  46. self.commands.add(name)
  47.  
  48. self.cfglist.append((self.TYPE_COMMAND, name))
  49.  
  50. def write(self):
  51. """ Writes the config to file """
  52. current_cfg = self._parse()
  53. indention = ' ' * self.indention
  54.  
  55. cfgfile = open(self.cfgpath, 'w')
  56.  
  57. # Write the config to file
  58.  
  59. for ltype, data in self.cfglist:
  60. # Write text
  61. if ltype == self.TYPE_TEXT:
  62. cfgfile.write(data)
  63.  
  64. # Write cvar
  65. elif ltype == self.TYPE_CVAR:
  66. name, default, description = data
  67.  
  68. cfgfile.write('\n')
  69. if description:
  70. cfgfile.write('// %s\n' % description)
  71.  
  72. if name in current_cfg:
  73. cfgfile.write(indention + current_cfg[name][0] + '\n')
  74. del current_cfg[name]
  75.  
  76. else:
  77. cfgfile.write(indention + name + ' ' + ('"%s"' if isinstance(default, str) else '%s') % default + '\n')
  78.  
  79. # Write server command
  80. elif ltype == self.TYPE_COMMAND:
  81. if data in current_cfg:
  82. cfgfile.write('\n')
  83. for old_line in current_cfg[data]:
  84. cfgfile.write(indention + old_line + '\n')
  85. del current_cfg[data]
  86.  
  87. # Write extraneous commands or variables
  88. if current_cfg:
  89. cfgfile.write('\n')
  90. for name in sorted(filter(lambda x: es.exists('variable', x) or es.exists('command', x), current_cfg)):
  91. for line in current_cfg[name]:
  92. cfgfile.write(indention + line + '\n')
  93. del current_cfg[name]
  94.  
  95. # Write unrecognized data
  96. if current_cfg:
  97. cfgfile.write('\n')
  98. for name in sorted(current_cfg): # If we don't sort these names they'll appear in a new order every time the .cfg is created
  99. for line in current_cfg[name]:
  100. cfgfile.write('// ' + line + '\n')
  101.  
  102. cfgfile.close()
  103.  
  104. def execute(self, queuecmd=False):
  105. """ Executes the config """
  106. es.mexec(self.cfgpath.replace(self.gamedir, '', 1))
  107.  
  108. def getCvars(self):
  109. """ Returns the cvars dictionary """
  110. return self.cvars.copy()
  111.  
  112. """ Private functions """
  113.  
  114. def _parse(self):
  115. """ Internal function: Parses the config and returns the current settings """
  116. if not os.path.isfile(self.cfgpath):
  117. return {}
  118.  
  119. cfgfile = open(self.cfgpath)
  120. cfglines = map(str.strip, cfgfile.readlines())
  121. cfgfile.close()
  122.  
  123. current_cfg = {}
  124.  
  125. for line in cfglines:
  126. if line.startswith('//') or not line: continue
  127.  
  128. name = line.split(' ', 1)[0]
  129. if name in self.commands or name in self.cvars:
  130. if not line.count(' '): continue
  131.  
  132. if name not in current_cfg:
  133. current_cfg[name] = []
  134.  
  135. if line not in current_cfg[name]:
  136. current_cfg[name].append(line + ('"' if line.count('"') % 2 else ''))
  137.  
  138. return current_cfg
  139.  
  140. """
  141. # Example usage:
  142.  
  143. import cfglib
  144. import es
  145.  
  146. config = cfglib.AddonCFG(es.getAddonPath("mugmod") + "/mugmod.cfg")
  147.  
  148. config.text("******************************")
  149. config.text(" MUGMOD SETTINGS")
  150. config.text("******************************")
  151.  
  152. mattie_mugmod = config.cvar("mattie_mugmod", 1, "Enable/disable Mattie's MugMod")
  153. mugmod_announce = config.cvar("mugmod_announce", 1, "Announces MugMod each round.")
  154. mugmod_taunt = config.cvar("mugmod_taunt", 1, "Taunts the mugging victim with a random message.")
  155. mugmod_sounds = config.cvar("mugmod_sounds", 1, "Enables kill sounds for MugMod")
  156. mugmod_soundfile = config.cvar("mugmod_soundfile", "bot/owned.wav", "Sound played for a mugging if mugmod_sounds is 1")
  157. mugmod_percentage = config.cvar("mugmod_percentage", 100, "Percentage of money stolen during a mugging.")
  158.  
  159. config.write() # Writes the .cfg to file
  160.  
  161.  
  162. def load():
  163. config.execute() # Executes the .cfg to register changes
  164. """
  165.  
  166.  
  167. class AddonINI(ConfigObj):
  168. """ Class for handling addon .ini files, mostly for langlib """
  169.  
  170. def __init__(self, filename, *a, **kw):
  171. super(AddonINI, self).__init__(filename, *a, **kw)
  172. self.unrepr = True # Allows us to write Python types (mainly for strings)
  173. self.filepath = filename # We need to know the file path to write the file later
  174. # But we don't want ConfigObj to write the file so we need to make it think we want a string output
  175. self.filename = None
  176. self.order = []
  177.  
  178. """ Comment functions """
  179.  
  180. def setInitialComments(self, comment_list):
  181. """ Sets the comments at the top of the ini file, lists or strings acceptable """
  182. if isinstance(comment_list, basestring):
  183. comment_list = [comment_list,]
  184. if comment_list and not comment_list[~0]:
  185. del comment_list[~0]
  186. self.initial_comment = map(self.formatComment, comment_list)
  187.  
  188. def setFinalComments(self, comment_list):
  189. """ Sets the comments at the bottom of the ini file, lists or strings acceptable """
  190. if isinstance(comment_list, basestring):
  191. comment_list = [comment_list,]
  192. if comment_list and not comment_list[~0]:
  193. del comment_list[~0]
  194. self.final_comment = [''] + map(self.formatComment, comment_list)
  195.  
  196.  
  197. """ Header functions """
  198.  
  199. def addGroup(self, header):
  200. """ Adds a group (tranlation phrase identifier) to the ini for another phrase for translation """
  201. self.order.append(header)
  202. self[header]
  203. self.comments[header] = ['']
  204.  
  205. def delGroup(self, header):
  206. """ Removes a group from the ini file """
  207. if header in self:
  208. del self[header]
  209.  
  210. def setGroupComments(self, header, comment_list):
  211. """ Sets the comments associated with a group, comments acceptable as list or strings """
  212. if isinstance(comment_list, basestring):
  213. comment_list = (comment_list,)
  214. self.comments[header] = [''] + map(self.formatComment, comment_list)
  215.  
  216.  
  217. """ Value functions """
  218.  
  219. def addValueToGroup(self, header, identifier, value, overwrite=False):
  220. """
  221. Adds an identifier (language abbreviation) and corresponding value (translation) to
  222. a group. This function will be ignored if the identifier already exists unless
  223. the overwrite keyword is True.
  224. """
  225. if identifier not in self[header] or overwrite:
  226. self[header][identifier] = value
  227. return True
  228.  
  229. return False
  230.  
  231. def delValueFromGroup(self, header, identifier):
  232. """ Removes an identifier (language abbreviation and corresponding translation) from ini file """
  233. if identifier in self[header]:
  234. del self[header][identifier]
  235.  
  236.  
  237. """ Override functions """
  238.  
  239. def write(self, outfile=None, **kw):
  240. """
  241. Writes contents of the ini to file
  242. We only override this function so the user doesn't have to provide a file name
  243. and we can write the file ourselves.
  244. """
  245. # Write calls itself again with the section keyword. This is very hacky but should work for now
  246. if 'section' in kw and len(kw) == 1 and outfile is None:
  247. return super(AddonINI, self).write(**kw)
  248.  
  249. # If a blank line is at the bottom of the initial comments we strip it for aesthetics
  250. if self.initial_comment and not self.initial_comment[~0]:
  251. del self.initial_comment[~0]
  252.  
  253. # If the user specified a preferred order we enforce that here
  254. if self.order:
  255. sort_order = list(reversed(self.order))
  256. self.sections = sorted(self.sections, key=lambda x: (sort_order.index(x) + 1) if x in sort_order else 0, reverse=True)
  257.  
  258. # Normal ConfigObj outfiles use the "wb" mode which isn't Windows-friendly
  259. if outfile is None:
  260. f = open(self.filepath, 'w')
  261. f.write('\n'.join(super(AddonINI, self).write()))
  262. f.close()
  263. else:
  264. outfile.write('\n'.join(super(AddonINI, self).write()))
  265.  
  266. def __getitem__(self, item):
  267. """ If the item to get doesn't exist we initialize it with an empty dictionary """
  268. if item not in self:
  269. self[item] = {}
  270. return super(AddonINI, self).__getitem__(item)
  271.  
  272. def __str__(self):
  273. return self.filename
  274.  
  275. def __coerce__(self, other):
  276. if isinstance(str, other):
  277. return self.filename, other
  278. return None
  279.  
  280.  
  281. """ Static methods """
  282.  
  283. @staticmethod
  284. def formatComment(comment):
  285. comment = comment.strip()
  286. if comment and not comment.startswith('#'):
  287. comment = '# ' + comment
  288. return comment
  289.  
  290. """
  291. import cfglib
  292. import es
  293.  
  294. ini = cfglib.AddonINI(es.getAddonPath('test') + '/languages.ini')
  295.  
  296. # Set initial and final comments
  297. ini.setInitialComments(['Yay, an initial comment!', 'We belong at the beginning of the .ini'])
  298. ini.setFinalComments("I'm a final comment")
  299.  
  300. # Add an existing group (only has effect if the group doesn't exist)
  301. ini.addGroup('Welcome')
  302. ini.addValueToGroup('Welcome', 'en', 'Welcome') # Values that already exist are ignored
  303. ini.addValueToGroup('Welcome', 'fr', 'Bienvenue')
  304. ini.addValueToGroup('Welcome', 'ge', 'Willkommen')
  305. ini.setGroupComments('Welcome', 'This group is for the welcome message')
  306.  
  307. ini.addGroup('to Cabaret')
  308. ini.addValueToGroup('to Cabaret', 'en', 'to Cabaret')
  309. ini.addValueToGroup('to Cabaret', 'fr', 'su Cabaret')
  310. ini.addValueToGroup('to Cabaret', 'ge', 'im Cabaret')
  311.  
  312. ini.write()
  313.  
  314. ### Can also be used with langlib ###
  315. import langlib
  316.  
  317. text = langlib.Strings(ini)
  318.  
  319. ### languages.ini output ###
  320.  
  321. # Yay, an initial comment!
  322. # We belong at the beginning of the .ini
  323.  
  324. # This header is for the welcome message
  325. [Welcome]
  326. en = 'Welcome'
  327. fr = 'Bienvenue'
  328. ge = 'Willkommen'
  329.  
  330. [to Cabaret]
  331. en = 'to Cabaret'
  332. fr = 'su Cabaret'
  333. ge = 'im Cabaret'
  334.  
  335. # I'm a final comment
  336. """
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement