Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
871 lines (705 sloc) 24.1 KB
# Python toolkit for text processing wares.xml
# and other x4f data
import re, sys, os
EOL='\r\n'
TNPATH='./x4f-notes/truenames/'
GUROOT = './v2.50-unpack/'
WaresFile = os.path.join(GUROOT+'libraries/wares.xml')
TransFile = os.path.join(GUROOT,'t/0001-l044.xml')
# Utilities Available:
# GetWareDict() : ware id : [ text of ware node, inclusive ]
# GetWareNames() : ware id : [ tags ]
# getNode( textlist, nodeRE ) : node matching node regex
# ==============================
def _main():
# for ReptilianTakeover
GenCharacters()
# for StopRollingStones
#GenRegionDef_stones()
# for PotatoFactories
#PTF_wares()
# for QuickBuilder
#CutProdTags()
# truenames for x4f-notes
#MakeTruenames_Wares()
#MakeShipsCons()
# ==============================
# ==============================
# ==============================
# ==============================
def GenCharacters():
OROOT = './reptiliantakeover/'
CMFILE = 'libraries/character_macros.xml'
ifile=os.path.join(GUROOT,CMFILE)
rawfile = open( ifile).read()
il = len(rawfile)
rawfile = stripComment( rawfile )
#print( rawfile.find('-->' ) )
print( 'dropped', il-len(rawfile), 'comments')
vlines = [ x.strip() for x in rawfile.split(EOL) ]
print( 'read', ifile, len(vlines), 'lines' )
# read macro tags
macros = getAllNodes( vlines, 'macro')
#print( len(macros), 'macros read' )
kl = macros.keys()
kl.sort()
chars={}
for k in kl:
mtxt = macros[k]
if not len(mtxt): continue
cname = reget('name="(.+?)"',mtxt[0])
if not cname: continue
else: cname = cname[0]
ctag = reget('class="(.+?)"',mtxt[0])
#print ctag
if not ctag or ctag[0] !='npc': continue
if cname.find('boron')>=0: continue
chars[cname] = mtxt
# endfor
mlist = chars.keys()
mlist.sort()
print( len(mlist), 'charmacros' )
reptag = r'''<replace sel="/macros/macro[@name='%s']"> '''
repmacro = [ x.strip() for x in open(os.path.join(OROOT,'libraries/.charmacro'),'r').readlines() ]
output=[]
a=output.append
a( '<?xml version="1.0" encoding="utf-8"?>')
a( '<diff>' )
for cn in mlist:
# print(cn)
# fish out component, identification
mtxt = chars[cn]
cptline = getNode(mtxt,'<component')
if cptline == []: cptline=''
else: cptline= cptline[0]
idline = getNode(mtxt,'<identification')
if idline == []: idline=''
else: idline= idline[0]
# new macro
a( reptag % cn )
a( mtxt[0] ) # macro line
a('<component ref="character_teladi_01" />')
a('<properties>')
a(idline)
output += repmacro
a('</replace>')
a( '' )
a( '' )
# endfor mlist
a( '' )
a('</diff>')
open(os.path.join(OROOT,CMFILE),'w').write( EOL.join( output ) )
return
# ==============================
def SingleRegion( region, text ):
output=[]
#print region, text
# do asteroids
repastg = r'''<replace sel="/regions/region[@name='%s']/fields/asteroid[@groupref='%s']"> '''
repastr = r'''<replace sel="/regions/region[@name='%s']/fields/asteroid[@ref='%s']"> '''
ast = getAllNodes(text, 'asteroid')
#print region, len(ast), 'asteroids'
for k in ast.keys():
atxt = ast[k]
a = atxt[0] # yes im that lazy
# make replace tag
gref= reget('groupref="(.+?)"', a)
ref= reget('\\bref="(.+?)"', a)
if gref:
rl = repastg % (region, gref[0] )
elif ref:
rl = repastr % (region, ref[0] )
# endif
# edit asteroid
dnf= float(reget('densityfactor="(.+?)"', a)[0])
#print (dnf)
# no rotation
a= presub(a, 'rotation="%s"', '0')
a= presub(a, 'rotationvariation="%s"', '0')
# replenishtime (only a few bigs but 150,000? really?)
rpt= reget('replenishtime="(.+?)"', a)
if rpt:
rpt=min( [(float(rpt[0]) *0.5), 3600.0] )
#print (region, gref, ref, rpt)
presub(a,'replenishtime="%s"', ('%0.3f' % rpt) )
# endif
# trim density
if dnf >= 0.7:
dnf = min((dnf*0.5),4) * 0.3
a = presub(a,'densityfactor="%s"', '%0.3f'%dnf)
# endif
# s and xs get lower desnity
if gref and gref[0].endswith( ('_s','_xs') ):
a = presub(a,'densityfactor="%s"', '0.001')
# print vlines[i]
# add to output
atxt[0] = a
output.append( rl )
output += atxt
output.append('</replace>')
# endfor
#output.append( '' )
# do debris (couple of multiples still meh)
repastg = r'''<replace sel="/regions/region[@name='%s']/fields/debris[@groupref='%s']"> '''
repastr = r'''<replace sel="/regions/region[@name='%s']/fields/debris[@ref='%s']"> '''
dst = getAllNodes(text, 'debris')
#print region, len(ast), 'debris'
for k in dst.keys():
atxt = dst[k]
a = atxt[0]
# make replace tag
gref= reget('groupref="(.+?)"', a)
ref= reget('\\bref="(.+?)"', a)
if gref:
rl = repastg % (region, gref[0] )
elif ref:
rl = repastr % (region, ref[0] )
# endif
# no rotation
a= presub(a, 'rotation="%s"', '0')
a= presub(a, 'rotationvariation="%s"', '0')
# add to output
output.append( rl )
atxt[0] = a
output += atxt
output.append('</replace>')
# endfor
#output.append( '' )
# positional fogs
repastr = r'''<replace sel="/regions/region[@name='%s']/fields/positional[@ref='%s']"> '''
dst = getAllNodes(text, 'positional')
print region, len(ast), 'positional'
for k in dst.keys():
atxt = dst[k]
a = atxt[0]
ref= reget('\\bref="(.+?)"', a)
rl = repastr % (region, ref[0] )
dnf= float(reget('densityfactor="(.+?)"', a)[0])
if dnf>0.3:
# do this one
newdnf = min( (dnf*0.5), 0.4 )
a = presub(a,'densityfactor="%s"', '%0.3f'%newdnf)
output.append( rl )
atxt[0] = a
output += atxt
output.append('</replace>')
print (region, ref, dnf, newdnf)
# endif
return output
# ==============================
# edit as diff
def GenRegionDef_stones():
# directory to put generated files
OROOT = './stoprollingstones/'
ifile=os.path.join(GUROOT,'libraries/region_definitions.xml')
rawfile = open( ifile).read()
il = len(rawfile)
rawfile = stripComment( rawfile )
#print( rawfile.find('-->' ) )
print( 'dropped', il-len(rawfile), 'comments')
vlines = [ x.strip() for x in rawfile.split(EOL) ]
print( 'read', ifile, len(vlines), 'lines' )
# read region tags
rgn = getAllNodes( vlines, 'region')
regions = {}
for i in rgn.keys():
rtxt = rgn[i]
rname = reget('name="(.+?)"', rtxt[0])
if rname: regions[rname[0]] = rtxt
# endofr
rlist = regions.keys()
rlist.sort()
print( len(rlist), 'regions' )
# create edited
output = []
for rg in rlist:
remit = SingleRegion( rg, regions[rg] )
if len(remit) <1: continue
print( rg, len(remit) )
output += remit
output.append( '' )
# enfor
# dump
open(os.path.join(OROOT,'#gen-rdefs.xml'),'w').write( EOL.join( output ) )
# ==============================
# first pass to test idea; straight edit
def GenRegionDef_stones1():
# directory to put generated files
OROOT = './stoprollingstones/'
ifile=os.path.join(GUROOT,'libraries/region_definitions.xml')
vlines = [ x.strip() for x in open( ifile).readlines() ]
print( 'read', ifile, len(vlines), 'lines' )
chg = {}
rname=''
for i in range(len(vlines)):
mt = re.search('<region\\b', vlines[i] )
if mt:
rname = reget('name="(.+?)"', vlines[i])[0]
# rot= float(reget('rotation="(.+?)"', vlines[i])[0])
# if float(rot): print( rname, rot)
# nedif
mt=re.search('<asteroid\\b', vlines[i] )
if mt:
#rot= float(reget('rotation="(.+?)"', vlines[i])[0])
#rvar= float(reget('rotationvariation="(.+?)"', vlines[i])[0])
dnx = 0
gref= reget('groupref="(.+?)"', vlines[i])
if gref and gref[0].endswith( ('_s','_xs') ):
dnx = 1
# endif
dnf= float(reget('densityfactor="(.+?)"', vlines[i])[0])
#print (dnf)
vlines[i] = presub(vlines[i], 'rotation="%s"', '0')
vlines[i] = presub(vlines[i], 'rotationvariation="%s"', '0')
if dnf >= 0.7:
dnf = max(dnf,2) * 0.3
vlines[i] = presub(vlines[i],'densityfactor="%s"', '%0.3f'%dnf)
# endif
if dnx:
vlines[i] = presub(vlines[i],'densityfactor="%s"', '0.001')
# print vlines[i]
# endif mt
mt=re.search('<debris\\b', vlines[i] )
if mt:
vlines[i] = presub(vlines[i], 'rotation="%s"', '6')
vlines[i] = presub(vlines[i], 'rotationvariation="%s"', '4')
# endfor i
open(os.path.join(OROOT,'#gen-rdefs.xml'),'w').write( EOL.join(vlines[2:-1]) )
# ==============================
def PTF_wares():
# directory to put generated files
OROOT = './potatofactories/'
# ware ids of modules used as input
wareroots = [ x.strip() for x in open('./ptfnames.txt').readlines() ]
print ( 'doing ', len(wareroots) )
waretext = GetWareDict()
# vanilla ware id = "module_gen_prod_energycells_01"
# vanilla macro = ...best read live "prod_gen_energycells_macro"
# nroot = "energycells"
# ptfware = "moduleptf_prod_energycells"
# ptfmacro = "ptf_prod_energycells_macro"
WareEnd = [
'<restriction licence="station_gen_basic" />',
'<owner faction="antigone" />',
'<owner faction="argon" />',
'<owner faction="holyorder" />',
'<owner faction="paranid" />',
'<owner faction="teladi" />',
]
def ptfize( aline, part):
pre = part % '(.+?)'
mt = re.search(pre, aline)
return re.sub( pre, (part % ('PTF '+mt.group(1) ) ), aline)
# end ptfize
out_roots = []
out_names = {}
out_waretext = {}
out_macros = {}
for nm in wareroots:
# get names
mt = re.search('module_(.+?)_prod_(.+?)_01', nm)
fact = mt.group(1)
nroot = fact+'_'+mt.group(2)
ptfware = "moduleptf_prod_" + nroot
ptfmacro = "ptf_prod_" + nroot + "_macro"
vcnode = [x.strip() for x in getNode( waretext[nm], 'component' ) ]
if not len(vcnode): continue
mt = re.search('ref="(.+?)"', ''.join(vcnode))
vmacro = mt.group(1)
print( nroot, nm, vmacro, ptfware, ptfmacro )
out_roots.append( nroot)
out_names[nroot] = [ptfware, ptfmacro, nm, vmacro]
# Ware node
nware = []
wt = [x.strip() for x in waretext[nm] ]
for wl in wt:
if wl.find('<owner')>=0: continue
if wl.find('<restriction')>=0: continue
if wl.find('<component')>=0:
wl = re.sub('ref="(.+?)"',('ref="%s"' % ptfmacro), wl )
# endif
if wl.find('<production')>=0:
wl = re.sub('time="(.+?)"','time="60"', wl )
# endif
nware.append( wl )
# endfor
nware[0] = re.sub('id="(.+?)"',('id="%s"' % ptfware), nware[0])
nware[0] = ptfize(nware[0], 'name="%s"')
nware[0] = ptfize(nware[0], 'description="%s"')
nware[-1:-1] = WareEnd
#print (nware )
out_waretext[nroot] = nware
# Macro file
vmacro_file = os.path.join(GUROOT,'assets/structures/production/macros', vmacro+'.xml')
vmacro_text = [ x.strip() for x in open(vmacro_file).readlines() ]
nmacro = []
for wl in vmacro_text:
if wl.find('<!--')>=0: continue
if wl.find('<component')>=0: wl='<component ref="ptf_prod_univ" />'
mt=re.search('<macro name=', wl)
if mt:
wl = re.sub('name="(.+?)"',('name="%s"' % ptfmacro), wl )
# endif
if wl.find('<identification')>=0:
wl = ptfize( wl, 'shortname="%s"' )
wl = ptfize( wl, ' name="%s"' )
wl = ptfize( wl, 'description="%s"' )
# endif
nmacro.append( wl )
# endfor
#print (nmacro)
out_macros[nroot] = nmacro
# endfor nm in wareroots
# index entries
MCROOT='extensions/potatofactories/macros/'
out_index=[]
a=out_index.append
for nm in out_roots:
[ptfware, ptfmacro, vware, vmacro] = out_names[nm]
path = MCROOT + ptfmacro
path= path.replace('/',"\\")
a( '<entry name="%s" value="%s" />' % (ptfmacro, path) )
# endfor
#print (out_index)
# icon entries
DOCOPY=0
ICROOT='extensions/potatofactories/ptficons/'
VIROOT=os.path.join(GUROOT,'assets/fx/gui/textures/stationmodules/')
out_icons=[]
a=out_icons.append
for nm in out_roots:
[ptfware, ptfmacro, vware, vmacro] = out_names[nm]
vip = os.path.join(VIROOT,vmacro+'.gz')
nip = os.path.join(OROOT,'ptficons',ptfmacro+'.gz')
# copy
if DOCOPY: open( nip, 'w').write( open( vip ).read() )
path = ICROOT + ptfmacro+'.tga'
path= path.replace('/',"\\")
a( '<icon name="%s" texture="%s" height="256" width="256"></icon>' %
(ptfmacro, path) )
# endfor
#print (out_icons)
MFROOT= os.path.join(OROOT,'#gen-macros' )
# OUTPUT macro files
out_roots.sort()
for nm in out_roots:
[ptfware, ptfmacro, vware, vmacro] = out_names[nm]
print (nm, ptfmacro, len(out_macros[nm]))
open(os.path.join(MFROOT,ptfmacro+'.xml'),'w').write( EOL.join(out_macros[nm]) )
# endfor
# OUTPUT ware nodes
output=[]
for nm in out_roots:
output += out_waretext[nm]
output.append( '' )
# endfor
warefile = os.path.join(OROOT,'#gen-wares.xml')
open(warefile,'w').write( EOL.join( output ))
# OUTPUT index entries
open(os.path.join(OROOT,'#gen-index.xml'),'w').write( EOL.join(out_index) )
# OUTPUT icon entries
open(os.path.join(OROOT,'#gen-icon.xml'),'w').write( EOL.join(out_icons) )
# ==============================
# create lists of ship ware id = Trans name
# for each ship list connection nodes (optionally filtered by tag)
def MakeShipsCons():
# ship definition files to scan
# find ./assets/ -name "ship*.xml" -not -name "*macro.xml" -print
ufnames= [ x.strip() for x in open('./unitfiles').readlines() ]
# tags wanted; empty for all
wanted = 'engine turret weapon shield'
# output file name (in TNPATH)
outname='ship-connections-forstart.txt'
wanted=''
outname='ship-connections-all.txt'
# prep wanted
wanttags=wanted.split(' ')
wanttagsdict ={}
for t in wanttags: wanttagsdict[t]=None
warenames = GetWareNames()
tpages= ReadTfile(TransFile)
# read all the connections in ship def files
udict = {}
for unitfile in ufnames:
(sid, cons) = stripShip( unitfile, wanttagsdict )
#print( sid, cons)
udict[sid]= cons
# endfor
# output
ships=udict.keys()
ships.sort()
output=[]
a=output.append
for sid in ships:
a( '' )
tn = warenames.get(sid+'_a')
if tn:
tname= tpages[tn[0]][tn[1]]
else:
tname="noname"
# endif
a( sid + ' = ' + tname )
cons = udict[sid]
conk = cons.keys()
conk.sort()
#print( sid,conk)
if wanted: # abbreviated output
a( '\t'+ ', '.join(conk) )
else: # tags too
for cn in conk:
a( '\t'+cn+': '+ ' '.join( cons[cn] ) )
# endofr
# endif
# endofr sid
open(os.path.join(TNPATH,outname),'w').write( EOL.join(output) )
return
# ==============================
# pull data from a ship definition file
def stripShip( unitfile, wanttagsdict={} ):
udef = [ x.strip() for x in open(os.path.join(GUROOT,unitfile)).readlines() ]
print ('read %s, %d lines ' % (unitfile, len(udef)) )
# ship id = component:name
sid = ''
for i in range(len(udef)):
if re.search('<component ',udef[i]):
#print( udef[i] )
mt = re.search('name="(.+?)"', udef[i])
sid = mt.group(1)
break
# endif
# endofr
if not sid: return None
# connections = connection:name
# grab tags too
conx = {}
for i in range(len(udef)):
if re.search('<connection ',udef[i]):
#print( udef[i] )
mt = re.search('name="(.+?)"', udef[i])
cname = mt.group(1)
mt = re.search('tags="(.+?)"', udef[i])
tags = [x.strip() for x in mt.group(1).split(' ') ]
want=1
if wanttagsdict:
want = 0
for t in tags:
if wanttagsdict.has_key(t):
want=1
break
# endif
# endfor t
# endif wanttags
if want:
conx[cname] = tags
#print( cname, tags )
# endif
return sid, conx
# ==============================
# get name attrs of wares
def GetWareNames():
# get warename / tid
wtx= GetWareDict()
warenames = {}
for wid in wtx.keys():
wtext = wtx[wid]
mt = re.search('name="(.*?)"', wtext[0])
tid = mt.group(1)
mt = re.search('{(\d+?),\s*?(\d+?)}', tid)
if mt: tid = [mt.group(1), mt.group(2)]
warenames[wid] = tid
# endfor
return warenames
# ==============================
# create lists of ware id by tags
def MakeTruenames_Wares():
wtx= GetWareDict()
alltags={}
for wid in wtx.keys():
wtext = wtx[wid]
mt = re.search('tags="(.*?)"', wtext[0] )
if mt:
tags= mt.group(1).split(' ')
for t in tags:
alltags[t] = alltags.get(t,[]) + [wid]
#endfor
# endfor mt
# endfor wid
tags=alltags.keys()
tags.sort()
for t in tags:
# print (t, len(alltags[t]))
wlist = alltags[t]
if len(wlist) < 6: continue
wlist.sort()
open(os.path.join(TNPATH,'warestag',t+'.txt'),'w').write( EOL.join(wlist) )
print( 'created %s.txt, %d entries' % (t, len(wlist)) )
# endfor t
wl = wtx.keys()
wl.sort()
open(os.path.join(TNPATH,'allwares.txt'),'w').write( EOL.join(wl) )
# ==============================
# different: replace whole ware node
# smae: generate modules with "time" attrib changed
def CutProdTags2():
wtx = GetWareDict()
DesiredWareNames = [x.strip() for x in open('module.txt').readlines() ]
# subs time="10" in production node
output=[]
a=output.append
le='\n'
for wid in DesiredWareNames:
#prodnode= [x.strip() for x in getNode( wtx[wid], 'production' ) ]
node= [x.strip() for x in wtx[wid] ]
prodline=0
for i in range(len(node)):
if re.search('production',node[i]):
prodline=i
break
# endif
# endofr
#a('<replace sel="/wares/ware[@id='+ "'"+ wid +"'"+']">' )
# edit the production line
node[prodline] = re.sub('time="(.+?)"','time="10"',node[prodline])
# print( wid, prodline)
output += node
#a('</replace>')
a( '')
# endfor
print (le.join(output))
# ==============================
# generate modules with "time" attrib changed
# this is what made quickbuilder
# i bet this could be done with 42 characters of perl
def CutProdTags():
wtx = GetWareDict()
DesiredWareNames = [x.strip() for x in open('module.txt').readlines() ]
# subs time="10" in production node
repstr = r'''<replace sel="/wares/ware[@id='%s']/production[@method='default']"> '''
output=[]
a=output.append
le='\n'
for wid in DesiredWareNames:
prodnode= [x.strip() for x in getNode( wtx[wid], 'production' ) ]
if not len(prodnode): continue
a( repstr % wid )
# edit the first line
nline = re.sub('time="(.+?)"','time="10"',prodnode[0])
#print( wid, nline)
a( nline )
output += prodnode[1:]
a('</replace>')
a( '')
# endfor
print (le.join(output))
# =================================
# =================================
# =================================
# =================================
# =================================
def stripComment( text ):
cmtre = r'''<!--(.+?)-->'''
return re.sub( cmtre, '', text, count=0, flags=re.S )
# =================================
def reget(regx,line):
mt = re.search(regx,line)
if not mt: return None
return mt.groups()
# ==============================
def presub( aline, part, newpart):
# part = 'someregex %s'
pre = part % '(.+?)'
mt = re.search(pre, aline)
return re.sub( pre, (part % newpart), aline)
# end presub
# =================================
# tag = node(s) to get
# return dict {k: [nodes text] }
# where k = seqential # of node as found in text
# todo: add key on attribute value
def getAllNodes(text, tag, key_attrib=None):
nodes={}
inf = 0
nt = []
for i in range(len(text)):
mt = re.search('<'+tag+'\\b', text[i] )
et = re.search('</'+tag+'>', text[i] )
et2 = re.search('/>', text[i] )
if mt: inf = 1
if inf: nt.append( text[i] )
if et or (mt and et2):
nodes[len(nodes)] = nt
nt=[]
inf=0
# endif
# endfor
#print( len(nodes), tag,' nodes' )
return nodes
# =================================
def getNode( tlist, nodere ):
ts=0
for i in range(len(tlist)):
if re.search( nodere, tlist[i] ):
if ts: return tlist[ts:i+1]
ts=i
# is single line?
if re.search( '/>', tlist[i] ): return tlist[ts:ts+1]
# endif
# endfor
return [] # wasnt there
# ==============================
# read a t file into page[text] dicts
def ReadTfile( filename ):
rawlines = open(filename).readlines()
ptr=0
pid=''
pages={}
while 1:
if ptr >= len(rawlines): break
mt = re.search('<page id="(\d+?)"',rawlines[ptr])
if mt:
pid = mt.group(1)
pages[pid]={}
ptr += 1
continue
# endif
mt = re.search('<t id="(\d+?)".*>(.*?)</t>',rawlines[ptr])
if mt:
pages[pid][ mt.group(1) ] = mt.group(2)
# endif
ptr +=1
# endwhile
return pages
# =================================
# 'wareid' : [ lines of definition xml ]
def GetWareDict():
rawlines = open(WaresFile).readlines()
print('read wares.xml %d lines' % len(rawlines) )
wbegin = re.compile('<ware.*id="(.+?)"(.*)')
wend = re.compile('</ware')
ptr=0
waretext ={}
firstline=ptr
while 1:
if ptr >= len(rawlines): break
mt = wbegin.search(rawlines[ptr])
if mt:
firstline=ptr
wid= mt.group(1)
# print wid, mt.groups()
# scan for end
while 1:
ptr=ptr+1
if ptr >= len(rawlines): break
emt = wend.search(rawlines[ptr])
if emt: break
# endwhile
# add to dict
waretext[ wid ] = rawlines[firstline:ptr+1]
#print wid, len(waretext[wid])
# endif
ptr = ptr+1
# end while
return waretext
# =================================
# =================================
if __name__=='__main__': _main()
You can’t perform that action at this time.