mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-23 20:16:55 +01:00
Yeah fuck this tools folder, installed BYONDtools directly into python instead.
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
*.pyc
|
||||
/doc/_build
|
||||
*.bak
|
||||
/.tox
|
||||
/BYONDTools.egg-info
|
||||
/build
|
||||
/dist
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>ByondTools</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Rob "N3X15" Nelson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,30 +0,0 @@
|
||||
OpenByond
|
||||
=========
|
||||
|
||||
A set of tools for BYOND-based games.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This is a toolkit for developers of BYOND-based games intended to do common, complex
|
||||
tasks that the engine itself does not currently possess. It also exposes common
|
||||
interfaces for developers wishing to obtain information from the BYOND object tree,
|
||||
maps, and DMIs.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
* Python 2.7+
|
||||
* Python Imaging Library (PIL)
|
||||
* numpy
|
||||
|
||||
Use
|
||||
---
|
||||
|
||||
Each script has documentation in its code at the top of each file.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
No commercial or official support is provided, but you are free to
|
||||
submit bug reports or harass N3X15 in irc.rizon.net #vgstation.
|
||||
@@ -1,142 +0,0 @@
|
||||
from byond import directions
|
||||
from PIL import Image
|
||||
import logging
|
||||
|
||||
class State:
|
||||
# So we don't overwrite the static state.
|
||||
MovementTag = 'M'
|
||||
def __init__(self, nm):
|
||||
self.name = nm
|
||||
self.hotspot = ''
|
||||
self.frames = 0
|
||||
self.dirs = 1
|
||||
self.movement = 0
|
||||
self.loop = 0
|
||||
self.rewind = 0
|
||||
self.delay = []
|
||||
self.icons = []
|
||||
self.positions = []
|
||||
|
||||
@staticmethod
|
||||
def MakeKey(name,movement=False):
|
||||
key = name
|
||||
tags = ''
|
||||
if movement:
|
||||
tags += State.MovementTag
|
||||
if tags != '':
|
||||
key += '\t' + tags
|
||||
return key
|
||||
|
||||
def genManifest(self):
|
||||
'''
|
||||
state = "void"
|
||||
dirs = 4
|
||||
frames = 4
|
||||
delay = 2,2,2,2
|
||||
'''
|
||||
o = '\r\nstate = "{0}"'.format(self.name)
|
||||
o += self.genManifestLine('hotspot', self.hotspot, '')
|
||||
o += self.genManifestLine('frames', self.frames, -1)
|
||||
o += self.genManifestLine('dirs', self.dirs, -1)
|
||||
o += self.genManifestLine('movement', self.movement, 0)
|
||||
o += self.genManifestLine('loop', self.loop, 0)
|
||||
o += self.genManifestLine('rewind', self.rewind, 0)
|
||||
o += self.genManifestLine('delay', self.delay, [])
|
||||
|
||||
return o
|
||||
|
||||
# Mostly for movement states.
|
||||
def displayName(self):
|
||||
tags=[]
|
||||
if self.movement:
|
||||
tags += self.MovementTag
|
||||
if len(tags)>0:
|
||||
return '{} ({})'.format(self.name,', '.join(tags))
|
||||
return self.name
|
||||
|
||||
def genDMIH(self):
|
||||
o = '\r\nstate "%s" {' % self.name
|
||||
o += self.genDMIHLine('hotspot', self.hotspot, '')
|
||||
o += self.genDMIHLine('frames', self.frames, -1)
|
||||
tdirs = 'ONE'
|
||||
if self.dirs == 4:
|
||||
tdirs = 'CARDINAL'
|
||||
elif self.dirs == 8:
|
||||
tdirs = 'ALL'
|
||||
o += self.genDMIHLine('dirs', tdirs, '')
|
||||
o += self.genDMIHLine('movement', self.movement, 0)
|
||||
o += self.genDMIHLine('loop', self.loop, 0)
|
||||
o += self.genDMIHLine('rewind', self.rewind, 0)
|
||||
o += self.genDMIHLine('delay', self.delay, [])
|
||||
|
||||
o += '\n\timport pngs {'
|
||||
for vdir in range(self.dirs):
|
||||
_dir = directions.IMAGE_INDICES[vdir]
|
||||
o += '\n\t\tdirection "%s" {' % directions.getNameFromDir(_dir)
|
||||
for f in range(self.frames):
|
||||
o += '\n\t\t\t"%s"' % self.getFrame(_dir, f)
|
||||
o += '\n\t\t}'
|
||||
o += '\n\t}'
|
||||
o += "\n}"
|
||||
return o
|
||||
|
||||
def key(self):
|
||||
return State.MakeKey(self.name, movement=self.movement==1)
|
||||
|
||||
def genDMIHLine(self, name, value, default):
|
||||
if value != default:
|
||||
if type(value) is list:
|
||||
value = ','.join(value)
|
||||
return '\n\t{0} = {1}'.format(name, value)
|
||||
return ''
|
||||
|
||||
def genManifestLine(self, name, value, default):
|
||||
if value != default:
|
||||
if type(value) is list:
|
||||
value = ','.join(value)
|
||||
return '\n\t{0} = {1}'.format(name, value)
|
||||
return ''
|
||||
|
||||
def ToString(self):
|
||||
o = '%s: %d frames, ' % (self.name, self.frames)
|
||||
o += '%d directions' % self.dirs
|
||||
# o += ' icons: ' + repr(self.icons)
|
||||
return o
|
||||
|
||||
def numIcons(self):
|
||||
return self.frames * self.dirs
|
||||
|
||||
def getFrameIndex(self, direction, frame):
|
||||
_dir = 0
|
||||
if self.dirs == 4 or self.dirs == 8:
|
||||
_dir = directions.IMAGE_INDICES.index(direction)
|
||||
if self.dirs == 4 and _dir > 3:
|
||||
_dir = 0
|
||||
|
||||
frame = _dir + (frame * self.dirs)
|
||||
if frame > len(self.icons):
|
||||
logging.warn('Only {} icons in state, args {{dir:{}, frame:{}}}: {}'.format(len(self.icons), direction, frame, self.ToString()))
|
||||
return frame
|
||||
|
||||
def getFrame(self, direction, frame):
|
||||
return self.icons[self.getFrameIndex(direction, frame)]
|
||||
|
||||
def setFrame(self, direction, frame, img):
|
||||
fi = self.getFrameIndex(direction, frame)
|
||||
if len(self.icons) < fi:
|
||||
shouldBeSize = 1
|
||||
if fi > 7:
|
||||
logging.error('Unable to set frame: State uninitialized with that many frames.')
|
||||
return
|
||||
elif fi > 3:
|
||||
shouldBeSize = 8
|
||||
elif fi > 0:
|
||||
shouldBeSize = 4
|
||||
while len(self.icons) < shouldBeSize:
|
||||
self.icons.append(Image.new('RGBA', (32, 32)))
|
||||
logging.warn('{0} now has {1} frames.'.format(self.name, len(self.icons)))
|
||||
self.icons[fi] = img
|
||||
|
||||
def postProcess(self):
|
||||
# So old I forgot what everything did.
|
||||
return
|
||||
@@ -1,379 +0,0 @@
|
||||
|
||||
import sys, os, glob, string, traceback, fnmatch, math, shutil, collections
|
||||
|
||||
from PIL import Image, PngImagePlugin
|
||||
from .State import State
|
||||
from byond.DMIH import *
|
||||
import logging
|
||||
|
||||
class DMILoadFlags:
|
||||
NoImages = 1
|
||||
NoPostProcessing = 2
|
||||
|
||||
|
||||
class DMI:
|
||||
MovementTag = '\t'
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.version = ''
|
||||
self.states = collections.OrderedDict() # {}
|
||||
self.icon_width = 32
|
||||
self.icon_height = 32
|
||||
self.pixels = None
|
||||
self.size = ()
|
||||
self.statelist = 'LOLNONE'
|
||||
self.max_x = -1
|
||||
self.max_y = -1
|
||||
self.img = None
|
||||
|
||||
def make(self, makefile):
|
||||
print('>>> Compiling %s -> %s' % (makefile, self.filename))
|
||||
h = DMIH()
|
||||
h.parse(makefile)
|
||||
for node in h.tokens:
|
||||
if type(node) is Variable:
|
||||
if node.name == 'height':
|
||||
self.icon_height = node.value
|
||||
elif node.name == 'weight':
|
||||
self.icon_width = node.value
|
||||
elif type(node) is directives.State:
|
||||
self.states[node.state.key()] = node.state
|
||||
elif type(node) is directives.Import:
|
||||
if node.ftype == 'dmi':
|
||||
dmi = DMI(node.filedef)
|
||||
dmi.extractTo("_tmp/" + os.path.basename(node.filedef))
|
||||
for name in dmi.states:
|
||||
self.states[name] = dmi.states[name]
|
||||
|
||||
def save(self, to, **kwargs):
|
||||
if len(self.states) == 0:
|
||||
return # Nope.
|
||||
# Now build the manifest
|
||||
manifest = '#BEGIN DMI'
|
||||
manifest += '\nversion = 4.0'
|
||||
manifest += '\n\twidth = {0}'.format(self.icon_width)
|
||||
manifest += '\n\theight = {0}'.format(self.icon_height)
|
||||
|
||||
frames = []
|
||||
fdata = []
|
||||
|
||||
# Sort by name because I'm autistic like that.
|
||||
ordered = self.states
|
||||
if kwargs.get('sort', True):
|
||||
ordered = sorted(self.states.keys())
|
||||
|
||||
for name in ordered:
|
||||
if len(self.states[name].icons) > 0:
|
||||
manifest += self.states[name].genManifest()
|
||||
numIcons = self.states[name].numIcons()
|
||||
lenIcons = len(self.states[name].icons)
|
||||
if numIcons != lenIcons:
|
||||
logging.warn('numIcons={0}, len(icons)={1} in state {2}!'.format(numIcons, lenIcons, name))
|
||||
# frames += self.states[name].icons
|
||||
# frames.extend(self.states[name].icons)
|
||||
for i in range(len(self.states[name].icons)):
|
||||
fdata += ['{}[{}]'.format(self.states[name].name, i)]
|
||||
frames += [self.states[name].icons[i]]
|
||||
else:
|
||||
logging.warn('State {0} has 0 icons.'.format(name))
|
||||
manifest += '\n#END DMI'
|
||||
|
||||
# print(manifest)
|
||||
|
||||
# Next bit borrowed from DMIDE.
|
||||
icons_per_row = math.ceil(math.sqrt(len(frames)))
|
||||
rows = icons_per_row
|
||||
|
||||
if len(frames) > icons_per_row * rows:
|
||||
rows += 1
|
||||
|
||||
sheet = Image.new('RGBA', (int((icons_per_row + 1) * self.icon_width), int(rows * self.icon_height)))
|
||||
|
||||
x = 0
|
||||
y = 0
|
||||
# for frame in frames:
|
||||
# print('per_row={0}, rows={1}, size={2}'.format(icons_per_row,rows,sheet.size))
|
||||
for f in range(len(frames)):
|
||||
frame = frames[f]
|
||||
icon = frame
|
||||
if isinstance(frame, str):
|
||||
icon = Image.open(frame, 'r')
|
||||
box = (x * self.icon_width, y * self.icon_height)
|
||||
# print('{0} -> ({1},{2}) {3} {4}'.format(f,x,y,box,fdata[f]))
|
||||
sheet.paste(icon, box, icon)
|
||||
x += 1
|
||||
if x > icons_per_row:
|
||||
y += 1
|
||||
x = 0
|
||||
|
||||
# More borrowed from DMIDE:
|
||||
# undocumented class
|
||||
meta = PngImagePlugin.PngInfo()
|
||||
|
||||
# copy metadata into new object
|
||||
reserved = ('interlace', 'gamma', 'dpi', 'transparency', 'aspect')
|
||||
for k, v in sheet.info.items():
|
||||
if k in reserved: continue
|
||||
meta.add_text(k, v, 1)
|
||||
|
||||
# Only need one - Rob
|
||||
meta.add_text(b'Description', manifest.encode('ascii'), 1)
|
||||
|
||||
# and save
|
||||
sheet.save(to, 'PNG', pnginfo=meta)
|
||||
# with open(to+'.txt','w') as f:
|
||||
# f.write(manifest)
|
||||
# logging.info('>>> {0} states saved to {1}'.format(len(frames), to))
|
||||
|
||||
def getDMIH(self):
|
||||
o = '# DMI Header 1.0 - Generated by DMI.py'
|
||||
o += self.genDMIHLine('width', self.icon_width, -1)
|
||||
o += self.genDMIHLine('height', self.icon_height, -1)
|
||||
|
||||
for s in sorted(self.states):
|
||||
o += self.states[s].genDMIH()
|
||||
|
||||
return o
|
||||
|
||||
def genDMIHLine(self, name, value, default):
|
||||
if value != default:
|
||||
if type(value) is list:
|
||||
value = ','.join(value)
|
||||
return '\n{0} = {1}'.format(name, value)
|
||||
return ''
|
||||
|
||||
def extractTo(self, dest, suppress_post_process=False):
|
||||
flags = 0
|
||||
if(suppress_post_process):
|
||||
flags |= DMILoadFlags.NoPostProcessing
|
||||
# print('>>> Loading %s...' % self.filename)
|
||||
self.loadAll(flags)
|
||||
# print('>>> Extracting %s...' % self.filename)
|
||||
self.extractAllStates(dest, flags)
|
||||
|
||||
def getFrame(self, state, direction, frame, movement=False):
|
||||
state = State.MakeKey(state,movement=movement)
|
||||
if state not in self.states:
|
||||
return None
|
||||
return self.states[state].getFrame(direction, frame)
|
||||
|
||||
def setFrame(self, state, direction, frame, img, movement=False):
|
||||
state = State.MakeKey(state,movement=movement)
|
||||
if state not in self.states:
|
||||
self.states[state] = State(state)
|
||||
return self.states[state].setFrame(direction, frame, img)
|
||||
|
||||
def getHeader(self):
|
||||
img = Image.open(self.filename)
|
||||
if(b'Description' not in img.info):
|
||||
raise Exception("DMI Description is not in the information headers!")
|
||||
return img.info[b'Description'].decode('ascii')
|
||||
|
||||
def setHeader(self, newHeader, dest):
|
||||
img = Image.open(self.filename)
|
||||
|
||||
# More borrowed from DMIDE:
|
||||
# undocumented class
|
||||
meta = PngImagePlugin.PngInfo()
|
||||
|
||||
# copy metadata into new object
|
||||
reserved = ('interlace', 'gamma', 'dpi', 'transparency', 'aspect', 'icc_profile')
|
||||
for k, v in img.info.items():
|
||||
if k in reserved: continue
|
||||
# print(k, v)
|
||||
meta.add_text(k, v, 1)
|
||||
|
||||
# Only need one - Rob
|
||||
meta.add_text(b'Description', newHeader.encode('ascii'), 1)
|
||||
|
||||
# and save
|
||||
img.save(dest + '.tmp', 'PNG', pnginfo=meta)
|
||||
shutil.move(dest + '.tmp', dest)
|
||||
|
||||
def loadMetadata(self, flags=0):
|
||||
self.load(flags | DMILoadFlags.NoImages)
|
||||
|
||||
def loadAll(self, flags=0):
|
||||
self.load(flags)
|
||||
|
||||
def load(self, flags):
|
||||
self.img = Image.open(self.filename)
|
||||
|
||||
# This is a stupid hack to work around BYOND generating indexed PNGs with unspecified transparency.
|
||||
# Uncorrected, this will result in PIL(low) trying to read the colors as alpha.
|
||||
if self.img.mode == 'P':
|
||||
# If there's no transparency, set it to black.
|
||||
if 'transparency' not in self.img.info:
|
||||
logging.warn('({0}): Indexed PNG does not specify transparency! Setting black as transparency. self.img.info = {1}'.format(self.filename, repr(self.img.info)))
|
||||
self.img.info['transparency'] = 0
|
||||
|
||||
# Always use RGBA, it causes less problems.
|
||||
self.img = self.img.convert('RGBA')
|
||||
|
||||
self.size = self.img.size
|
||||
|
||||
# Sanity
|
||||
if(b'Description' not in self.img.info):
|
||||
raise Exception("DMI Description is not in the information headers!")
|
||||
|
||||
# Load pixels from image
|
||||
self.pixels = self.img.load()
|
||||
|
||||
# Load DMI header
|
||||
desc = self.img.info[b'Description'].decode('ascii')
|
||||
"""
|
||||
version = 4.0
|
||||
width = 32
|
||||
height = 32
|
||||
state = "fire"
|
||||
dirs = 4
|
||||
frames = 1
|
||||
state = "fire2"
|
||||
dirs = 1
|
||||
frames = 1
|
||||
state = "void"
|
||||
dirs = 4
|
||||
frames = 4
|
||||
delay = 2,2,2,2
|
||||
state = "void2"
|
||||
dirs = 1
|
||||
frames = 4
|
||||
delay = 2,2,2,2
|
||||
"""
|
||||
state = None
|
||||
x = 0
|
||||
y = 0
|
||||
self.statelist = desc
|
||||
ii = 0
|
||||
for line in desc.split("\n"):
|
||||
line = line.strip()
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
if '=' in line:
|
||||
(key, value) = line.split(' = ')
|
||||
key = key.strip()
|
||||
value = value.strip().replace('"', '')
|
||||
if key == 'version':
|
||||
self.version = value
|
||||
elif key == 'width':
|
||||
self.icon_width = int(value)
|
||||
self.max_x = self.img.size[0] / self.icon_width
|
||||
elif key == 'height':
|
||||
self.icon_height = int(value)
|
||||
self.max_y = self.img.size[1] / self.icon_height
|
||||
# print(('%s: {sz: %s,h: %d, w: %d, m_x: %d, m_y: %d}'%(self.filename,repr(img.size),self.icon_height,self.icon_width,self.max_x,self.max_y)))
|
||||
elif key == 'state':
|
||||
if state != None:
|
||||
# print(" + %s" % (state.ToString()))
|
||||
if(self.icon_width == 0 or self.icon_height == 0):
|
||||
if(len(self.states) > 0):
|
||||
raise SystemError("Width and height for each cell are not available.")
|
||||
else:
|
||||
self.icon_width = self.img.size[0]
|
||||
self.max_x = 1
|
||||
self.icon_height = self.img.size[1]
|
||||
self.max_y = 1
|
||||
elif(self.max_x == -1 or self.max_y == -1):
|
||||
self.max_x = self.img.size[0] / self.icon_width
|
||||
self.max_y = self.img.size[1] / self.icon_width
|
||||
for _ in range(state.numIcons()):
|
||||
state.positions += [(x, y)]
|
||||
if (flags & DMILoadFlags.NoImages) == 0:
|
||||
state.icons += [self.loadIconAt(x, y)]
|
||||
x += 1
|
||||
# print('%s[%d:%d] x=%d, max_x=%d' % (self.filename,ii,i,x,self.max_x))
|
||||
if(x >= self.max_x):
|
||||
x = 0
|
||||
y += 1
|
||||
self.states[state.key()] = state
|
||||
# if not suppress_post_process:
|
||||
# self.states[state.name].postProcess()
|
||||
ii += 1
|
||||
state = State(value)
|
||||
elif key == 'dirs':
|
||||
state.dirs = int(value)
|
||||
elif key == 'frames':
|
||||
state.frames = int(value)
|
||||
elif key == 'loop':
|
||||
state.loop = int(value)
|
||||
elif key == 'rewind':
|
||||
state.rewind = int(value)
|
||||
elif key == 'movement':
|
||||
state.movement = int(value)
|
||||
elif key == 'delay':
|
||||
state.delay = value.split(',')
|
||||
elif key == 'hotspot':
|
||||
state.hotspot = value
|
||||
else:
|
||||
logging.critical('Unknown key ' + key + ' (value=' + value + ')!')
|
||||
sys.exit()
|
||||
|
||||
self.states[state.name] = state
|
||||
for _ in range(state.numIcons()):
|
||||
self.states[state.name].icons += [self.loadIconAt(x, y)]
|
||||
x += 1
|
||||
if(x >= self.max_x):
|
||||
x = 0
|
||||
y += 1
|
||||
|
||||
def extractAllStates(self, dest, flags=0):
|
||||
for _, state in self.states.iteritems():
|
||||
# state = State()
|
||||
for i in xrange(len(state.positions)):
|
||||
x, y = state.positions[i]
|
||||
self.extractIconAt(state, dest, x, y, i)
|
||||
|
||||
if (flags & DMILoadFlags.NoPostProcessing) == 0:
|
||||
self.states[state.name].postProcess()
|
||||
if dest is not None:
|
||||
outfolder = os.path.join(dest, os.path.basename(self.filename))
|
||||
nfn = self.filename.replace('.dmi', '.dmih')
|
||||
valid_chars = "-_.()[] %s%s" % (string.ascii_letters, string.digits)
|
||||
nfn = ''.join(c for c in nfn if c in valid_chars)
|
||||
nfn = os.path.join(outfolder, nfn)
|
||||
with open(nfn, 'w') as dmih:
|
||||
dmih.write(self.getDMIH())
|
||||
|
||||
def loadIconAt(self, sx, sy):
|
||||
if(self.icon_width == 0 or self.icon_height == 0):
|
||||
raise SystemError('Image is {}x{}, an invalid size.'.format(self.icon_height, self.icon_width))
|
||||
# print(" X (%d,%d)"%(sx*self.icon_width,sy*self.icon_height))
|
||||
icon = Image.new(self.img.mode, (self.icon_width, self.icon_height))
|
||||
|
||||
newpix = icon.load()
|
||||
for y in range(self.icon_height):
|
||||
for x in range(self.icon_width):
|
||||
_x = x + (sx * self.icon_width)
|
||||
_y = y + (sy * self.icon_height)
|
||||
try:
|
||||
pixel = self.pixels[_x, _y]
|
||||
if pixel[3] == 0: continue
|
||||
newpix[x, y] = pixel
|
||||
except IndexError:
|
||||
print("!!! Received IndexError in %s <%d,%d> = <%d,%d> + (<%d,%d> * <%d,%d>), max=<%d,%d> halting." % (self.filename, _x, _y, x, y, sx, sy, self.icon_width, self.icon_height, self.max_x, self.max_y))
|
||||
print('%s: {sz: %s,h: %d, w: %d, m_x: %d, m_y: %d}' % (self.filename, repr(self.img.size), self.icon_height, self.icon_width, self.max_x, self.max_y))
|
||||
print('# of cells: %d' % len(self.states))
|
||||
print('Image h/w: %s' % repr(self.size))
|
||||
print('--STATES:--')
|
||||
print(self.statelist)
|
||||
sys.exit(1)
|
||||
return icon
|
||||
|
||||
def extractIconAt(self, state, dest, sx, sy, i=0):
|
||||
icon = self.loadIconAt(sx, sy)
|
||||
outfolder = os.path.join(dest, os.path.basename(self.filename))
|
||||
if not os.path.isdir(outfolder):
|
||||
os.makedirs(outfolder)
|
||||
nfn = "{}[{}].png".format(state.name, i)
|
||||
valid_chars = "-_.()[] %s%s" % (string.ascii_letters, string.digits)
|
||||
nfn = ''.join(c for c in nfn if c in valid_chars)
|
||||
nfn = os.path.join(outfolder, nfn)
|
||||
if os.path.isfile(nfn):
|
||||
os.remove(nfn)
|
||||
try:
|
||||
icon.save(nfn)
|
||||
except SystemError as e:
|
||||
print("Received SystemError, halting: %s" % traceback.format_exc(e))
|
||||
print('{ih=%d,iw=%d,state=%s,dest=%s,sx=%d,sy=%d,i=%d}' % (self.icon_height, self.icon_width, state.ToString(), dest, sx, sy, i))
|
||||
sys.exit(1)
|
||||
return nfn
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
|
||||
class Variable(object):
|
||||
name=''
|
||||
value=None
|
||||
|
||||
def __init__(self,name,value):
|
||||
self.name=name
|
||||
self.value=value
|
||||
@@ -1,135 +0,0 @@
|
||||
'''
|
||||
Created on Feb 23, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
|
||||
from . import directives, Variable
|
||||
|
||||
valid_symbol_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
|
||||
|
||||
class DMIH(object):
|
||||
"""
|
||||
# DMI Header 1.0
|
||||
# ------------------------
|
||||
|
||||
height = 32
|
||||
width = 32
|
||||
|
||||
state "AMAZIN' RAISINS" {
|
||||
dirtype=CARDINAL
|
||||
frames=5
|
||||
|
||||
import pngs {
|
||||
direction NORTH {
|
||||
"amazinraisin-N-0.png"
|
||||
"amazinraisin-N-1.png"
|
||||
"amazinraisin-N-2.png"
|
||||
"amazinraisin-N-3.png"
|
||||
"amazinraisin-N-4.png"
|
||||
}
|
||||
direction EAST {
|
||||
"amazinraisin-E-0.png"
|
||||
"amazinraisin-E-1.png"
|
||||
"amazinraisin-E-2.png"
|
||||
"amazinraisin-E-3.png"
|
||||
"amazinraisin-E-4.png"
|
||||
}
|
||||
direction WEST {
|
||||
"amazinraisin-W-0.png"
|
||||
"amazinraisin-W-1.png"
|
||||
"amazinraisin-W-2.png"
|
||||
"amazinraisin-W-3.png"
|
||||
"amazinraisin-W-4.png"
|
||||
}
|
||||
direction SOUTH {
|
||||
"amazinraisin-S-0.png"
|
||||
"amazinraisin-S-1.png"
|
||||
"amazinraisin-S-2.png"
|
||||
"amazinraisin-S-3.png"
|
||||
"amazinraisin-S-4.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# File State orig State new
|
||||
import dmi "import/ohgodwhy.dmi" "Oh god why" "metroid5"
|
||||
|
||||
"""
|
||||
|
||||
tokens = []
|
||||
|
||||
'''
|
||||
directive arg1 {block}
|
||||
'''
|
||||
directives = {
|
||||
'direction': directives.Direction.Direction,
|
||||
'import': directives.Import.Import,
|
||||
'state': directives.State.State
|
||||
}
|
||||
|
||||
def parse(self, file):
|
||||
with open(file) as f:
|
||||
self.tokens = self.parseBlockContents(f)
|
||||
|
||||
def readSymbol(self, f):
|
||||
f.seek(f.tell() - 1) # Back up one char
|
||||
o = ''
|
||||
while True:
|
||||
c = f.read(1)
|
||||
if c in valid_symbol_chars:
|
||||
o += c
|
||||
else:
|
||||
return o
|
||||
|
||||
def readString(self, f, b):
|
||||
# f.seek(f.tell()-1) # Back up one char
|
||||
o = ''
|
||||
while True:
|
||||
c = f.read(1)
|
||||
if c == b:
|
||||
return o
|
||||
else:
|
||||
o += c
|
||||
|
||||
def parseBlockContents(self, f):
|
||||
buf = ''
|
||||
currentBlock = []
|
||||
memory = []
|
||||
_in = None
|
||||
memchanged = False
|
||||
while True:
|
||||
b = f.read(1) # .decode('utf-8')
|
||||
if b in ('"', "'"):
|
||||
memory += [self.readString(f, b)]
|
||||
memchanged = True
|
||||
|
||||
if b in valid_symbol_chars:
|
||||
memory += [self.readSymbol(f)]
|
||||
f.seek(f.tell() - 1) # Back up one char in case we have to deal with a block.
|
||||
memchanged = True
|
||||
|
||||
if b == '=':
|
||||
memory += ['=']
|
||||
memchanged = True
|
||||
|
||||
if b == '{':
|
||||
memory += [self.parseBlockContents(f)]
|
||||
memchanged = True
|
||||
|
||||
if b == '}' or b == '': # End of block or end of file.
|
||||
return currentBlock
|
||||
|
||||
if memchanged:
|
||||
token = None
|
||||
if len(memory) == 3:
|
||||
if memory[2] == '=':
|
||||
token = Variable(memory[0], memory[1])
|
||||
if len(memory) > 0:
|
||||
if memory[0] in self.directives:
|
||||
token = self.directives[memory[0]](memory[0], memory[1:])
|
||||
if token:
|
||||
currentBlock += [token]
|
||||
memory = []
|
||||
memchanged = False
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
'''
|
||||
Created on Feb 23, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
from .Directive import Directive
|
||||
from byond import directions
|
||||
|
||||
class Direction(Directive):
|
||||
'''
|
||||
Tells the compiler which frames will be used for this direction.
|
||||
'''
|
||||
|
||||
'''
|
||||
Which direction?
|
||||
'''
|
||||
dir=0
|
||||
|
||||
'''
|
||||
List of files.
|
||||
'''
|
||||
frames=[]
|
||||
def __init__(self,name,frames):
|
||||
Directive.__init__(self, name, [name,frames])
|
||||
_dir = directions.getDirFromName(name)
|
||||
if _dir:
|
||||
self.dir=_dir
|
||||
self.frames=frames
|
||||
@@ -1,14 +0,0 @@
|
||||
'''
|
||||
Created on Feb 23, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
|
||||
class Directive(object):
|
||||
'''
|
||||
Base type for directives.
|
||||
'''
|
||||
name = ''
|
||||
|
||||
def __init__(self,name,args):
|
||||
self.name=name
|
||||
@@ -1,50 +0,0 @@
|
||||
'''
|
||||
Created on Feb 23, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
from .Directive import Directive
|
||||
|
||||
class Import(Directive):
|
||||
'''
|
||||
Tells the compiler to import a file into the DMI.
|
||||
'''
|
||||
|
||||
'''
|
||||
pngs or dmi.
|
||||
'''
|
||||
ftype=''
|
||||
|
||||
'''
|
||||
The file(s) to import into the DMI.
|
||||
'''
|
||||
filedef=None
|
||||
|
||||
'''
|
||||
State(s) to import (DMIs)
|
||||
'''
|
||||
states={}
|
||||
|
||||
def __init__(self,name,params):
|
||||
Directive.__init__(self,name,params)
|
||||
self.ftype=params[0]
|
||||
if self.ftype=='pngs':
|
||||
self.filedef=params[1]
|
||||
elif self.ftype=='dmi':
|
||||
self.filedef=str(params[1])
|
||||
if type(params[2]) is list:
|
||||
for sn in params[2]:
|
||||
self.addState(sn)
|
||||
elif type(params[2]) is str:
|
||||
self.addState(params[2])
|
||||
|
||||
def addState(self,sn):
|
||||
oldname=None
|
||||
newname=None
|
||||
snp=sn.split('->')
|
||||
if snp.len == 2:
|
||||
(oldname, newname)=snp
|
||||
elif snp.len == 1:
|
||||
oldname=newname=snp[0]
|
||||
if oldname and newname:
|
||||
self.states[oldname]=newname
|
||||
@@ -1,51 +0,0 @@
|
||||
'''
|
||||
Created on Feb 23, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
from .Directive import Directive
|
||||
from .Import import Import
|
||||
from byond.DMI import State
|
||||
from .. import Variable
|
||||
|
||||
directly_assignable={
|
||||
'hotspot':tuple,
|
||||
'dirs':int,
|
||||
'frames':int,
|
||||
'movement':int,
|
||||
'loop':int,
|
||||
'rewind':int,
|
||||
'delay':tuple
|
||||
}
|
||||
|
||||
class State(Directive):
|
||||
'''
|
||||
Tells the compiler to create a state with the specified variables and frames.
|
||||
'''
|
||||
|
||||
'''
|
||||
The actual state
|
||||
'''
|
||||
state = None
|
||||
imports = []
|
||||
def __init__(self,name,params):
|
||||
Directive.__init__(self,name,params)
|
||||
self.state=State()
|
||||
if params.len != 2:
|
||||
raise Exception('state directive requires 2 parameters. state "name" { }')
|
||||
self.state.name=params[0]
|
||||
for o in params[1]:
|
||||
if type(o) is Variable and o.name in directly_assignable:
|
||||
if o.name == 'dirs':
|
||||
if o.value == 'CARDINAL':
|
||||
o.value = 4
|
||||
elif o.value == 'ALL':
|
||||
o.value = 8
|
||||
else:
|
||||
o.value = 1
|
||||
setattr(self.state,o.name,directly_assignable[o.name](o.value))
|
||||
if type(o) is Import:
|
||||
if o.ftype == 'pngs':
|
||||
for dirblock in o.filedef:
|
||||
for i in range(dirblock.frames.len):
|
||||
self.state.setFrame(dirblock.dir, i, dirblock.frames[i])
|
||||
@@ -1,4 +0,0 @@
|
||||
from . import Direction, Directive, Import, State
|
||||
__all__ = [
|
||||
Direction, Directive, Import, State
|
||||
]
|
||||
@@ -1,41 +0,0 @@
|
||||
'''
|
||||
Created on Sep 21, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import os
|
||||
|
||||
from .map import Map, Tile, MapRenderFlags
|
||||
from .objtree import ObjectTree
|
||||
|
||||
def GetFilesFromDME(dmefile='baystation12.dme', ext='.dm'):
|
||||
filesInDME=[]
|
||||
rootdir = os.path.dirname(dmefile)
|
||||
with open(dmefile, 'r') as dmeh:
|
||||
for line in dmeh:
|
||||
if line.startswith('#include'):
|
||||
inString = False
|
||||
# escaped=False
|
||||
filename = ''
|
||||
for c in line:
|
||||
"""
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
if
|
||||
escaped = False
|
||||
continue
|
||||
"""
|
||||
if c == '"':
|
||||
inString = not inString
|
||||
if not inString:
|
||||
filepath = os.path.join(rootdir, filename)
|
||||
if filepath.endswith(ext):
|
||||
filesInDME += [filepath]
|
||||
filename = ''
|
||||
continue
|
||||
else:
|
||||
if inString:
|
||||
filename += c
|
||||
return filesInDME
|
||||
@@ -1,454 +0,0 @@
|
||||
'''
|
||||
Created on Nov 6, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
# import logging
|
||||
AREA_LAYER = 1
|
||||
TURF_LAYER = 2
|
||||
OBJ_LAYER = 3
|
||||
MOB_LAYER = 4
|
||||
FLY_LAYER = 5
|
||||
|
||||
import re
|
||||
from .utils import eval_expr
|
||||
REGEX_TABS = re.compile('^(?P<tabs>\t*)')
|
||||
class BYONDValue:
|
||||
"""
|
||||
Handles numbers and unhandled types like lists.
|
||||
"""
|
||||
def __init__(self, string, filename='', line=0, typepath='/', **kwargs):
|
||||
#: The actual value.
|
||||
self.value = string
|
||||
|
||||
#: Filename this was found in
|
||||
self.filename = filename
|
||||
|
||||
#: Line of the originating file.
|
||||
self.line = line
|
||||
|
||||
#: Typepath of the value.
|
||||
self.type = typepath
|
||||
|
||||
#: Has this value been inherited?
|
||||
self.inherited = kwargs.get('inherited', False)
|
||||
|
||||
#: Is this a declaration? (/var)
|
||||
self.declaration = kwargs.get('declaration', False)
|
||||
|
||||
#: Anything special? (global, const, etc.)
|
||||
self.special = kwargs.get('special', None)
|
||||
|
||||
#: If a list, what's the size?
|
||||
self.size = kwargs.get('size', None)
|
||||
|
||||
def copy(self):
|
||||
'''Make a clone of this without dangling references.'''
|
||||
return BYONDValue(self.value, self.filename, self.line, self.type, declaration=self.declaration, inherited=self.inherited, special=self.special)
|
||||
|
||||
def __str__(self):
|
||||
return '{0}'.format(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return '<BYONDValue value="{}" filename="{}" line={}>'.format(self.value, self.filename, self.line)
|
||||
|
||||
def DumpCode(self, name):
|
||||
'''
|
||||
Try to dump valid BYOND code for this variable.
|
||||
|
||||
.. :param name: The name of this variable.
|
||||
'''
|
||||
decl = []
|
||||
if self.declaration:
|
||||
decl += ['var']
|
||||
if self.type != '/' and self.declaration:
|
||||
decl += self.type.split('/')[1:]
|
||||
decl += [name]
|
||||
constructed = '/'.join(decl)
|
||||
if self.value is not None:
|
||||
constructed += ' = {0}'.format(str(self))
|
||||
return constructed
|
||||
|
||||
class BYONDFileRef(BYONDValue):
|
||||
"""
|
||||
Just to format file references differently.
|
||||
"""
|
||||
def __init__(self, string, filename='', line=0, **kwargs):
|
||||
BYONDValue.__init__(self, string, filename, line, '/icon', **kwargs)
|
||||
|
||||
def copy(self):
|
||||
return BYONDFileRef(self.value, self.filename, self.line, declaration=self.declaration, inherited=self.inherited, special=self.special)
|
||||
|
||||
def __str__(self):
|
||||
return "'{0}'".format(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return '<BYONDFileRef value="{}" filename="{}" line={}>'.format(self.value, self.filename, self.line)
|
||||
|
||||
class BYONDString(BYONDValue):
|
||||
"""
|
||||
Correctly formats strings.
|
||||
"""
|
||||
def __init__(self, string, filename='', line=0, **kwargs):
|
||||
BYONDValue.__init__(self, string, filename, line, '/', **kwargs)
|
||||
|
||||
def copy(self):
|
||||
return BYONDString(self.value, self.filename, self.line, declaration=self.declaration, inherited=self.inherited, special=self.special)
|
||||
|
||||
def __str__(self):
|
||||
return '"{0}"'.format(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return '<BYONDString value="{}" filename="{}" line={}>'.format(self.value, self.filename, self.line)
|
||||
|
||||
class PropertyFlags:
|
||||
'''Collection of flags that affect :func:`Atom.setProperty` behavior.'''
|
||||
|
||||
#: Property being set should be saved to the map
|
||||
MAP_SPECIFIED = 1
|
||||
|
||||
#: Property being set should be handled as a string
|
||||
STRING = 2
|
||||
|
||||
#: Property being set should be handled as a file reference
|
||||
FILEREF = 4
|
||||
|
||||
#: Property being set should be handled as a value
|
||||
VALUE = 8
|
||||
|
||||
class Atom:
|
||||
'''
|
||||
An atom is, in simple terms, what BYOND considers a class.
|
||||
|
||||
:param string path:
|
||||
The absolute path of this atom. ex: */obj/item/weapon/gun*
|
||||
:param string filename:
|
||||
The file this atom originated from.
|
||||
:param int line:
|
||||
The line in the aforementioned file.
|
||||
'''
|
||||
|
||||
#: Prints all inherited properties, not just the ones that are mapSpecified.
|
||||
FLAG_INHERITED_PROPERTIES = 1
|
||||
|
||||
#: writeMap2 prints old_ids instead of the actual IID.
|
||||
FLAG_USE_OLD_ID = 2
|
||||
|
||||
def __init__(self, path, filename='', line=0, **kwargs):
|
||||
global TURF_LAYER, AREA_LAYER, OBJ_LAYER, MOB_LAYER
|
||||
|
||||
#: Absolute path of this atom
|
||||
self.path = path
|
||||
|
||||
#: Vars of this atom, including inherited vars.
|
||||
self.properties = {}
|
||||
|
||||
#: List of var names that were specified by the map, if atom was loaded from a :class:`byond.map.Map`.
|
||||
self.mapSpecified = []
|
||||
|
||||
#: Child atoms and procs.
|
||||
self.children = {}
|
||||
|
||||
#: The parent of this atom.
|
||||
self.parent = None
|
||||
|
||||
#: The file this atom originated from.
|
||||
self.filename = filename
|
||||
|
||||
#: Line from the originating file.
|
||||
self.line = line
|
||||
|
||||
#: Instance ID (maps only). Used internally, do NOT change.
|
||||
self.id = None
|
||||
|
||||
#: Instance ID that was read from the map.
|
||||
self.old_id = None
|
||||
|
||||
#: Used internally.
|
||||
self.ob_inherited=False
|
||||
|
||||
#: Loaded from map, but missing in the code. (Maps only)
|
||||
self.missing=kwargs.get('missing',False)
|
||||
|
||||
#if not self.missing and path == '/area/engine/engineering':
|
||||
# raise Exception('God damnit')
|
||||
def copy(self):
|
||||
'''
|
||||
Make a copy of this atom, without dangling references.
|
||||
|
||||
:returns byond.basetypes.Atom
|
||||
'''
|
||||
new_node = Atom(self.path,self.filename,self.line,missing=self.missing)
|
||||
new_node.properties = self.properties.copy()
|
||||
new_node.mapSpecified = self.mapSpecified
|
||||
new_node.id = self.id
|
||||
new_node.old_id = self.old_id
|
||||
# new_node.parent = self.parent
|
||||
return new_node
|
||||
|
||||
def getProperty(self, index, default=None):
|
||||
'''
|
||||
Get the value of the specified property.
|
||||
|
||||
:param string index:
|
||||
The name of the var we want.
|
||||
:param mixed default:
|
||||
Default value, if the var cannot be found.
|
||||
:returns:
|
||||
The desired value.
|
||||
'''
|
||||
prop = self.properties.get(index, None)
|
||||
if prop == None:
|
||||
return default
|
||||
elif prop == 'null':
|
||||
return None
|
||||
return prop.value
|
||||
|
||||
def setProperty(self, index, value, flags=0):
|
||||
'''
|
||||
Set the value of a property.
|
||||
|
||||
In the event the property cannot be found, a new property is added.
|
||||
|
||||
This function will attempt to convert python types to BYOND types.
|
||||
Hints can be provided in the form of PropertyFlags given to *flags*.
|
||||
|
||||
:param string index:
|
||||
The name of the var desired.
|
||||
:param mixed value:
|
||||
The new value.
|
||||
:param int flags:
|
||||
Changes value assignment behavior.
|
||||
|
||||
+------------------------------------+------------------------------------------------+
|
||||
| Flag | Effect |
|
||||
+====================================+================================================+
|
||||
| :attr:`PropertyFlag.MAP_SPECIFIED` | Adds the property to *mapSpecified*, if needed.|
|
||||
+------------------------------------+------------------------------------------------+
|
||||
| :attr:`PropertyFlag.STRING` | Forces conversion of value to a BYONDString. |
|
||||
+------------------------------------+------------------------------------------------+
|
||||
| :attr:`PropertyFlag.FILEREF` | Forces conversion of value to a BYONDFileRef. |
|
||||
+------------------------------------+------------------------------------------------+
|
||||
| :attr:`PropertyFlag.VALUE` | Forces conversion of value to a BYONDValue. |
|
||||
+------------------------------------+------------------------------------------------+
|
||||
|
||||
:returns:
|
||||
The desired value.
|
||||
'''
|
||||
if flags & PropertyFlags.MAP_SPECIFIED:
|
||||
if index not in self.mapSpecified:
|
||||
self.mapSpecified += [index]
|
||||
if flags & PropertyFlags.VALUE:
|
||||
self.properties[index] = BYONDValue(value)
|
||||
elif isinstance(value, str) or flags & PropertyFlags.STRING:
|
||||
if flags & PropertyFlags.STRING:
|
||||
value = str(value)
|
||||
self.properties[index] = BYONDString(value)
|
||||
elif flags & PropertyFlags.FILEREF:
|
||||
if flags & PropertyFlags.FILEREF:
|
||||
value = str(value)
|
||||
self.properties[index] = BYONDFileRef(value)
|
||||
else:
|
||||
self.properties[index] = BYONDValue(value)
|
||||
|
||||
def InheritProperties(self):
|
||||
if self.ob_inherited: return
|
||||
#debugInheritance=self.path in ('/area','/obj','/mob','/atom/movable','/atom')
|
||||
if self.parent:
|
||||
if not self.parent.ob_inherited:
|
||||
self.parent.InheritProperties()
|
||||
for key in sorted(self.parent.properties.keys()):
|
||||
value = self.parent.properties[key].copy()
|
||||
if key not in self.properties:
|
||||
self.properties[key] = value
|
||||
self.properties[key].inherited = True
|
||||
#if debugInheritance:print(' {0}[{2}] -> {1}'.format(self.parent.path,self.path,key))
|
||||
#assert 'name' in self.properties
|
||||
self.ob_inherited=True
|
||||
for k in self.children.iterkeys():
|
||||
self.children[k].InheritProperties()
|
||||
|
||||
def __ne__(self, atom):
|
||||
return not self.__eq__(atom)
|
||||
|
||||
def __eq__(self, atom):
|
||||
if atom == None:
|
||||
return False
|
||||
if self.mapSpecified != atom.mapSpecified:
|
||||
return False
|
||||
if self.path != atom.path:
|
||||
return False
|
||||
return self.properties == atom.properties
|
||||
|
||||
def handle_math(self,expr):
|
||||
if isinstance(expr,str):
|
||||
return eval_expr(expr)
|
||||
return expr
|
||||
|
||||
def __lt__(self, other):
|
||||
if 'layer' not in self.properties or 'layer' not in other.properties:
|
||||
return False
|
||||
myLayer = 0
|
||||
otherLayer = 0
|
||||
try:
|
||||
myLayer = self.handle_math(self.getProperty('layer',myLayer))
|
||||
except ValueError:
|
||||
print('Failed to parse {0} as float.'.format(self.properties['layer'].value))
|
||||
pass
|
||||
try:
|
||||
otherLayer = self.handle_math(other.getProperty('layer',otherLayer))
|
||||
except ValueError:
|
||||
print('Failed to parse {0} as float.'.format(other.properties['layer'].value))
|
||||
pass
|
||||
return myLayer > otherLayer
|
||||
|
||||
def __gt__(self, other):
|
||||
if 'layer' not in self.properties or 'layer' not in other.properties:
|
||||
return False
|
||||
myLayer = 0
|
||||
otherLayer = 0
|
||||
try:
|
||||
myLayer = self.handle_math(self.getProperty('layer',myLayer))
|
||||
except ValueError:
|
||||
print('Failed to parse {0} as float.'.format(self.properties['layer'].value))
|
||||
pass
|
||||
try:
|
||||
otherLayer = self.handle_math(other.getProperty('layer',otherLayer))
|
||||
except ValueError:
|
||||
print('Failed to parse {0} as float.'.format(other.properties['layer'].value))
|
||||
pass
|
||||
return myLayer < otherLayer
|
||||
|
||||
def MapSerialize(self, flags=0):
|
||||
atomContents = []
|
||||
# print(repr(self.mapSpecified))
|
||||
if (flags & Atom.FLAG_INHERITED_PROPERTIES):
|
||||
for key, val in self.properties.items():
|
||||
atomContents += ['{0} = {1}'.format(key, val)]
|
||||
else:
|
||||
for i in range(len(self.mapSpecified)):
|
||||
key = self.mapSpecified[i]
|
||||
if key in self.properties:
|
||||
val = self.properties[key]
|
||||
atomContents += ['{0} = {1}'.format(key, val)]
|
||||
if len(atomContents) > 0:
|
||||
return self.path + '{' + '; '.join(atomContents) + '}'
|
||||
else:
|
||||
return self.path
|
||||
|
||||
def dumpPropInfo(self, name):
|
||||
o = '{0}: '.format(name)
|
||||
if name not in self.properties:
|
||||
return o + 'None'
|
||||
return o + repr(self.properties[name])
|
||||
|
||||
def _DumpCode(self):
|
||||
divider = '//' + ((len(self.path) + 2) * '/') + '\n'
|
||||
o = divider
|
||||
o += '// ' + self.path + '\n'
|
||||
o += divider
|
||||
o += self.path + '\n'
|
||||
# o += '\t//{0} properties total\n'.format(len(self.properties))
|
||||
for name in sorted(self.properties.keys()):
|
||||
prop = self.properties[name]
|
||||
if prop.inherited: continue
|
||||
_type = prop.type
|
||||
if not _type.endswith('/'):
|
||||
_type += '/'
|
||||
prefix = ''
|
||||
if prop.declaration:
|
||||
prefix = 'var'
|
||||
if not prop.declaration: # and _type == '/':
|
||||
_type = ''
|
||||
o += '\t{prefix}{type}{name}'.format(prefix=prefix, type=_type, name=name)
|
||||
if prop.value is not None:
|
||||
o += ' = {value}'.format(value=str(prop))
|
||||
o += '\n'
|
||||
|
||||
# o += '\n'
|
||||
# o += '\t//{0} children total\n'.format(len(self.children))
|
||||
procs = ''
|
||||
children = ''
|
||||
for ck in sorted(self.children.keys()):
|
||||
co = '\n'
|
||||
co += self.children[ck]._DumpCode()
|
||||
if isinstance(self.children[ck], Proc):
|
||||
procs += co
|
||||
else:
|
||||
children += co
|
||||
o += procs + children
|
||||
return o
|
||||
|
||||
def DumpCode(self):
|
||||
return self._DumpCode()
|
||||
|
||||
class Proc(Atom):
|
||||
def __init__(self, path, arguments, filename='', line=0):
|
||||
Atom.__init__(self, path, filename, line)
|
||||
self.name = self.figureOutName(self.path)
|
||||
self.arguments = arguments
|
||||
self.code = [] # (indent, line)
|
||||
self.definition = False
|
||||
self.origpath = ''
|
||||
|
||||
def figureOutName(self,path):
|
||||
name = path.split('(')[0]
|
||||
return name.split('/')[-1]
|
||||
|
||||
def CountTabs(self, line):
|
||||
m = REGEX_TABS.match(line)
|
||||
if m is not None:
|
||||
return len(m.group('tabs'))
|
||||
return 0
|
||||
|
||||
def AddCode(self, indentLevel, line):
|
||||
self.code += [(indentLevel, line)]
|
||||
|
||||
def AddBlankLine(self):
|
||||
if len(self.code) > 0 and self.code[-1][1] == '':
|
||||
return
|
||||
self.code += [(0, '')]
|
||||
|
||||
def MapSerialize(self, flags=0):
|
||||
return None
|
||||
|
||||
def InheritProperties(self):
|
||||
return
|
||||
def getMinimumIndent(self):
|
||||
# Find minimum indent level
|
||||
for i in range(len(self.code)):
|
||||
indent, _ = self.code[i]
|
||||
if indent == 0: continue
|
||||
return indent
|
||||
return 0
|
||||
|
||||
def _DumpCode(self):
|
||||
args = self.path[self.path.index('('):]
|
||||
true_path = self.path[:self.path.index('(')].split('/')
|
||||
name = true_path[-1]
|
||||
true_path = true_path[:-1]
|
||||
if self.definition:
|
||||
true_path += ['proc']
|
||||
true_path += [name + args]
|
||||
o = '\n' + '/'.join(true_path) + '\n'
|
||||
min_indent = self.getMinimumIndent()
|
||||
# Should be 1, so find the difference.
|
||||
indent_delta = 1 - min_indent
|
||||
# o += '\t// true_path = {0}\n'.format(repr(true_path))
|
||||
# o += '\t// name = {0}\n'.format(name)
|
||||
# o += '\t// args = {0}\n'.format(args)
|
||||
# o += '\t// definition = {0}\n'.format(self.definition)
|
||||
# o += '\t// path = {0}\n'.format(self.path[:self.path.index('(')])
|
||||
# o += '\t// origpath = {0}\n'.format(self.origpath)
|
||||
# o += '\t// min_indent = {0}\n'.format(min_indent)
|
||||
# o += '\t// indent_delta = {0}\n'.format(indent_delta)
|
||||
for i in range(len(self.code)):
|
||||
indent, code = self.code[i]
|
||||
indent = max(1, indent + indent_delta)
|
||||
if code == '' and i == len(self.code) - 1:
|
||||
continue
|
||||
if code.strip() == '':
|
||||
o += '\n'
|
||||
else:
|
||||
o += (indent * '\t') + code.strip() + '\n'
|
||||
return o
|
||||
@@ -1,47 +0,0 @@
|
||||
'''
|
||||
Created on Feb 23, 2013
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import sys
|
||||
# NORTH, SOUTH, EAST, and WEST are just #define statements built in DM.
|
||||
# They represent 1, 2, 4, and 8
|
||||
|
||||
NORTH = 1
|
||||
SOUTH = 2
|
||||
EAST = 4
|
||||
WEST = 8
|
||||
|
||||
IMAGE_INDICES=[
|
||||
SOUTH,
|
||||
NORTH,
|
||||
EAST,
|
||||
WEST,
|
||||
(SOUTH|EAST),
|
||||
(SOUTH|WEST),
|
||||
(NORTH|EAST),
|
||||
(NORTH|WEST)
|
||||
]
|
||||
|
||||
def getDirFromName(name):
|
||||
return getattr(sys.modules[__name__],name,None)
|
||||
|
||||
def getNameFromDir(_dir):
|
||||
if _dir == NORTH:
|
||||
return 'NORTH'
|
||||
elif _dir == SOUTH:
|
||||
return 'SOUTH'
|
||||
elif _dir == EAST:
|
||||
return 'EAST'
|
||||
elif _dir == WEST:
|
||||
return 'WEST'
|
||||
elif _dir == (NORTH|WEST):
|
||||
return 'NORTHWEST'
|
||||
elif _dir == (NORTH|EAST):
|
||||
return 'NORTHEAST'
|
||||
elif _dir == (SOUTH|EAST):
|
||||
return 'SOUTHEAST'
|
||||
elif _dir == (SOUTH|WEST):
|
||||
return 'SOUTHWEST'
|
||||
else:
|
||||
return 'UNKNOWN (%d)' %_dir
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
||||
import logging, glob, os, sys
|
||||
from .base import MapFix, GetDependencies
|
||||
|
||||
def Load():
|
||||
print('Loading MapFix Modules...')
|
||||
for f in glob.glob(os.path.dirname(__file__) + "/*.py"):
|
||||
modName = 'mapfixes.' + os.path.basename(f)[:-3]
|
||||
print(' Loading module ' + modName)
|
||||
mod = __import__(modName)
|
||||
for attr in dir(mod):
|
||||
if not attr.startswith('_'):
|
||||
#print(' {} = {}'.format(attr,getattr(mod, attr)))
|
||||
globals()[attr] = getattr(mod, attr)
|
||||
|
||||
def GetFixesForNS(namespaces, load_dependencies=True):
|
||||
selected = [None] + namespaces
|
||||
depends = GetDependencies()
|
||||
if load_dependencies:
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
for cat in selected:
|
||||
if cat is None: continue # Global namespace is always needed.
|
||||
print('Checking dependencies for {}...'.format(cat))
|
||||
if cat in depends:
|
||||
for newcat in depends[cat]:
|
||||
if newcat not in selected:
|
||||
print('Selected dependency {} (required by {})'.format(newcat,cat))
|
||||
selected += [newcat]
|
||||
changed = True
|
||||
o = []
|
||||
for cat in selected:
|
||||
for _, val in MapFix.all[cat].items():
|
||||
o += [val()]
|
||||
return o
|
||||
@@ -1,150 +0,0 @@
|
||||
'''
|
||||
Global BYOND fixes and matchers
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import logging
|
||||
from byond.basetypes import BYONDString, BYONDValue
|
||||
# from byond.directions import *
|
||||
|
||||
# Decorator
|
||||
class MapFix(object):
|
||||
all = {}
|
||||
def __init__(self, category, _id=None):
|
||||
self.id = _id
|
||||
self.category = category
|
||||
def __call__(self, c):
|
||||
if self.id is None:
|
||||
fname_p = c.__name__
|
||||
self.id = fname_p
|
||||
print('Adding MapFix {0}-{1}.'.format(self.category, self.id))
|
||||
if self.category not in MapFix.all:
|
||||
MapFix.all[self.category] = {}
|
||||
MapFix.all[self.category][self.id] = c
|
||||
return c
|
||||
|
||||
_dependencies = {}
|
||||
|
||||
def DeclareDependencies(dependee, dependencies):
|
||||
if dependee not in _dependencies:
|
||||
_dependencies[dependee] = []
|
||||
_dependencies[dependee] += dependencies
|
||||
print(' Dependencies: {}'.format(dependencies))
|
||||
|
||||
def GetDependencies():
|
||||
return _dependencies
|
||||
|
||||
class Matcher:
|
||||
def Matches(self, atom):
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
return atom
|
||||
|
||||
def SetTree(self, tree):
|
||||
self.tree = tree
|
||||
|
||||
@MapFix(None)
|
||||
class NukeTags(Matcher):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def Matches(self, atom):
|
||||
return 'tag' in atom.properties and 'tag' in atom.mapSpecified
|
||||
|
||||
def Fix(self, atom):
|
||||
atom.mapSpecified.remove('tag')
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Removed tag'
|
||||
|
||||
class RenameProperty(Matcher):
|
||||
'''
|
||||
Generic property renamer.
|
||||
'''
|
||||
|
||||
def __init__(self, old, new):
|
||||
self.old = old
|
||||
self.new = new
|
||||
self.removed = False
|
||||
|
||||
def Matches(self, atom):
|
||||
if self.old in atom.properties and self.old in atom.mapSpecified:
|
||||
return True
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
if self.new not in atom.properties: # Defer to the correct one if both exist.
|
||||
atom.properties[self.new] = atom.properties[self.old]
|
||||
if self.old in atom.mapSpecified:
|
||||
if self.new not in atom.mapSpecified:
|
||||
atom.mapSpecified += [self.new]
|
||||
else:
|
||||
self.removed = True
|
||||
atom.mapSpecified.remove(self.old)
|
||||
del atom.properties[self.old]
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
if self.removed:
|
||||
return 'Removed {0}'.format(self.old)
|
||||
else:
|
||||
return 'Renamed {0} to {1}'.format(self.old, self.new)
|
||||
|
||||
class ChangeType(Matcher):
|
||||
def __init__(self, old, new, forcetype=False, fuzzy=False):
|
||||
self.old = old
|
||||
self.new = new
|
||||
self.forcetype = forcetype
|
||||
self.fuzzy = fuzzy
|
||||
|
||||
def Matches(self, atom):
|
||||
matches = False
|
||||
if self.fuzzy:
|
||||
matches = atom.path.startswith(self.old)
|
||||
if matches:
|
||||
self.new += atom.path[len(self.old):]
|
||||
self.old = atom.path
|
||||
#print('{} -> {}'.format(self.old,self.new))
|
||||
else:
|
||||
matches = self.old == atom.path
|
||||
if matches:
|
||||
if atom.missing:
|
||||
return True
|
||||
else:
|
||||
logging.warn('[{}] Found type, but marked not missing: {}'.format(self.__class__.__name__,atom.path))
|
||||
logging.warn('{}:{}: Target type found here'.format(atom.filename, atom.line))
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
atom.path = self.new
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Change type from {0} to {1}'.format(self.old, self.new)
|
||||
|
||||
@MapFix(None)
|
||||
class FixStepX(RenameProperty):
|
||||
def __init__(self):
|
||||
RenameProperty.__init__(self, 'step_x', 'pixel_x')
|
||||
|
||||
@MapFix(None)
|
||||
class FixStepY(RenameProperty):
|
||||
def __init__(self):
|
||||
RenameProperty.__init__(self, 'step_y', 'pixel_y'),
|
||||
|
||||
@MapFix(None)
|
||||
class RepairDirections(Matcher):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def Matches(self, atom):
|
||||
return 'dir' in atom.properties and 'dir' in atom.mapSpecified and isinstance(atom.properties['dir'], BYONDString)
|
||||
|
||||
def Fix(self, atom):
|
||||
atom.setProperty('dir', int(atom.getProperty('dir')))
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Repaired direction type'
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
from .base import Matcher,MapFix
|
||||
from byond.basetypes import BYONDString, BYONDValue, Atom, PropertyFlags
|
||||
from byond.directions import *
|
||||
|
||||
@MapFix('ss13')
|
||||
class StandardizeAPCs(Matcher):
|
||||
ACT_CLEAR_NAME = 1
|
||||
ACT_FIX_OFFSET = 2
|
||||
def __init__(self):
|
||||
self.actions = 0
|
||||
self.pixel_x = 0
|
||||
self.pixel_y = 0
|
||||
|
||||
def Matches(self, atom):
|
||||
self.actions = 0
|
||||
if atom.path == '/obj/machinery/power/apc':
|
||||
# Determine if this APC is pretty close to standard-issue (no weird permissions, etc).
|
||||
nonstandard_settings = []
|
||||
for setting in atom.mapSpecified:
|
||||
if setting not in ('name', 'pixel_x', 'pixel_y', 'tag', 'dir'):
|
||||
nonstandard_settings += [setting]
|
||||
if len(nonstandard_settings) > 0:
|
||||
print('Non-standard APC #{}: Has strange settings - {}'.format(atom.id,', '.join(nonstandard_settings)))
|
||||
else:
|
||||
if 'name' in atom.properties and 'name' in atom.mapSpecified:
|
||||
self.actions |= self.ACT_CLEAR_NAME
|
||||
|
||||
direction = int(atom.getProperty('dir', 2))
|
||||
self.pixel_x = 0
|
||||
self.pixel_y = 0
|
||||
c_pixel_x = atom.getProperty('pixel_x', 0)
|
||||
c_pixel_y = atom.getProperty('pixel_y', 0)
|
||||
if (direction & 3):
|
||||
self.pixel_x = 0
|
||||
if(direction == 1):
|
||||
self.pixel_y = 24
|
||||
else:
|
||||
self.pixel_y = -24
|
||||
else:
|
||||
self.pixel_y = 0
|
||||
if(direction == 4):
|
||||
self.pixel_x = 24
|
||||
else:
|
||||
self.pixel_x = -24
|
||||
if self.pixel_x != c_pixel_x or self.pixel_y != c_pixel_y:
|
||||
self.actions |= self.ACT_FIX_OFFSET
|
||||
return self.actions != 0
|
||||
|
||||
def Fix(self, atom):
|
||||
if self.actions & self.ACT_CLEAR_NAME:
|
||||
atom.mapSpecified.remove('name')
|
||||
if self.actions & self.ACT_FIX_OFFSET:
|
||||
atom.setProperty('pixel_x', self.pixel_x, PropertyFlags.MAP_SPECIFIED)
|
||||
atom.setProperty('pixel_y', self.pixel_y, PropertyFlags.MAP_SPECIFIED)
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
if self.actions == 0:
|
||||
return 'APC Standardization'
|
||||
descr = []
|
||||
if self.actions & self.ACT_CLEAR_NAME:
|
||||
descr += ['Cleared name property']
|
||||
if self.actions & self.ACT_FIX_OFFSET:
|
||||
descr += ['Set pixel offset to {0},{1}'.format(self.pixel_x, self.pixel_y)]
|
||||
return 'Standardized APC: ' + ', '.join(descr)
|
||||
@@ -1,311 +0,0 @@
|
||||
'''
|
||||
/vg/station-specific fixes.
|
||||
'''
|
||||
|
||||
from .base import Matcher,MapFix,RenameProperty,DeclareDependencies,ChangeType
|
||||
from byond.basetypes import BYONDString, BYONDValue, Atom, PropertyFlags
|
||||
from byond.directions import *
|
||||
|
||||
DeclareDependencies('vgstation',['ss13'])
|
||||
|
||||
@MapFix('vgstation')
|
||||
class FixNetwork(Matcher):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def Matches(self, atom):
|
||||
if atom.path.startswith('/obj/machinery/camera') and 'network' in atom.properties:
|
||||
return isinstance(atom.properties['network'], BYONDString) and not atom.properties['network'].value.startswith('list(')
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
fix = atom.properties['network'].value
|
||||
atom.properties['network'] = BYONDValue('list("{0}")'.format(fix))
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Changed network property to list'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class NetworkingChangeAtmos(ChangeType):
|
||||
def __init__(self):
|
||||
ChangeType.__init__(self,'/obj/machinery/atmospherics','/obj/machinery/networked/atmos', fuzzy = True)
|
||||
|
||||
@MapFix('vgstation')
|
||||
class NetworkingChangePower(ChangeType):
|
||||
def __init__(self):
|
||||
ChangeType.__init__(self,'/obj/machinery/power','/obj/machinery/networked/power', fuzzy = True)
|
||||
|
||||
@MapFix('vgstation')
|
||||
class NetworkingChangeFiber(ChangeType):
|
||||
def __init__(self):
|
||||
ChangeType.__init__(self,'/obj/machinery/fiber','/obj/machinery/networked/fiber', fuzzy = True)
|
||||
|
||||
|
||||
class FixIDTags(Matcher):
|
||||
atomsToFix={}
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def Matches(self, atom):
|
||||
global atomsToFix
|
||||
if 'id_tag' in atom.properties:
|
||||
compiled_atom = self.tree.GetAtom(atom.path)
|
||||
if compiled_atom is None: return False
|
||||
if 'id_tag' not in compiled_atom.properties:
|
||||
FixIDTags.atomsToFix[atom.path] = True
|
||||
return 'id' in atom.properties and 'id' in atom.mapSpecified
|
||||
# return False
|
||||
|
||||
def Fix(self, atom):
|
||||
_id = atom.properties['id']
|
||||
id_idx = atom.mapSpecified.index('id')
|
||||
atom.properties['id_tag'] = _id
|
||||
del atom.properties['id']
|
||||
atom.mapSpecified[id_idx] = 'id_tag'
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Renamed id to id_tag'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class StandardizeManifolds(Matcher):
|
||||
STATE_TO_TYPE = {
|
||||
'manifold-b' :'/obj/machinery/networked/atmos/pipe/manifold/supply/visible',
|
||||
'manifold-b-f':'/obj/machinery/networked/atmos/pipe/manifold/supply/hidden',
|
||||
'manifold-r' :'/obj/machinery/networked/atmos/pipe/manifold/scrubbers/visible',
|
||||
'manifold-r-f':'/obj/machinery/networked/atmos/pipe/manifold/scrubbers/hidden',
|
||||
'manifold-c' :'/obj/machinery/networked/atmos/pipe/manifold/cyan/visible',
|
||||
'manifold-c-f':'/obj/machinery/networked/atmos/pipe/manifold/cyan/hidden',
|
||||
'manifold-y' :'/obj/machinery/networked/atmos/pipe/manifold/yellow/visible',
|
||||
'manifold-y-f':'/obj/machinery/networked/atmos/pipe/manifold/yellow/hidden',
|
||||
'manifold-g' :'/obj/machinery/networked/atmos/pipe/manifold/filtering/visible',
|
||||
'manifold-g-f':'/obj/machinery/networked/atmos/pipe/manifold/filtering/hidden',
|
||||
'manifold' :'/obj/machinery/networked/atmos/pipe/manifold/general/visible',
|
||||
'manifold-f' :'/obj/machinery/networked/atmos/pipe/manifold/general/hidden',
|
||||
}
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def Matches(self, atom):
|
||||
if atom.path == '/obj/machinery/networked/atmos/pipe/manifold' and 'icon_state' in atom.mapSpecified:
|
||||
return atom.getProperty('icon_state') in self.STATE_TO_TYPE
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
icon_state = atom.properties['icon_state'].value
|
||||
new_atom = Atom(self.STATE_TO_TYPE[icon_state])
|
||||
if 'dir' in atom.mapSpecified:
|
||||
new_atom.setProperty('dir', atom.getProperty('dir'), PropertyFlags.MAP_SPECIFIED)
|
||||
return new_atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Standardized pipe manifold'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class StandardizePiping(Matcher):
|
||||
TYPE_TRANSLATIONS = {
|
||||
'/obj/machinery/networked/atmos/pipe/simple': 'simple',
|
||||
'/obj/machinery/networked/atmos/pipe/manifold': 'manifold',
|
||||
'/obj/machinery/networked/atmos/pipe/manifold4w': 'manifold4w',
|
||||
}
|
||||
COLOR_CODES = {
|
||||
'b':'supply',
|
||||
'r':'scrubbers',
|
||||
'g':'filtering',
|
||||
'c':'cyan',
|
||||
'y':'yellow',
|
||||
'': 'general'
|
||||
}
|
||||
def __init__(self):
|
||||
self.before = None
|
||||
self.after = None
|
||||
return
|
||||
|
||||
def trans_simple(self, atom):
|
||||
type_tmpl = '/obj/machinery/networked/atmos/pipe/simple/{color}/{visibility}'
|
||||
color_code, visible = self.parseIconState(atom.getProperty('icon_state', ''))
|
||||
return self.getNewType(type_tmpl, color_code, visible)
|
||||
|
||||
def trans_manifold(self, atom):
|
||||
type_tmpl = '/obj/machinery/networked/atmos/pipe/manifold/{color}/{visibility}'
|
||||
color_code, visible = self.parseIconState(atom.getProperty('icon_state', ''))
|
||||
return self.getNewType(type_tmpl, color_code, visible)
|
||||
|
||||
def trans_manifold4w(self, atom):
|
||||
type_tmpl = '/obj/machinery/networked/atmos/pipe/manifold4w/{color}/{visibility}'
|
||||
color_code, visible = self.parseIconState(atom.getProperty('icon_state', ''))
|
||||
return self.getNewType(type_tmpl, color_code, visible)
|
||||
|
||||
def parseIconState(self, state):
|
||||
parts = state.split('-')
|
||||
if len(parts) <= 1:
|
||||
return ('', True)
|
||||
elif len(parts) == 2:
|
||||
if parts[1] == 'f':
|
||||
return ('', True)
|
||||
return (parts[1], True)
|
||||
return (parts[1], parts[2] != 'f')
|
||||
|
||||
def getNewType(self, tmpl, color_code, visible, color_wheel=COLOR_CODES):
|
||||
visibility = 'visible'
|
||||
if not visible:
|
||||
visibility = 'hidden'
|
||||
color = color_wheel[color_code]
|
||||
return Atom(tmpl.format(color=color, visibility=visibility))
|
||||
|
||||
def Matches(self, atom):
|
||||
return atom.path in self.TYPE_TRANSLATIONS
|
||||
|
||||
def Fix(self, atom):
|
||||
self.before = atom.MapSerialize()
|
||||
old_dir = None
|
||||
if 'dir' in atom.mapSpecified:
|
||||
old_dir = int(atom.getProperty('dir', 2))
|
||||
atom = getattr(self, 'trans_{0}'.format(self.TYPE_TRANSLATIONS[atom.path]))(atom)
|
||||
if old_dir is not None and old_dir != 2:
|
||||
atom.setProperty('dir', old_dir, PropertyFlags.MAP_SPECIFIED)
|
||||
self.after = atom.MapSerialize()
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
if self.before is not None and self.after is not None:
|
||||
return 'Standardized pipe: {0} -> {1}'.format(self.before, self.after)
|
||||
else:
|
||||
return 'Standardize pipes'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class StandardizeInsulatedPipes(Matcher):
|
||||
STATE_TO_TYPE = {
|
||||
'intact' :'/obj/machinery/networked/atmos/pipe/simple/insulated/visible',
|
||||
'intact-f':'/obj/machinery/networked/atmos/pipe/simple/insulated/hidden'
|
||||
}
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def Matches(self, atom):
|
||||
if atom.path == '/obj/machinery/networked/atmos/pipe/simple/insulated':
|
||||
return True
|
||||
if atom.path.startswith('/obj/machinery/networked/atmos/pipe/simple/insulated') and int(atom.getProperty('dir', 0)) in (3, 8, 12):
|
||||
# print(atom.MapSerialize())
|
||||
return True
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
newtype = atom.path
|
||||
if atom.path == '/obj/machinery/networked/atmos/pipe/simple/insulated':
|
||||
icon_state = ''
|
||||
if 'icon_state' in atom.properties:
|
||||
icon_state = atom.properties['icon_state'].value
|
||||
newtype = self.STATE_TO_TYPE.get(icon_state, '/obj/machinery/networked/atmos/pipe/simple/insulated/visible')
|
||||
new_atom = Atom(newtype)
|
||||
if 'dir' in atom.mapSpecified:
|
||||
# Normalize dir
|
||||
direction = int(atom.getProperty('dir', 2))
|
||||
if direction == 3:
|
||||
direction = 1
|
||||
elif direction == 8: # Breaks things, for some reason
|
||||
direction = 4
|
||||
elif direction == 12:
|
||||
direction = 4
|
||||
new_atom.setProperty('dir', direction, PropertyFlags.MAP_SPECIFIED)
|
||||
return new_atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Standardized insulated pipe'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class FixWindows(Matcher):
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def Matches(self, atom):
|
||||
if atom.path.startswith('/obj/structure/window/full'):
|
||||
return False
|
||||
if atom.path.startswith('/obj/structure/window') and int(atom.getProperty('dir', SOUTH)) in (NORTH | WEST, SOUTH | WEST, NORTH | EAST, SOUTH | EAST):
|
||||
# print(atom.MapSerialize())
|
||||
return True
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
newtype = atom.path.replace('/obj/structure/window', '/obj/structure/window/full')
|
||||
atom.path = newtype
|
||||
atom.properties = {}
|
||||
atom.mapSpecified = []
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Standardized full windows'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class FixVaultFloors(Matcher):
|
||||
"""
|
||||
Changes flooring icons to use /vg/'s standardized vault icons.
|
||||
"""
|
||||
# state:1
|
||||
ICON_STATE_CHANGES = {
|
||||
'vault:1' :{'icon_state':'dark-markings', 'dir':2},
|
||||
'vault:2' :{'icon_state':'dark vault stripe', 'dir':2},
|
||||
'vault:4' :{'icon_state':'dark-markings', 'dir':1},
|
||||
'vault:8' :{'icon_state':'dark-markings', 'dir':8},
|
||||
'vault:6' :{'icon_state':'dark vault corner', 'dir':2},
|
||||
'vault:10':{'icon_state':'dark vault corner', 'dir':8},
|
||||
'vault:5' :{'icon_state':'dark vault full', 'dir':2},
|
||||
'vault:9' :{'icon_state':'dark loading', 'dir':4},
|
||||
|
||||
'vault-border:1' :{'icon_state':'dark vault stripe', 'dir':2},
|
||||
'vault-border:2' :{'icon_state':'dark vault stripe', 'dir':1},
|
||||
'vault-border:4' :{'icon_state':'dark vault stripe', 'dir':4},
|
||||
'vault-border:8' :{'icon_state':'dark vault stripe', 'dir':8},
|
||||
'vault-border:6' :{'icon_state':'dark vault corner', 'dir':2},
|
||||
'vault-border:10':{'icon_state':'dark vault stripe', 'dir':5},
|
||||
'vault-border:5' :{'icon_state':'dark vault stripe', 'dir':5},
|
||||
'vault-border:9' :{'icon_state':'dark vault stripe', 'dir':6},
|
||||
}
|
||||
def __init__(self):
|
||||
self.stateKey = ''
|
||||
self.changesMade = []
|
||||
return
|
||||
|
||||
def GetStateKey(self, atom):
|
||||
icon_state = ''
|
||||
_dir = '2'
|
||||
if 'dir' in atom.properties:
|
||||
_dir = str(atom.getProperty('dir'))
|
||||
if 'icon_state' in atom.properties:
|
||||
icon_state = atom.getProperty('icon_state')
|
||||
return icon_state + ":" + _dir
|
||||
|
||||
def Matches(self, atom):
|
||||
if atom.path.startswith('/turf/') and 'icon_state' in atom.mapSpecified:
|
||||
sk = self.GetStateKey(atom)
|
||||
if sk in self.ICON_STATE_CHANGES:
|
||||
self.stateKey = sk
|
||||
return True
|
||||
return False
|
||||
|
||||
def Fix(self, atom):
|
||||
self.changesMade = []
|
||||
propChanges = self.ICON_STATE_CHANGES[self.stateKey]
|
||||
if 'tag' in atom.mapSpecified:
|
||||
atom.mapSpecified.remove('tag')
|
||||
for key, newval in propChanges.items():
|
||||
if key not in atom.mapSpecified:
|
||||
atom.mapSpecified += [key]
|
||||
oldval = 'NONE'
|
||||
if key in atom.properties:
|
||||
oldval = str(atom.properties[key])
|
||||
if isinstance(newval, str):
|
||||
atom.properties[key] = BYONDString(newval)
|
||||
elif isinstance(newval, int):
|
||||
atom.properties[key] = BYONDValue(newval)
|
||||
self.changesMade += ['{0}: {1} -> {2}'.format(key, oldval, atom.properties[key])]
|
||||
return atom
|
||||
|
||||
def __str__(self):
|
||||
return 'Standardized vault flooring (' + ', '.join(self.changesMade) + ')'
|
||||
|
||||
@MapFix('vgstation')
|
||||
class RenameColorVG(RenameProperty):
|
||||
def __init__(self):
|
||||
RenameProperty.__init__(self, "color", "_color")
|
||||
@@ -1,91 +0,0 @@
|
||||
"""
|
||||
BYOND Base Packet Class
|
||||
|
||||
Created with help from tobba.
|
||||
"""
|
||||
import logging, struct
|
||||
|
||||
class NetTypes:
|
||||
BYTE = 0
|
||||
SHORT = 1
|
||||
LONG = 2
|
||||
STRING = 3
|
||||
|
||||
min_lens = [1, 2, 4, None]
|
||||
|
||||
@staticmethod
|
||||
def GetMinLength(t):
|
||||
return NetTypes.min_lens[t]
|
||||
|
||||
PacketTypes = {}
|
||||
|
||||
class Packet:
|
||||
ID = 0
|
||||
Name = ''
|
||||
def __init__(self):
|
||||
self.__field_data = {}
|
||||
self.header = {}
|
||||
self.min_length = 0
|
||||
|
||||
self.length = 0
|
||||
self.sequence = 0
|
||||
|
||||
def LinkField(self, datatype, propname, **kwargs):
|
||||
'''
|
||||
Associate a part of a packet to a field in this class
|
||||
'''
|
||||
kwargs['type'] = datatype
|
||||
kwargs['name'] = propname
|
||||
self.__field_data[len(self.__field_data)] = kwargs
|
||||
self.min_length += NetTypes.GetMinLength(datatype)
|
||||
|
||||
def Deserialize(self, msg):
|
||||
if len(msg) < self.min_length:
|
||||
logging.error('Received truncated packet {0}: min_length={1}, msg.len={2}'.format(self.Name, self.min_length, len(msg)))
|
||||
|
||||
# TIME FOR ASSUMPTIONS!
|
||||
pos = 0
|
||||
for idx, fieldinfo in self.__field_data.items():
|
||||
dtype = fieldinfo['type']
|
||||
propname = fieldinfo['name']
|
||||
unpacked = None
|
||||
if dtype == NetTypes.BYTE:
|
||||
dat = msg[pos:pos + 1]
|
||||
unpacked = struct.unpack('B', dat) # Unsigned char
|
||||
pos += 1
|
||||
elif dtype == NetTypes.SHORT:
|
||||
dat = msg[pos:pos + 2]
|
||||
unpacked = struct.unpack('h', dat) # short (maybe H?)
|
||||
pos += 2
|
||||
elif dtype == NetTypes.LONG:
|
||||
dat = msg[pos:pos + 4]
|
||||
unpacked = struct.unpack('l', dat) # short (maybe L?)
|
||||
pos += 4
|
||||
elif dtype == NetTypes.STRING:
|
||||
dat = msg[pos:]
|
||||
unpacked = dat.split('\x00', 1)
|
||||
pos += len(unpacked) + 1 # NUL byte stripped
|
||||
else:
|
||||
logging.error('Unable to unpack {0} packet at field {1}: Unknown datatype {2}'.format(self.Name, idx, dtype))
|
||||
logging.error('Packet __field_data:'.repr(self.__field_data))
|
||||
raise SystemError()
|
||||
setattr(self, propname, unpacked)
|
||||
|
||||
def Serialize(self):
|
||||
msg = b''
|
||||
for idx, fieldinfo in self.__field_data.items():
|
||||
dtype = fieldinfo['type']
|
||||
dat = getattr(self, fieldinfo['name'])
|
||||
if dtype == NetTypes.BYTE:
|
||||
msg += struct.pack('B', dat) # Unsigned char
|
||||
elif dtype == NetTypes.SHORT:
|
||||
msg += struct.pack('h', dat) # short (maybe H?)
|
||||
elif dtype == NetTypes.LONG:
|
||||
msg += struct.pack('l', dat) # short (maybe L?)
|
||||
elif dtype == NetTypes.STRING:
|
||||
msg += dat + b'\x00'
|
||||
else:
|
||||
logging.error('Unable to pack {0} packet at field {1}: Unknown datatype {2}'.format(self.Name, idx, dtype))
|
||||
logging.error('Packet __field_data:'.repr(self.__field_data))
|
||||
raise SystemError()
|
||||
return msg
|
||||
@@ -1,709 +0,0 @@
|
||||
'''
|
||||
Superficially generate an object/property tree.
|
||||
'''
|
||||
import re, logging, os
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except:
|
||||
import pickle
|
||||
|
||||
from .basetypes import Atom, Proc, BYONDValue, BYONDString, BYONDFileRef
|
||||
from .utils import md5sum, get_stdlib
|
||||
|
||||
REGEX_TABS = re.compile('^(?P<tabs>[\t\s]*)')
|
||||
REGEX_ATOMDEF = re.compile('^(?P<tabs>\t*)(?P<atom>[a-zA-Z0-9_/]+)\\{?\\s*$')
|
||||
REGEX_ABSOLUTE_PROCDEF = re.compile('^(?P<tabs>\t*)(?P<atom>[a-zA-Z0-9_/]+)/(?P<proc>[a-zA-Z0-9_]+)\((?P<args>.*)\)\\{?\s*$')
|
||||
REGEX_RELATIVE_PROCDEF = re.compile('^(?P<tabs>\t*)(?P<proc>[a-zA-Z0-9_]+)\((?P<args>.*)\)\\{?\\s*$')
|
||||
REGEX_LINE_COMMENT = re.compile('//.*?$')
|
||||
|
||||
def debug(filename, line, path, message):
|
||||
print('{0}:{1}: {2} - {3}'.format(filename, line, '/'.join(path), message))
|
||||
|
||||
class OTRCache:
|
||||
# : Only used for obliterating outdated data.
|
||||
VERSION = [28, 4, 2014]
|
||||
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.files = {}
|
||||
self.atoms = None
|
||||
self.handle = None
|
||||
|
||||
def StartReading(self):
|
||||
if self.handle:
|
||||
self.handle.close()
|
||||
self.handle = None
|
||||
if os.path.isfile(self.filename):
|
||||
self.handle = open(self.filename, 'r')
|
||||
|
||||
def StopReading(self):
|
||||
if self.handle is not None:
|
||||
self.handle.close()
|
||||
|
||||
def CheckVersion(self):
|
||||
# print('READ VERSION')
|
||||
# Block 1: Version
|
||||
if pickle.load(self.handle) != self.VERSION:
|
||||
print('!!! Outdated OTR data, rebuilding.')
|
||||
return False
|
||||
return True
|
||||
|
||||
def ReadFiles(self):
|
||||
# print('READ FILES')
|
||||
# Block 2: Files
|
||||
self.files = pickle.load(self.handle)
|
||||
|
||||
def ReadAtoms(self):
|
||||
# print('READ ATOMS')
|
||||
return pickle.load(self.handle)
|
||||
|
||||
def CheckFileHash(self, fn, md5):
|
||||
# print('{0}: {1}'.format(fn,md5))
|
||||
if fn not in self.files:
|
||||
print(' + {0}'.format(fn))
|
||||
return False
|
||||
if self.files[fn] != md5:
|
||||
print(' * {0}'.format(fn))
|
||||
return False
|
||||
return True
|
||||
|
||||
def PruneFiles(self, file_list):
|
||||
for fn in self.files.keys():
|
||||
if fn not in file_list:
|
||||
self.files -= [fn]
|
||||
print(' - {0}'.format(fn))
|
||||
|
||||
def SetFileMD5(self, fn, md5):
|
||||
self.files[fn] = md5
|
||||
|
||||
def GetFiles(self):
|
||||
return self.files.keys()
|
||||
|
||||
def Save(self, atoms):
|
||||
with open(self.filename, 'w') as f:
|
||||
pickle.dump(self.VERSION, f)
|
||||
pickle.dump(self.files, f)
|
||||
pickle.dump(atoms, f)
|
||||
|
||||
class ObjectTree:
|
||||
reserved_words = ('else', 'break', 'return', 'continue', 'spawn') # , 'proc')
|
||||
stdlib_files = (
|
||||
'dm_std.dm',
|
||||
'atom_defaults.dm'
|
||||
)
|
||||
def __init__(self, **options):
|
||||
#: All atoms, in a list.
|
||||
self.Atoms = {}
|
||||
|
||||
#: All atoms, in a tree-node structure.
|
||||
self.Tree = Atom('')
|
||||
|
||||
#: Skip loading from .OTR?
|
||||
self.skip_otr = False
|
||||
|
||||
self.LoadedStdLib = False
|
||||
self.cpath = []
|
||||
self.popLevels = []
|
||||
self.InProc = []
|
||||
self.pindent = 0 # Previous Indent
|
||||
self.ignoreLevel = [] # Block Comments
|
||||
self.ignoreStartIndent = -1
|
||||
self.debugOn = True
|
||||
self.ignoreDebugOn = False
|
||||
self.ignoreTokens = {
|
||||
'/*':'*/',
|
||||
'{"':'"}'
|
||||
}
|
||||
self.defines = {}
|
||||
self.defineMatchers = {}
|
||||
self.comments = []
|
||||
self.fileLayouts = {}
|
||||
self.LeavePreprocessorDirectives = options.get('preprocessor_directives', False)
|
||||
|
||||
nit = self.ignoreTokens.copy()
|
||||
for _, stop in self.ignoreTokens.iteritems():
|
||||
nit[stop] = None
|
||||
self.ignoreTokens = nit
|
||||
|
||||
self.defines['__OBJTREE'] = BYONDValue('1')
|
||||
|
||||
def ProcessMultiString(self, filename, line, ignoreLevels, current_buffer):
|
||||
return '"{0}"'.format(current_buffer)
|
||||
|
||||
def SplitPath(self, string):
|
||||
o = []
|
||||
buf = []
|
||||
inProc = False
|
||||
for chunk in string.split('/'):
|
||||
if not inProc:
|
||||
if '(' in chunk and ')' not in chunk:
|
||||
inProc = True
|
||||
buf += [chunk]
|
||||
else:
|
||||
o += [chunk]
|
||||
else:
|
||||
if ')' in chunk:
|
||||
o += ['/'.join(buf + [chunk])]
|
||||
inProc = False
|
||||
else:
|
||||
buf += [chunk]
|
||||
return o
|
||||
|
||||
def ProcessFilesFromDME(self, dmefile='baystation12.dme', ext='.dm', **kwargs):
|
||||
changed_files = 0
|
||||
rootdir = os.path.dirname(dmefile)
|
||||
projectfile = os.path.join(rootdir, os.path.basename(dmefile).replace('.dme', '.otr'))
|
||||
|
||||
cache = OTRCache(projectfile)
|
||||
invalid = False
|
||||
if not self.skip_otr:
|
||||
if os.path.isfile(projectfile):
|
||||
print('--- Loading pickled object tree...')
|
||||
cache.StartReading()
|
||||
if cache.CheckVersion():
|
||||
cache.ReadFiles()
|
||||
else:
|
||||
invalid = True
|
||||
else:
|
||||
invalid = True
|
||||
|
||||
ToRead = []
|
||||
if not self.LoadedStdLib and kwargs.get('load_stdlib', True):
|
||||
stdlib_dir = get_stdlib()
|
||||
for filename in self.stdlib_files:
|
||||
# self.ProcessFile(os.path.join(stdlib_dir, filename))
|
||||
ToRead += [os.path.join(stdlib_dir, filename)]
|
||||
with open(dmefile, 'r') as dmeh:
|
||||
for line in dmeh:
|
||||
if line.startswith('#include'):
|
||||
inString = False
|
||||
# escaped=False
|
||||
filename = ''
|
||||
for c in line:
|
||||
"""
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
if
|
||||
escaped = False
|
||||
continue
|
||||
"""
|
||||
if c == '"':
|
||||
inString = not inString
|
||||
if not inString:
|
||||
filepath = os.path.join(rootdir, filename)
|
||||
if filepath.endswith(ext):
|
||||
ToRead += [filepath]
|
||||
filename = ''
|
||||
continue
|
||||
else:
|
||||
if inString:
|
||||
filename += c
|
||||
|
||||
for filepath in ToRead:
|
||||
md5 = md5sum(filepath)
|
||||
if invalid or not cache.CheckFileHash(filepath, md5):
|
||||
changed_files += 1
|
||||
cache.SetFileMD5(filepath, md5)
|
||||
if invalid or self.skip_otr or changed_files > 0:
|
||||
if invalid:
|
||||
print('--- Rebuilding object tree - Parsing DM files...'.format(changed_files))
|
||||
else:
|
||||
print('--- {0} changed files. Parsing DM files...'.format(changed_files))
|
||||
for f in ToRead:
|
||||
self.ProcessFile(f)
|
||||
print('--- Saving atoms...')
|
||||
cache.StopReading()
|
||||
cache.Save(self.Atoms)
|
||||
self.MakeTree()
|
||||
else:
|
||||
print('--- No changes detected, using pickled atoms...')
|
||||
self.Atoms = cache.ReadAtoms()
|
||||
cache.StopReading()
|
||||
self.MakeTree()
|
||||
|
||||
def DetermineContext(self, filename, ln, line, numtabs, atom_prefix=[]):
|
||||
'''
|
||||
Spit out the full path of the atom we're currently in.
|
||||
|
||||
Does NOT update internal positioning. Think peek.
|
||||
'''
|
||||
if numtabs == 0:
|
||||
return None # Global context
|
||||
|
||||
elif numtabs > self.pindent:
|
||||
return '/'.join(self.cpath + atom_prefix)
|
||||
|
||||
elif numtabs < self.pindent:
|
||||
cpath_copy = list(self.cpath)
|
||||
for _ in range(self.pindent - numtabs + 1):
|
||||
popsToDo = self.popLevels.pop()
|
||||
for _ in range(popsToDo):
|
||||
cpath_copy.pop()
|
||||
cpath_copy += atom_prefix
|
||||
return '/'.join(cpath_copy)
|
||||
|
||||
elif numtabs == self.pindent:
|
||||
cpath_copy = list(self.cpath)
|
||||
levelsToPop = self.popLevels.pop()
|
||||
for _ in range(levelsToPop):
|
||||
cpath_copy.pop()
|
||||
cpath_copy += atom_prefix
|
||||
return '/'.join(cpath_copy)
|
||||
|
||||
|
||||
def ProcessAtom(self, filename, ln, line, atom, atom_path, numtabs, procArgs=None):
|
||||
# Reserved words that show up on their own
|
||||
if atom in ObjectTree.reserved_words:
|
||||
return
|
||||
|
||||
# Other things to ignore (false positives, comments)
|
||||
if atom.startswith('var/') or atom.startswith('//'):
|
||||
return
|
||||
|
||||
# Things part of a string or list.
|
||||
if numtabs > 0 and atom.strip().startswith('/'):
|
||||
return
|
||||
|
||||
if self.debugOn: print('{} > {}'.format(numtabs, line.rstrip()))
|
||||
|
||||
if numtabs == 0:
|
||||
self.cpath = atom_path
|
||||
if len(self.cpath) == 0:
|
||||
self.cpath += ['']
|
||||
elif self.cpath[0] != '':
|
||||
self.cpath.insert(0, '')
|
||||
self.popLevels = [len(self.cpath)]
|
||||
if self.debugOn: debug(filename, ln, self.cpath, '0 - ' + repr(atom_path))
|
||||
|
||||
elif numtabs > self.pindent:
|
||||
self.cpath += atom_path
|
||||
self.popLevels += [len(atom_path)]
|
||||
if self.debugOn: debug(filename, ln, self.cpath, '>')
|
||||
|
||||
elif numtabs < self.pindent:
|
||||
if self.debugOn: print('({} - {})={}: {}'.format(self.pindent, numtabs, self.pindent - numtabs, repr(self.cpath)))
|
||||
for _ in range(self.pindent - numtabs + 1):
|
||||
popsToDo = self.popLevels.pop()
|
||||
if self.debugOn: print(' pop {} {}'.format(popsToDo, self.popLevels))
|
||||
for i in range(popsToDo):
|
||||
self.cpath.pop()
|
||||
if self.debugOn: print(' pop {}/{}: {}'.format(i + 1, popsToDo, repr(self.cpath)))
|
||||
self.cpath += atom_path
|
||||
self.popLevels += [len(atom_path)]
|
||||
if self.debugOn: debug(filename, ln, self.cpath, '<')
|
||||
|
||||
elif numtabs == self.pindent:
|
||||
levelsToPop = self.popLevels.pop()
|
||||
for i in range(levelsToPop):
|
||||
self.cpath.pop()
|
||||
self.cpath += atom_path
|
||||
self.popLevels += [len(atom_path)]
|
||||
if self.debugOn: print('popLevels: ' + repr(self.popLevels))
|
||||
if self.debugOn: debug(filename, ln, self.cpath, '==')
|
||||
|
||||
origpath = '/'.join(self.cpath)
|
||||
# print(npath)
|
||||
|
||||
# definition?
|
||||
defs = []
|
||||
|
||||
# Trim off /proc or /var, if needed.
|
||||
prep_path = list(self.cpath)
|
||||
|
||||
for special in ['proc']:
|
||||
if special in prep_path:
|
||||
defs += [special]
|
||||
prep_path.remove(special)
|
||||
|
||||
npath = '/'.join(prep_path)
|
||||
|
||||
if npath not in self.Atoms:
|
||||
if procArgs is not None:
|
||||
assert npath.endswith(')')
|
||||
# if origpath != npath:
|
||||
# print(origpath,proc_def)
|
||||
proc = Proc(npath, procArgs, filename, ln)
|
||||
proc.origpath = origpath
|
||||
proc.definition = 'proc' in defs
|
||||
self.Atoms[npath] = proc
|
||||
else:
|
||||
self.Atoms[npath] = Atom(npath, filename, ln)
|
||||
# if self.debugOn: print('Added ' + npath)
|
||||
self.pindent = numtabs
|
||||
return self.Atoms[npath]
|
||||
|
||||
def AddCodeToProc(self, startIndent, code):
|
||||
if '\n' in code:
|
||||
for line in code.split('\n'):
|
||||
self.AddCodeToProc(startIndent, line)
|
||||
else:
|
||||
m = REGEX_TABS.match(code)
|
||||
if m is not None:
|
||||
numtabs = len(m.group('tabs'))
|
||||
i = max(1, numtabs - startIndent)
|
||||
# self.loadingProc.AddCode(i, '/* {0} */ {1}'.format(i,code.strip()))
|
||||
self.loadingProc.AddCode(i, code.rstrip())
|
||||
|
||||
def finishComment(self, line, **args):
|
||||
self.comments += [self.comment]
|
||||
self.fileLayout += [('COMMENT', len(self.comments) - 1)]
|
||||
if self.ignoreDebugOn: print('finishComment({}): {}'.format(line, self.comment))
|
||||
if self.loadingProc is not None and (args.get('cleansed_line', '') == '' and not self.comment.strip().startswith('//')):
|
||||
self.AddCodeToProc(self.ignoreStartIndent, self.comment)
|
||||
self.comment = ''
|
||||
|
||||
def handleOBToken(self, name, context, params):
|
||||
if context is not None:
|
||||
context = self.Atoms[context]
|
||||
name = 'ob_{0}'.format(name.lower())
|
||||
getattr(self, name)(context, *params)
|
||||
|
||||
def ProcessFile(self, filename):
|
||||
self.cpath = []
|
||||
self.popLevels = []
|
||||
self.pindent = 0 # Previous Indent
|
||||
self.ignoreLevel = []
|
||||
self.debugOn = False
|
||||
self.ignoreDebugOn = False
|
||||
self.ignoreStartIndent = -1
|
||||
self.loadingProc = None
|
||||
self.comment = ''
|
||||
self.fileLayout = []
|
||||
self.lineBeforePreprocessing = ''
|
||||
self.current_filename = filename
|
||||
with open(filename, 'r') as f:
|
||||
ln = 0
|
||||
ignoreLevel = []
|
||||
|
||||
for line in f:
|
||||
ln += 1
|
||||
|
||||
skipNextChar = False
|
||||
nl = ''
|
||||
|
||||
line = line.rstrip()
|
||||
self.lineBeforePreprocessing = line
|
||||
line_len = len(line)
|
||||
for i in xrange(line_len):
|
||||
c = line[i]
|
||||
nc = ''
|
||||
if line_len > i + 1:
|
||||
nc = line[i + 1]
|
||||
tok = c + nc
|
||||
# print(tok)
|
||||
if skipNextChar:
|
||||
if self.ignoreDebugOn: print('Skipping {}.'.format(repr(tok)))
|
||||
skipNextChar = False
|
||||
# self.comment += c
|
||||
if self.ignoreDebugOn: print('self.comment = {}.'.format(repr(self.comment)))
|
||||
continue
|
||||
if tok == '//':
|
||||
# if self.ignoreDebugOn: debug(filename,ln,self.cpath,'{} ({})'.format(tok,len(ignoreLevel)))
|
||||
if len(ignoreLevel) == 0:
|
||||
self.comment = line[i:]
|
||||
# if self.ignoreDebugOn: print('self.comment = {}.'.format(repr(self.comment)))
|
||||
# print('Found '+self.comment)
|
||||
self.finishComment('243', cleaned_line=nl)
|
||||
break
|
||||
if tok in self.ignoreTokens:
|
||||
pc = ''
|
||||
if i > 0:
|
||||
pc = line[i - 1]
|
||||
if tok == '{"' and pc == '"':
|
||||
self.comment += c
|
||||
continue
|
||||
# if self.ignoreDebugOn: print(repr(self.ignoreTokens[tok]))
|
||||
stop = self.ignoreTokens[tok]
|
||||
if stop == None: # End comment
|
||||
if len(ignoreLevel) > 0:
|
||||
if ignoreLevel[-1] == tok:
|
||||
skipNextChar = True
|
||||
self.comment += tok
|
||||
ignoreLevel.pop()
|
||||
if len(ignoreLevel) == 0:
|
||||
self.finishComment('261')
|
||||
continue
|
||||
else:
|
||||
self.comment += c
|
||||
continue
|
||||
else: # Start comment
|
||||
skipNextChar = True
|
||||
ignoreLevel += [stop]
|
||||
self.comment = tok
|
||||
continue
|
||||
if self.ignoreDebugOn: debug(filename, ln, self.cpath, '{} ({})'.format(tok, len(ignoreLevel)))
|
||||
if len(ignoreLevel) == 0:
|
||||
nl += c
|
||||
else:
|
||||
self.comment += c
|
||||
if line != nl:
|
||||
if self.ignoreDebugOn: print('IN : ' + line)
|
||||
line = nl
|
||||
if self.ignoreDebugOn: print('OUT: ' + line)
|
||||
if self.ignoreDebugOn: print('self.comment = {}.'.format(repr(self.comment)))
|
||||
|
||||
if len(ignoreLevel) > 0:
|
||||
self.comment += "\n"
|
||||
continue
|
||||
|
||||
line = REGEX_LINE_COMMENT.sub('', line)
|
||||
|
||||
if line.strip() == '':
|
||||
if self.loadingProc is not None:
|
||||
self.loadingProc.AddBlankLine()
|
||||
continue
|
||||
|
||||
# Preprocessing defines.
|
||||
if line.strip().startswith("#"):
|
||||
if line.endswith('\\'): continue
|
||||
tokenChunks = line.split('#')
|
||||
tokenChunks = tokenChunks[1].split()
|
||||
directive = tokenChunks[0]
|
||||
if directive == 'define':
|
||||
# #define SOMETHING Value
|
||||
defineChunks = line.split(None, 3)
|
||||
if len(defineChunks) == 2:
|
||||
defineChunks += [1]
|
||||
elif len(defineChunks) == 3:
|
||||
defineChunks[2] = self.PreprocessLine(defineChunks[2])
|
||||
# print(repr(defineChunks))
|
||||
try:
|
||||
if '.' in defineChunks[2]:
|
||||
self.defines[defineChunks[1]] = BYONDValue(float(defineChunks[2]), filename, ln)
|
||||
else:
|
||||
self.defines[defineChunks[1]] = BYONDValue(int(defineChunks[2]), filename, ln)
|
||||
except:
|
||||
self.defines[defineChunks[1]] = BYONDString(defineChunks[2], filename, ln)
|
||||
self.fileLayout += [('DEFINE', defineChunks[1], defineChunks[2])]
|
||||
elif directive == 'undef':
|
||||
undefChunks = line.split(' ', 2)
|
||||
if undefChunks[1] in self.defines:
|
||||
del self.defines[undefChunks[1]]
|
||||
self.fileLayout += [('UNDEF', undefChunks[1])]
|
||||
|
||||
# OpenBYOND tokens.
|
||||
elif directive.startswith('__OB_'):
|
||||
numtabs = 0
|
||||
m = REGEX_TABS.match(line)
|
||||
if m is not None:
|
||||
numtabs = len(m.group('tabs'))
|
||||
atom = self.DetermineContext(filename, ln, line, numtabs)
|
||||
# if atom is None: continue
|
||||
# print('OBTOK {0}'.format(repr(tokenChunks)))
|
||||
self.handleOBToken(tokenChunks[0].replace('__OB_', ''), atom, tokenChunks[1:])
|
||||
# self.fileLayout += [('OBTOK', atom.path)]
|
||||
continue
|
||||
else:
|
||||
chunks = line.split(' ')
|
||||
self.fileLayout += [('PP_TOKEN', line)]
|
||||
print('BUG: Unhandled preprocessor directive #{} in {}:{}'.format(directive, filename, ln))
|
||||
continue
|
||||
|
||||
# Preprocessing
|
||||
line = self.PreprocessLine(line)
|
||||
|
||||
m = REGEX_TABS.match(self.lineBeforePreprocessing)
|
||||
if m is not None:
|
||||
numtabs = len(m.group('tabs'))
|
||||
if self.ignoreStartIndent > -1 and self.ignoreStartIndent < numtabs:
|
||||
if self.loadingProc is not None:
|
||||
# self.loadingProc.AddCode(numtabs - self.ignoreStartIndent, self.lineBeforePreprocessing.strip())
|
||||
self.AddCodeToProc(self.ignoreStartIndent, self.lineBeforePreprocessing)
|
||||
if self.debugOn: print('TABS: {} ? {} - {}: {}'.format(numtabs, self.ignoreStartIndent, self.loadingProc, line))
|
||||
continue
|
||||
else:
|
||||
if self.debugOn and self.ignoreStartIndent > -1: print('BREAK ({} -> {}): {}'.format(self.ignoreStartIndent, numtabs, line))
|
||||
self.ignoreStartIndent = -1
|
||||
self.loadingProc = None
|
||||
else:
|
||||
if self.debugOn and self.ignoreStartIndent > -1: print('BREAK ' + line)
|
||||
self.ignoreStartIndent = -1
|
||||
self.loadingProc = None
|
||||
|
||||
if not line.strip().startswith('var/'):
|
||||
m = REGEX_ATOMDEF.match(line)
|
||||
if m is not None:
|
||||
numtabs = len(m.group('tabs'))
|
||||
atom = m.group('atom')
|
||||
atom_path = self.SplitPath(atom)
|
||||
atom = self.ProcessAtom(filename, ln, line, atom, atom_path, numtabs)
|
||||
if atom is None: continue
|
||||
self.fileLayout += [('ATOMDEF', atom.path)]
|
||||
continue
|
||||
|
||||
m = REGEX_ABSOLUTE_PROCDEF.match(line)
|
||||
if m is not None:
|
||||
numtabs = len(m.group('tabs'))
|
||||
atom = '{0}/{1}({2})'.format(m.group('atom'), m.group("proc"), m.group('args'))
|
||||
atom_path = self.SplitPath(atom)
|
||||
# print('PROCESSING ABS PROC AT INDENT > ' + str(numtabs) + " " + atom+" -> "+repr(atom_path))
|
||||
proc = self.ProcessAtom(filename, ln, line, atom, atom_path, numtabs, m.group('args').split(','))
|
||||
if proc is None: continue
|
||||
self.ignoreStartIndent = numtabs
|
||||
self.loadingProc = proc
|
||||
self.fileLayout += [('PROCDEF', proc.path)]
|
||||
continue
|
||||
|
||||
m = REGEX_RELATIVE_PROCDEF.match(line)
|
||||
if m is not None:
|
||||
numtabs = len(m.group('tabs'))
|
||||
atom = '{}({})'.format(m.group("proc"), m.group('args'))
|
||||
atom_path = self.SplitPath(atom)
|
||||
# print('IGNORING RELATIVE PROC AT INDENT > ' + str(numtabs) + " " + line)
|
||||
proc = self.ProcessAtom(filename, ln, line, atom, atom_path, numtabs, m.group('args').split(','))
|
||||
if proc is None: continue
|
||||
self.ignoreStartIndent = numtabs
|
||||
self.loadingProc = proc
|
||||
self.fileLayout += [('PROCDEF', proc.path)]
|
||||
continue
|
||||
|
||||
path = '/'.join(self.cpath)
|
||||
# if len(self.cpath) > 0 and 'proc' in self.cpath:
|
||||
# continue
|
||||
# if 'proc' in self.cpath:
|
||||
# continue
|
||||
if '=' in line or line.strip().startswith('var/'):
|
||||
if path not in self.Atoms:
|
||||
self.Atoms[path] = Atom(path)
|
||||
name, prop = self.consumeVariable(line, filename, ln)
|
||||
self.Atoms[path].properties[name] = prop
|
||||
self.fileLayout += [('VAR', path, name)]
|
||||
self.fileLayouts[filename] = self.fileLayout
|
||||
|
||||
def consumeVariable(self, line, filename, ln):
|
||||
declaration = False
|
||||
value = None
|
||||
size = None
|
||||
|
||||
decl = ''
|
||||
if self.LeavePreprocessorDirectives:
|
||||
line = decl = self.lineBeforePreprocessing.strip()
|
||||
else:
|
||||
decl = line.strip()
|
||||
if '[' in line:
|
||||
line_split, arr_decl = line.split('[', 1)
|
||||
str_size = arr_decl[:arr_decl.index(']')]
|
||||
size = -1
|
||||
if str_size != '':
|
||||
try:
|
||||
size = int(str_size)
|
||||
except ValueError:
|
||||
pass
|
||||
# print(repr({'size':size,'line':line_split}))
|
||||
line = line_split
|
||||
|
||||
if '=' in line:
|
||||
decl, value = line.split('=', 1)
|
||||
decl = decl.strip()
|
||||
value = value.strip()
|
||||
else:
|
||||
decl = line.strip()
|
||||
value = None
|
||||
# print(repr({'decl':decl,'value':value}))
|
||||
|
||||
# (var)(/global|const|tmp)(/type/fragment)name
|
||||
if decl.startswith('var/'):
|
||||
declaration = True
|
||||
decl = decl[4:]
|
||||
pathchunks = decl.split('/')
|
||||
name = pathchunks[-1]
|
||||
special = None
|
||||
typepath = '/'
|
||||
if declaration:
|
||||
if pathchunks[0] in ('tmp', 'global', 'const'):
|
||||
special = pathchunks[0]
|
||||
pathchunks = pathchunks[1:]
|
||||
if 'list' not in pathchunks and size is not None:
|
||||
pathchunks = ['list'] + pathchunks
|
||||
typepath = '/' + '/'.join(pathchunks[:-1])
|
||||
|
||||
kwargs = {
|
||||
'declaration':declaration,
|
||||
'special':special,
|
||||
'size':size
|
||||
}
|
||||
if typepath != '/':
|
||||
return (name, BYONDValue(value, filename, ln, typepath, **kwargs))
|
||||
elif value and value[0] == '"':
|
||||
return (name, BYONDString(value[1:-1], filename, ln, **kwargs))
|
||||
elif value and value[0] == "'":
|
||||
return (name, BYONDFileRef(value[1:-1], filename, ln, **kwargs))
|
||||
elif value and '.' in value:
|
||||
try:
|
||||
return (name, BYONDValue(float(value), filename, ln, typepath, **kwargs))
|
||||
except ValueError:
|
||||
pass
|
||||
return (name, BYONDValue(value, filename, ln, typepath, **kwargs))
|
||||
|
||||
def MakeTree(self):
|
||||
print('Generating Tree...')
|
||||
self.Tree = Atom('/')
|
||||
with open('objtree.txt', 'w') as f:
|
||||
for key in sorted(self.Atoms):
|
||||
f.write("{0}\n".format(key))
|
||||
atom = self.Atoms[key]
|
||||
cpath = []
|
||||
cNode = self.Tree
|
||||
fullpath = self.SplitPath(atom.path)
|
||||
truncatedPath = fullpath[1:]
|
||||
for path_item in truncatedPath:
|
||||
cpath += [path_item]
|
||||
cpath_str = '/'.join([''] + cpath)
|
||||
# if path_item == 'var':
|
||||
# if path_item not in cNode.properties:
|
||||
# cNode.properties[fullpath[-1]]='???'
|
||||
if path_item not in cNode.children:
|
||||
if cpath_str in self.Atoms:
|
||||
cNode.children[path_item] = self.Atoms[cpath_str]
|
||||
else:
|
||||
if '(' in path_item:
|
||||
cNode.children[path_item] = Proc('/'.join([''] + cpath), [])
|
||||
else:
|
||||
cNode.children[path_item] = Atom('/'.join([''] + cpath),atom.filename,atom.line)
|
||||
cNode.children[path_item].parent = cNode
|
||||
parent_type = cNode.children[path_item].getProperty('parent_type')
|
||||
if parent_type is not None:
|
||||
print(' - Parent of {0} forced to be {1}'.format(cNode.children[path_item].path, repr(parent_type)))
|
||||
cNode.children[path_item].parent = self.Atoms[parent_type]
|
||||
cNode = cNode.children[path_item]
|
||||
self.Tree.InheritProperties()
|
||||
print('Processed {0} atoms.'.format(len(self.Atoms)))
|
||||
# self.Atoms = {}
|
||||
|
||||
def GetAtom(self, path):
|
||||
if path in self.Atoms:
|
||||
return self.Atoms[path]
|
||||
|
||||
cpath = []
|
||||
cNode = self.Tree
|
||||
fullpath = path.split('/')
|
||||
truncatedPath = fullpath[1:]
|
||||
for path_item in truncatedPath:
|
||||
cpath += [path_item]
|
||||
if path_item not in cNode.children:
|
||||
print('Unable to find {0} (lost at {1})'.format(path, cNode.path))
|
||||
print(repr(cNode.children.keys()))
|
||||
return None
|
||||
cNode = cNode.children[path_item]
|
||||
# print('Found {0}!'.format(path))
|
||||
self.Atoms[path] = cNode
|
||||
return cNode
|
||||
|
||||
|
||||
def PreprocessLine(self, line):
|
||||
for key, define in self.defines.items():
|
||||
if key in line:
|
||||
if key not in self.defineMatchers:
|
||||
self.defineMatchers[key] = re.compile(r'\b' + key + r'\b')
|
||||
newline = self.defineMatchers[key].sub(str(define.value), line)
|
||||
if newline != line:
|
||||
'''
|
||||
if filename.endswith('pipes.dm'):
|
||||
print('OLD: {}'.format(line))
|
||||
print('PPD: {}'.format(newline))
|
||||
'''
|
||||
line = newline
|
||||
return line
|
||||
@@ -1,48 +0,0 @@
|
||||
import hashlib, ast, os
|
||||
import operator as op
|
||||
|
||||
def md5sum(filename):
|
||||
with open(filename, mode='rb') as f:
|
||||
d = hashlib.md5()
|
||||
while True:
|
||||
buf = f.read(4096) # 128 is smaller than the typical filesystem block
|
||||
if not buf:
|
||||
break
|
||||
d.update(buf)
|
||||
return d.hexdigest().upper()
|
||||
|
||||
# supported operators
|
||||
operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
|
||||
ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor}
|
||||
|
||||
def eval_expr(expr):
|
||||
"""
|
||||
>>> eval_expr('2^6')
|
||||
4
|
||||
>>> eval_expr('2**6')
|
||||
64
|
||||
>>> eval_expr('1 + 2*3**(4^5) / (6 + -7)')
|
||||
-5.0
|
||||
"""
|
||||
return eval_(ast.parse(expr).body[0].value) # Module(body=[Expr(value=...)])
|
||||
|
||||
def eval_(node):
|
||||
if isinstance(node, ast.Num): # <number>
|
||||
return node.n
|
||||
elif isinstance(node, ast.operator): # <operator>
|
||||
return operators[type(node)]
|
||||
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
|
||||
return eval_(node.op)(eval_(node.left), eval_(node.right))
|
||||
else:
|
||||
raise TypeError(node)
|
||||
|
||||
|
||||
_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
def get_data(path):
|
||||
return os.path.join(_ROOT, 'data', path)
|
||||
|
||||
def get_stdlib(path=''):
|
||||
if path != '':
|
||||
return os.path.join(get_data('stdlib'), path)
|
||||
return get_data('stdlib')
|
||||
@@ -1,177 +0,0 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenBYOND.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenBYOND.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/OpenBYOND"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenBYOND"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
@@ -1,3 +0,0 @@
|
||||
rm -rf _build
|
||||
call make html
|
||||
pause
|
||||
@@ -1,28 +0,0 @@
|
||||
.. module:: com.byond.basetypes
|
||||
|
||||
:mod:`com.byond.basetypes` -- Basic BYOND Types
|
||||
===============================================
|
||||
|
||||
Basic Types
|
||||
-----------
|
||||
|
||||
.. autoclass:: BYONDValue
|
||||
:members:
|
||||
|
||||
.. autoclass:: BYONDFileRef
|
||||
:members:
|
||||
|
||||
.. autoclass:: BYONDString
|
||||
:members:
|
||||
|
||||
Atoms and Procs
|
||||
---------------
|
||||
|
||||
.. autoclass:: PropertyFlags
|
||||
:members:
|
||||
|
||||
.. autoclass:: Atom
|
||||
:members:
|
||||
|
||||
.. autoclass:: Proc
|
||||
:members:
|
||||
@@ -1,266 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# OpenBYOND documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Feb 07 20:03:28 2014.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('../src'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.pngmath',
|
||||
'sphinx.ext.viewcode',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'BYONDTools'
|
||||
copyright = u'2013-2014 BYONDTools Team'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.1.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'OpenBYONDdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'OpenBYOND.tex', u'OpenBYOND Documentation',
|
||||
u'OpenBYOND Team', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'openbyond', u'OpenBYOND Documentation',
|
||||
[u'OpenBYOND Team'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'OpenBYOND', u'OpenBYOND Documentation',
|
||||
u'OpenBYOND Team', 'OpenBYOND', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
primary_domain = 'py'
|
||||
@@ -1,18 +0,0 @@
|
||||
OpenBYOND
|
||||
=========
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
byond/basetypes
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=_build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\OpenBYOND.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\OpenBYOND.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %BUILDDIR%/..
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %BUILDDIR%/..
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
@@ -1,50 +0,0 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# Originally cxfreeze-postinstall
|
||||
# Script run after installation on Windows to fix up the Python location in
|
||||
# the script as well as create batch files.
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
import distutils.sysconfig
|
||||
import glob
|
||||
import os
|
||||
|
||||
vars = distutils.sysconfig.get_config_vars()
|
||||
prefix = vars["prefix"]
|
||||
python = os.path.join(prefix, "python.exe")
|
||||
scriptDir = os.path.join(prefix, "Scripts")
|
||||
|
||||
# Keep in-sync with setup.py.
|
||||
scripts = [
|
||||
'dmm',
|
||||
'dmi',
|
||||
'dmindent',
|
||||
'dmmrender',
|
||||
'dmmfix',
|
||||
|
||||
'ss13_makeinhands'
|
||||
]
|
||||
for fileName in glob.glob(os.path.join(scriptDir, "*.py")):
|
||||
# skip already created batch files if they exist
|
||||
name, ext = os.path.splitext(os.path.basename(fileName))
|
||||
if name not in scripts:
|
||||
continue
|
||||
|
||||
print('Running post-install for {}.'.format(name))
|
||||
# copy the file with the first line replaced with the correct python
|
||||
fullName = os.path.join(scriptDir, fileName)
|
||||
strippedName = os.path.join(scriptDir, name)
|
||||
lines = open(fullName).readlines()
|
||||
startidx=1
|
||||
if not lines[0].strip().startswith('#!'):
|
||||
print('WARNING: {} does not have a shebang.'.format(lines[0]))
|
||||
startidx=0
|
||||
outFile = open(fullName, "w")
|
||||
outFile.write("#!%s\n" % python)
|
||||
outFile.writelines(lines[startidx:])
|
||||
outFile.close()
|
||||
|
||||
# create the batch file
|
||||
batchFileName = strippedName + ".bat"
|
||||
command = "%s %s %%*" % (python, fullName)
|
||||
open(batchFileName, "w").write("@echo off\n\n%s" % command)
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Usage:
|
||||
$ python calculateMaxTechLevels.py path/to/your.dme .dm
|
||||
|
||||
calculateMaxTechLevels.py - Get techlevels of all objects and generate reports.
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
import os, sys, re
|
||||
from byond.objtree import ObjectTree
|
||||
from byond.basetypes import Atom, Proc
|
||||
|
||||
# Calculated Max Tech Levels.
|
||||
CMTLs = {}
|
||||
|
||||
# All known atoms with tech origins.
|
||||
AtomTechOrigins = {}
|
||||
|
||||
def ProcessTechLevels(atom, path=''):
|
||||
global CMTLs, AtomTechOrigins
|
||||
if path.endswith(')'):
|
||||
# print('ignoring '+path)
|
||||
return
|
||||
for key, val in atom.properties.iteritems():
|
||||
# if 'obj' in path: print('{}: {}'.format(path,key))
|
||||
if key == 'origin_tech':
|
||||
tech_origin = {}
|
||||
# materials=9;bluespace=10;magnets=3
|
||||
text_origin_tech = atom.getProperty('origin_tech', 'null')
|
||||
if text_origin_tech == 'null' or text_origin_tech == '':
|
||||
continue
|
||||
techchunks = text_origin_tech.split(';')
|
||||
for techchunk in techchunks:
|
||||
parts = techchunk.split('=')
|
||||
if len(parts) != 2:
|
||||
print('Improperly formed origin_tech in {0}: {1}'.format(atom.path, val.value))
|
||||
continue
|
||||
tech = parts[0]
|
||||
level = int(parts[1])
|
||||
tech_origin[tech] = level
|
||||
if tech not in CMTLs:
|
||||
CMTLs[tech] = level
|
||||
if CMTLs[tech] < level:
|
||||
CMTLs[tech] = level
|
||||
AtomTechOrigins[path] = tech_origin
|
||||
break
|
||||
for key, child in atom.children.iteritems():
|
||||
ProcessTechLevels(child, path + '/' + key)
|
||||
|
||||
def prettify(tree, indent=0):
|
||||
prefix = ' ' * indent
|
||||
for key in tree.iterkeys():
|
||||
atom = tree[key]
|
||||
print('{}{}/'.format(prefix, key))
|
||||
prettify(atom.children, indent + len(key))
|
||||
for propkey, value in atom.properties.iteritems():
|
||||
print('{}var/{} = {}'.format(' ' * (indent + len(key)), propkey, repr(value)))
|
||||
|
||||
if os.path.isfile(sys.argv[1]):
|
||||
tree = ObjectTree()
|
||||
tree.ProcessFilesFromDME(sys.argv[1])
|
||||
ProcessTechLevels(tree.Tree)
|
||||
with open(os.path.join(os.path.dirname(sys.argv[1]), 'tech_origin_list.csv'), 'w') as w:
|
||||
with open(os.path.join(os.path.dirname(sys.argv[1]), 'max_tech_origins.txt'), 'w') as mto:
|
||||
tech_columns = []
|
||||
mto.write('Calculated Max Tech Levels:\n These tech levels have been determined by parsing ALL origin_tech variables in code included by {0}.\n'.format(sys.argv[1]))
|
||||
for tech in sorted(CMTLs.keys()):
|
||||
tech_columns.append(tech)
|
||||
mto.write('{:>15}: {}\n'.format(tech, CMTLs[tech]))
|
||||
w.write(','.join(['Atom', 'Name'] + tech_columns) + "\n")
|
||||
for path in sorted(AtomTechOrigins.keys()):
|
||||
row = []
|
||||
row.append(path)
|
||||
atom = tree.GetAtom(path)
|
||||
name = atom.properties.get('name', None)
|
||||
if name is None:
|
||||
name = ''
|
||||
else:
|
||||
name = name.value
|
||||
row.append('"' + name.replace('"', '""') + '"')
|
||||
for tech in tech_columns:
|
||||
if tech in AtomTechOrigins[path]:
|
||||
row.append(str(AtomTechOrigins[path][tech]))
|
||||
else:
|
||||
row.append('')
|
||||
w.write(','.join(row) + "\n")
|
||||
# prettify(tree.Tree.children)
|
||||
@@ -1,163 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import os, sys, re
|
||||
"""
|
||||
Usage:
|
||||
$ python fix_string_idiocy.py path/to/your.dme .dm
|
||||
|
||||
NOTE: NOT PERFECT, CREATES code-fixed DIRECTORY.
|
||||
*** MERGE THIS MANUALLY OR YOU WILL BREAK SHIT. ***
|
||||
|
||||
fix_string_idiocy.py - Combines multiple string append operations in DreamMaker code
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
REGEX_TO_COMBINE_AS_BLOCK = re.compile('^(?P<tabs>\t+)(?P<declaration>var/)?(?P<identifier>[A-Za-z\.]+)\s*(?P<operator>\+?)=\s*"(?P<content>.+)"\s*$')
|
||||
def ProcessFile(filename):
|
||||
fuckups = []
|
||||
with open(filename, 'r') as f:
|
||||
lastID = ''
|
||||
declaring = False
|
||||
lastLevel = 0
|
||||
lastWasAlert = False
|
||||
buffa = ''
|
||||
tempbuffa = ''
|
||||
tempfuckup = ''
|
||||
tempBackup = ''
|
||||
origIndentLevel = 0
|
||||
ln = 0
|
||||
for line in f:
|
||||
ln += 1
|
||||
m = REGEX_TO_COMBINE_AS_BLOCK.match(line)
|
||||
if m is not None:
|
||||
level = m.group('tabs').count('\t')
|
||||
ID = m.group('identifier')
|
||||
content = m.group('content').strip()
|
||||
indent = '\t' * level
|
||||
# indentMore = '\t' * (level + 1)
|
||||
if ID == lastID and level == lastLevel:
|
||||
if not lastWasAlert:
|
||||
buffa += '\n' + indent + '// AUTOFIXED BY fix_string_idiocy.py'
|
||||
buffa += '\n' + indent + '// ' + tempfuckup
|
||||
buffa += '\n' + tempbuffa
|
||||
print(tempfuckup)
|
||||
fuckups.append(tempfuckup)
|
||||
msg = '{0}:{1}: {2}'.format(filename, ln, line.strip())
|
||||
print(msg)
|
||||
fuckups.append(msg)
|
||||
buffa += '\n'
|
||||
# buffa += indentMore
|
||||
buffa += content
|
||||
lastWasAlert = True
|
||||
else:
|
||||
if lastWasAlert:
|
||||
buffa += '"}'
|
||||
buffa += '\n' + ('\t' * origIndentLevel) + '// END AUTOFIX'
|
||||
buffa += '\n'
|
||||
lastWasAlert = False
|
||||
if tempBackup != '':
|
||||
buffa += tempBackup
|
||||
tempBackup = line
|
||||
tempbuffa = indent
|
||||
origIndentLevel = level
|
||||
if m.group('declaration') is None:
|
||||
tempbuffa += '{0} {2}= {{"{1}'.format(ID, content, m.group('operator'))
|
||||
else:
|
||||
tempbuffa += 'var/{0} {2}= {{"{1}'.format(ID, content, m.group('operator'))
|
||||
tempfuckup = '{0}:{1}: {2}'.format(filename, ln, line.strip())
|
||||
lastID = ID
|
||||
lastLevel = level
|
||||
else:
|
||||
if line.strip() == '':
|
||||
tempBackup += line
|
||||
continue
|
||||
if lastWasAlert:
|
||||
buffa += '"}'
|
||||
buffa += '\n' + indent + '// END AUTOFIX'
|
||||
buffa += '\n'
|
||||
lastWasAlert = False
|
||||
tempBackup = ''
|
||||
if tempBackup != '':
|
||||
buffa += tempBackup
|
||||
tempBackup = ''
|
||||
lastID = ''
|
||||
lastLevel = ''
|
||||
buffa += line
|
||||
fixpaths = ['code', 'interface', 'RandomZLevels', '_maps']
|
||||
fixpath=filename
|
||||
for fp in fixpaths:
|
||||
fixpath = fixpath.replace(fp + os.sep, fp + '-fixed' + os.sep)
|
||||
if len(fuckups) > 0:
|
||||
if not os.path.isdir(os.path.dirname(fixpath)):
|
||||
os.makedirs(os.path.dirname(fixpath))
|
||||
with open(fixpath, 'w') as fixes:
|
||||
fixes.write(buffa)
|
||||
else:
|
||||
if os.path.isfile(fixpath):
|
||||
print('RM {0} ({1})'.format(fixpath,os.sep))
|
||||
os.remove(fixpath)
|
||||
# print(' Processed - {0} lines.'.format(ln))
|
||||
return fuckups
|
||||
|
||||
def ProcessFilesFromDME(dmefile='baystation12.dme', ext='.dm'):
|
||||
numFilesTotal = 0
|
||||
fileFuckups = {}
|
||||
rootdir = os.path.dirname(dmefile)
|
||||
with open(os.path.join(rootdir, 'stringcounts.csv'), 'w') as csv:
|
||||
with open(dmefile, 'r') as dmeh:
|
||||
for line in dmeh:
|
||||
if line.startswith('#include'):
|
||||
inString = False
|
||||
# escaped=False
|
||||
filename = ''
|
||||
for c in line:
|
||||
"""
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
if
|
||||
escaped = False
|
||||
continue
|
||||
"""
|
||||
if c == '"':
|
||||
inString = not inString
|
||||
if not inString:
|
||||
filepath = os.path.join(rootdir, filename)
|
||||
if filepath.endswith(ext):
|
||||
# print('Processing {0}...'.format(filepath))
|
||||
fileFuckups[filepath] = ProcessFile(filepath)
|
||||
numFilesTotal += 1
|
||||
filename = ''
|
||||
continue
|
||||
else:
|
||||
if inString:
|
||||
filename += c
|
||||
|
||||
if os.path.isdir(sys.argv[1]):
|
||||
for root, _, files in os.walk(sys.argv[1]):
|
||||
for filename in files:
|
||||
filepath = os.path.join(root, filename)
|
||||
if filepath.endswith('.dme'):
|
||||
ProcessFilesFromDME(filepath, sys.argv[2])
|
||||
sys.exit(0)
|
||||
if os.path.isfile(sys.argv[1]):
|
||||
ProcessFilesFromDME(sys.argv[1], sys.argv[2])
|
||||
@@ -1,278 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
DMI SPLITTER-UPPER THING
|
||||
|
||||
Makes merging sprites a hell of a lot easier.
|
||||
by N3X15 <nexis@7chan.org>
|
||||
|
||||
Requires PIL
|
||||
Written for Python 2.7.
|
||||
"""
|
||||
|
||||
import sys, os, traceback, fnmatch, argparse
|
||||
|
||||
from byond.DMI import DMI
|
||||
|
||||
args = ()
|
||||
|
||||
def main():
|
||||
opt = argparse.ArgumentParser() # version='0.1')
|
||||
opt.add_argument('-p', '--suppress-post-processing', dest='suppress_post_process', default=False, action='store_true')
|
||||
command = opt.add_subparsers(help='The command you wish to execute', dest='MODE')
|
||||
|
||||
_disassemble = command.add_parser('disassemble', help='Disassemble a single DMI file to a destination directory')
|
||||
_disassemble.add_argument('file', type=str, help='The DMI file to disassemble.', metavar='file.dmi')
|
||||
_disassemble.add_argument('destination', type=str, help='The directory in which to dump the resulting images.', metavar='dest/')
|
||||
|
||||
_disassemble_all = command.add_parser('disassemble-all', help='Disassemble a directory of DMI files to a destination directory')
|
||||
_disassemble_all.add_argument('source', type=str, help='The DMI files to disassemble.', metavar='source/')
|
||||
_disassemble_all.add_argument('destination', type=str, help='The directory in which to dump the resulting images.', metavar='dest/')
|
||||
|
||||
_compile = command.add_parser('compile', help='Compile a .dmi.mak file')
|
||||
_compile.add_argument('makefile', type=str, help='The .dmi.mak file to compile.', metavar='file.dmi.mak')
|
||||
_compile.add_argument('destination', type=str, help='The location of the resulting .dmi file.', metavar='file.dmi')
|
||||
|
||||
_compare = command.add_parser('compare', help='Compare two DMI files and note the differences')
|
||||
_compare.add_argument('theirs', type=str, help='One side of the difference', metavar='theirs.dmi')
|
||||
_compare.add_argument('mine', type=str, help='The other side.', metavar='mine.dmi')
|
||||
|
||||
_compare_all = command.add_parser('compare-all', help='Compare two DMI file directories and note the differences')
|
||||
_compare_all.add_argument('theirs', type=str, help='One side of the difference', metavar='theirs/')
|
||||
_compare_all.add_argument('mine', type=str, help='The other side.', metavar='mine/')
|
||||
_compare_all.add_argument('report', type=str, help='The file the report is saved to', metavar='report.txt')
|
||||
|
||||
_get_dmi_data = command.add_parser('get-dmi-data', help='Extract DMI header')
|
||||
_get_dmi_data.add_argument('file', type=str, help='DMI file', metavar='file.dmi')
|
||||
_get_dmi_data.add_argument('dest', type=str, help='The file where the DMI header will be saved', metavar='dest.txt')
|
||||
|
||||
_set_dmi_data = command.add_parser('set-dmi-data', help='Set DMI header')
|
||||
_set_dmi_data.add_argument('file', type=str, help='One side of the difference', metavar='file.dmi')
|
||||
_set_dmi_data.add_argument('metadata', type=str, help='DMI header file', metavar='metadata.txt')
|
||||
|
||||
_set_dmi_data = command.add_parser('clean', help='Clean up temporary files and *.new.dmi files.')
|
||||
_set_dmi_data.add_argument('basedir', type=str, help='Starting directory', metavar='vgstation/')
|
||||
|
||||
args = opt.parse_args()
|
||||
#print(args)
|
||||
if args.MODE == 'compile':
|
||||
make_dmi(args.makefile, args.destination, args)
|
||||
if args.MODE == 'compare':
|
||||
compare(args.theirs, args.mine, args, sys.stdout)
|
||||
if args.MODE == 'compare-all':
|
||||
compare_all(args.theirs, args.mine, args.report, args)
|
||||
elif args.MODE == 'disassemble':
|
||||
disassemble(args.file, args.destination, args)
|
||||
elif args.MODE == 'disassemble-all':
|
||||
disassemble_all(args.source, args.destination, args)
|
||||
elif args.MODE == 'get-dmi-data':
|
||||
get_dmi_data(args.file, args.dest, args)
|
||||
elif args.MODE == 'set-dmi-data':
|
||||
set_dmi_data(args.file, args.metadata, args)
|
||||
elif args.MODE == 'cleanup':
|
||||
cleanup(args.basedir, args)
|
||||
else:
|
||||
print('!!! Error, unknown MODE=%r' % args.MODE)
|
||||
|
||||
|
||||
|
||||
class ModeAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
# print('%s %s %s' % (namespace, values, option_string))
|
||||
namespace.MODE = self.dest
|
||||
namespace.args = values
|
||||
|
||||
def get_dmi_data(path, dest, parser):
|
||||
if(os.path.isfile(path)):
|
||||
dmi = DMI(path)
|
||||
with open(dest, 'w') as f:
|
||||
f.write(dmi.getHeader())
|
||||
|
||||
def set_dmi_data(path, headerFile, parser):
|
||||
if(os.path.isfile(path)):
|
||||
dmi = DMI(path)
|
||||
with open(headerFile, 'r') as f:
|
||||
dmi.setHeader(f.read(), path)
|
||||
|
||||
def make_dmi(path, dest, parser):
|
||||
if(os.path.isfile(path)):
|
||||
dmi = None
|
||||
try:
|
||||
dmi = DMI(dest)
|
||||
dmi.make(path)
|
||||
dmi.save(dest)
|
||||
except SystemError as e:
|
||||
print("!!! Received SystemError in %s, halting: %s" % (dmi.filename, traceback.format_exc(e)))
|
||||
print('# of cells: %d' % len(dmi.states))
|
||||
print('Image h/w: %s' % repr(dmi.size))
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print("Received error, continuing: %s" % traceback.format_exc())
|
||||
|
||||
def disassemble(path, to, parser):
|
||||
print('\tD %s -> %s' % (path, to))
|
||||
if(os.path.isfile(path)):
|
||||
dmi = None
|
||||
try:
|
||||
dmi = DMI(path)
|
||||
dmi.extractTo(to, parser.suppress_post_process)
|
||||
except SystemError as e:
|
||||
print("!!! Received SystemError in %s, halting: %s" % (dmi.filename, traceback.format_exc(e)))
|
||||
print('# of cells: %d' % len(dmi.states))
|
||||
print('Image h/w: %s' % repr(dmi.size))
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print("Received error, continuing: %s" % traceback.format_exc())
|
||||
|
||||
def compare(theirsfile, minefile, parser, reportstream, **kwargs):
|
||||
# print('\tD %s -> %s' % (theirsfile, minefile))
|
||||
theirs = []
|
||||
theirsDMI = None
|
||||
mine = []
|
||||
mineDMI = None
|
||||
states = []
|
||||
|
||||
new2mineFilename = minefile.replace('.dmi', '.new.dmi')
|
||||
new2theirsFilename = theirsfile.replace('.dmi', '.new.dmi')
|
||||
|
||||
new2mine=None
|
||||
if os.path.isfile(new2mineFilename):
|
||||
os.remove(new2mineFilename)
|
||||
if kwargs.get('newfile_mine',True):
|
||||
new2mine = DMI(new2mineFilename)
|
||||
|
||||
new2theirs=None
|
||||
if os.path.isfile(new2theirsFilename):
|
||||
os.remove(new2theirsFilename)
|
||||
if kwargs.get('newfile_theirs',False):
|
||||
new2theirs = DMI(new2theirsFilename)
|
||||
|
||||
|
||||
o = ''
|
||||
if(os.path.isfile(theirsfile)):
|
||||
try:
|
||||
theirsDMI = DMI(theirsfile)
|
||||
theirsDMI.loadAll()
|
||||
theirs = theirsDMI.states
|
||||
except SystemError as e:
|
||||
print("!!! Received SystemError in %s, halting: %s" % (theirs.filename, traceback.format_exc(e)))
|
||||
print('# of cells: %d' % len(theirs.states))
|
||||
print('Image h/w: %s' % repr(theirs.size))
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print("Received error, continuing: %s" % traceback.format_exc())
|
||||
o += "\n {0}: Received error, continuing: {1}".format(theirsfile, traceback.format_exc())
|
||||
for stateName in theirs:
|
||||
if stateName not in states:
|
||||
states.append(stateName)
|
||||
if(os.path.isfile(minefile)):
|
||||
try:
|
||||
mineDMI = DMI(minefile)
|
||||
mineDMI.loadAll()
|
||||
mine = mineDMI.states
|
||||
except SystemError as e:
|
||||
print("!!! Received SystemError in %s, halting: %s" % (mine.filename, traceback.format_exc(e)))
|
||||
print('# of cells: %d' % len(mine.states))
|
||||
print('Image h/w: %s' % repr(mine.size))
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print("Received error, continuing: %s" % traceback.format_exc())
|
||||
o += "\n {0}: Received error, continuing: {1}".format(minefile, traceback.format_exc())
|
||||
for stateName in mine:
|
||||
if stateName not in states:
|
||||
states.append(stateName)
|
||||
for state in sorted(states):
|
||||
inTheirs = state in theirs
|
||||
inMine = state in mine
|
||||
if inTheirs and not inMine:
|
||||
o += '\n + {1}'.format(minefile, state)
|
||||
if new2mine is not None:
|
||||
new2mine.states[state] = theirsDMI.states[state]
|
||||
elif not inTheirs and inMine:
|
||||
o += '\n - {1}'.format(theirsfile, state)
|
||||
if new2theirs is not None:
|
||||
new2theirs.states[state] = mineDMI.states[state]
|
||||
elif inTheirs and inMine:
|
||||
if theirs[state].ToString() != mine[state].ToString():
|
||||
o += '\n - {0}: {1}'.format(mine[state].displayName(), mine[state].ToString())
|
||||
o += '\n + {0}: {1}'.format(theirs[state].displayName(), theirs[state].ToString())
|
||||
elif kwargs.get('check_changed',True):
|
||||
diff_count=0
|
||||
for i in xrange(len(theirs[state].icons)):
|
||||
theirF = theirs[state].icons[i]
|
||||
myF = theirs[state].icons[i]
|
||||
|
||||
theirData = list(theirF.getdata())
|
||||
myData = list(myF.getdata())
|
||||
#diff = []
|
||||
|
||||
for i in xrange(len(theirData)):
|
||||
dr = theirData[i][0] - myData[i][0]
|
||||
dg = theirData[i][1] - myData[i][1]
|
||||
db = theirData[i][2] - myData[i][2]
|
||||
#diff[idx] = (abs(dr), abs(dg), abs(db))
|
||||
if((dr != 0) or (dg != 0) or (db != 0)):
|
||||
diff_count += 1
|
||||
break
|
||||
if diff_count > 0:
|
||||
o += '\n ! {0}: {1} frames differ'.format(theirs[state].displayName(), diff_count)
|
||||
if new2mine is not None:
|
||||
new2mine.states[state] = theirsDMI.states[state]
|
||||
if new2theirs is not None:
|
||||
new2theirs.states[state] = mineDMI.states[state]
|
||||
if o != '':
|
||||
reportstream.write('\n--- {0}'.format(theirsfile))
|
||||
reportstream.write('\n+++ {0}'.format(minefile))
|
||||
reportstream.write(o)
|
||||
|
||||
if new2mine is not None:
|
||||
if len(new2mine.states) > 0:
|
||||
new2mine.save(new2mineFilename)
|
||||
else:
|
||||
if os.path.isfile(new2mineFilename):
|
||||
os.remove(new2mineFilename)
|
||||
#print('RM {0}'.format(new2mineFilename))
|
||||
if new2theirs is not None:
|
||||
if len(new2theirs.states) > 0:
|
||||
new2theirs.save(new2theirsFilename)
|
||||
else:
|
||||
if os.path.isfile(new2theirsFilename):
|
||||
os.remove(new2theirsFilename)
|
||||
#print('RM {0}'.format(new2theirsFilename))
|
||||
|
||||
def cleanup(subject):
|
||||
print('Cleaning...')
|
||||
for root, _, filenames in os.walk(subject):
|
||||
for filename in fnmatch.filter(filenames, '*.new.dmi'):
|
||||
path = os.path.join(root, filename)
|
||||
print('RM {0}'.format(path))
|
||||
os.remove(path)
|
||||
|
||||
def disassemble_all(in_dir, out_dir, parser):
|
||||
print('D_A %s -> %s' % (in_dir, out_dir))
|
||||
for root, dirnames, filenames in os.walk(out_dir):
|
||||
for filename in fnmatch.filter(filenames, '*.new.dmi'):
|
||||
path = os.path.join(root, filename)
|
||||
print('RM {0}'.format(path))
|
||||
os.remove(path)
|
||||
for root, dirnames, filenames in os.walk(in_dir):
|
||||
for filename in fnmatch.filter(filenames, '*.dmi'):
|
||||
path = os.path.join(root, filename)
|
||||
to = os.path.join(out_dir, path.replace(in_dir, '').replace(os.path.basename(path), ''))
|
||||
disassemble(path, to, parser)
|
||||
|
||||
|
||||
def compare_all(in_dir, out_dir, report, parser, **kwargs):
|
||||
with open(report, 'w') as report:
|
||||
report.write('# DMITool Difference Report: {0} {1}'.format(os.path.abspath(in_dir), os.path.abspath(out_dir)))
|
||||
for root, dirnames, filenames in os.walk(in_dir):
|
||||
for filename in fnmatch.filter(filenames, '*.dmi'):
|
||||
path = os.path.join(root, filename)
|
||||
to = os.path.join(out_dir, path.replace(in_dir, '').replace(os.path.basename(path), ''))
|
||||
to = os.path.join(to, filename)
|
||||
path = os.path.abspath(path)
|
||||
to = os.path.abspath(to)
|
||||
compare(path, to, parser, report, **kwargs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,77 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on Jan 5, 2014
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import os, sys, argparse
|
||||
from byond.basetypes import Atom, Proc
|
||||
from byond import objtree, GetFilesFromDME
|
||||
|
||||
def processFile(tree, origin, destination, args):
|
||||
atomsWritten=[]
|
||||
origin = os.path.relpath(origin)
|
||||
with open(destination, 'w') as f:
|
||||
print('>>> {0}'.format(destination))
|
||||
if args.reorganize:
|
||||
for ak in sorted(tree.Atoms.keys()):
|
||||
atom = tree.Atoms[ak]
|
||||
for a in atomsWritten:
|
||||
if atom.path.startswith(a): continue
|
||||
#if atom.filename.replace(os.sep,'/') == sys.argv[2]:
|
||||
if atom.filename == origin:
|
||||
f.write(atom.DumpCode())
|
||||
atomsWritten+=[atom.path]
|
||||
else:
|
||||
for thing in tree.fileLayouts[origin]:
|
||||
ttype = thing[0]
|
||||
if ttype == 'ATOMDEF':
|
||||
f.write(thing[1] + '\n')
|
||||
elif ttype == 'PROCDEF':
|
||||
proc = tree.GetAtom(thing[1])
|
||||
f.write(proc.DumpCode() + '\n')
|
||||
elif ttype == 'VAR':
|
||||
atom = tree.GetAtom(thing[1])
|
||||
var = atom.properties[thing[2]]
|
||||
f.write('\t{}\n'.format(var.DumpCode(thing[2])))
|
||||
elif ttype == 'DEFINE':
|
||||
name = thing[1]
|
||||
value = thing[2]
|
||||
f.write('#define {} {}\n'.format(name, value))
|
||||
elif ttype == 'UNDEF':
|
||||
name = thing[1]
|
||||
f.write('#undef {}\n'.format(name))
|
||||
elif ttype == 'COMMENT':
|
||||
continue
|
||||
else:
|
||||
print('wot is ' + ttype + '?')
|
||||
if __name__ == '__main__':
|
||||
|
||||
opt = argparse.ArgumentParser()
|
||||
opt.add_argument('project', metavar="project.dme")
|
||||
opt.add_argument('file', metavar="file.dm", default=None, nargs='?')
|
||||
opt.add_argument('--reorganize', dest='reorganize', default=False, action='store_true', help="Reorganize the file's contents, instead of keeping current structure.")
|
||||
opt.add_argument('--output','-o', dest='output', default='', help="Where to put the output (default: <file>.fixed)")
|
||||
|
||||
args = opt.parse_args()
|
||||
|
||||
tree = objtree.ObjectTree(preprocessor_directives=True)
|
||||
tree.ProcessFilesFromDME(args.project)
|
||||
|
||||
atomsWritten = []
|
||||
|
||||
if args.file is not None and os.path.isfile(args.file):
|
||||
output=args.output
|
||||
if output=='':
|
||||
output=args.file+'.fixed'
|
||||
processFile(tree, args.file, output, args)
|
||||
else:
|
||||
for filename in GetFilesFromDME(args.project):
|
||||
fixpath = filename.replace('code' + os.sep, 'code-indented' + os.sep)
|
||||
fixpath = fixpath.replace('interface' + os.sep, 'interface-indented' + os.sep)
|
||||
fixpath = fixpath.replace('RandomZLevels' + os.sep, 'RandomZLevels-indented' + os.sep)
|
||||
fixdir = os.path.dirname(fixpath)
|
||||
if not os.path.isdir(fixdir):
|
||||
os.makedirs(fixdir)
|
||||
fixpath = fixpath.replace('/', os.sep)
|
||||
processFile(tree, filename, fixpath,args)
|
||||
@@ -1,229 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
dmm.py - Collection of map tools.
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
import sys, argparse, os
|
||||
from byond import ObjectTree, Map, MapRenderFlags
|
||||
|
||||
def main():
|
||||
opt = argparse.ArgumentParser() # version='0.1')
|
||||
opt.add_argument('--project', default='baystation12.dme', type=str, help='Project file.', metavar='environment.dme')
|
||||
|
||||
command = opt.add_subparsers(help='The command you wish to execute', dest='MODE')
|
||||
|
||||
_compare = command.add_parser('diff', help='Compare two map files and generate a map patch.')
|
||||
_compare.add_argument('theirs', type=str, help='One side of the difference', metavar='theirs.dmm')
|
||||
_compare.add_argument('mine', type=str, help='The other side.', metavar='mine.dmm')
|
||||
_compare.add_argument('-O', '--output', dest='output', type=str, help='The other side.', metavar='mine.dmm')
|
||||
|
||||
#_compare = command.add_parser('patch', help='Apply a map patch.')
|
||||
#_compare.add_argument('theirs', type=str, help='One side of the difference', metavar='theirs.dmm')
|
||||
#_compare.add_argument('mine', type=str, help='The other side.', metavar='mine.dmm')
|
||||
|
||||
_compare = command.add_parser('analyze', help='Generate a report of each atom on a map. WARNING: huge')
|
||||
_compare.add_argument('map', type=str, help='Map to analyze.', metavar='map.dmm')
|
||||
|
||||
opt.add_argument('map', type=str, help='Map to fix.', metavar='map.dmm')
|
||||
|
||||
args = opt.parse_args()
|
||||
if args.MODE == 'compare':
|
||||
compare_dmm(args)
|
||||
elif args.MODE == 'analyze':
|
||||
analyze_dmm(args)
|
||||
#elif args.MODE == 'patch':
|
||||
# patch_dmm(args)
|
||||
else:
|
||||
print('!!! Error, unknown MODE=%r' % args.MODE)
|
||||
|
||||
def compare_dmm(args):
|
||||
if not os.path.isfile(args.theirs):
|
||||
print('File {0} does not exist.'.format(args.theirs))
|
||||
sys.exit(1)
|
||||
if not os.path.isfile(args.mine):
|
||||
print('File {0} does not exist.'.format(args.mine))
|
||||
sys.exit(1)
|
||||
if not os.path.isfile(args.project):
|
||||
print('DM Environment File {0} does not exist.'.format(args.project))
|
||||
sys.exit(1)
|
||||
|
||||
theirs_dmm = Map(forgiving_atom_lookups=True)
|
||||
theirs_dmm.readMap(args.theirs)
|
||||
|
||||
mine_dmm = Map(forgiving_atom_lookups=True)
|
||||
mine_dmm.readMap(args.mine)
|
||||
|
||||
if theirs_dmm.width != mine_dmm.width:
|
||||
print('Width is not equal: {} != {}.'.format(theirs_dmm.width, mine_dmm.width))
|
||||
sys.exit(1)
|
||||
if theirs_dmm.height != mine_dmm.height:
|
||||
print('Height is not equal: {} != {}.'.format(theirs_dmm.height, mine_dmm.height))
|
||||
sys.exit(1)
|
||||
|
||||
ttitle, _ = os.path.splitext(os.path.basename(args.theirs))
|
||||
mtitle, _ = os.path.splitext(os.path.basename(args.mine))
|
||||
|
||||
output = '{} - {}.dmmpatch'.format(ttitle, mtitle)
|
||||
if args.output:
|
||||
output = args.output
|
||||
with open(output, 'w') as f:
|
||||
stats = {
|
||||
'diffs':0,
|
||||
'tilediffs':0
|
||||
}
|
||||
print('Comparing maps...')
|
||||
for z in range(len(theirs_dmm.zLevels)):
|
||||
for y in range(theirs_dmm.height):
|
||||
for x in range(theirs_dmm.width):
|
||||
CHANGES = {}
|
||||
|
||||
tTile = theirs_dmm.GetTileAt(x, y, z)
|
||||
mTile = mine_dmm.GetTileAt(x, y, z)
|
||||
|
||||
theirs = tTile.GetAtoms()
|
||||
mine = mTile.GetAtoms()
|
||||
|
||||
for atom in theirs + mine:
|
||||
key = atom.MapSerialize()
|
||||
change = None
|
||||
if atom not in mine:
|
||||
change = '-'
|
||||
if atom not in theirs:
|
||||
change = '+'
|
||||
if change is not None:
|
||||
CHANGES[key] = change
|
||||
|
||||
if len(CHANGES) > 0:
|
||||
f.write('<{},{},{}>\n'.format(x, y, z))
|
||||
stats['tilediffs'] += 1
|
||||
for key, change in CHANGES.items():
|
||||
f.write(' {} {}\n'.format(change, key))
|
||||
stats['diffs'] += 1
|
||||
print('Compared maps: {} differences in {} tiles.'.format(stats['diffs'],stats['tilediffs']))
|
||||
|
||||
|
||||
def analyze_dmm(args):
|
||||
tmpl_head = '''
|
||||
<html>
|
||||
<head>
|
||||
<title>BYONDTools Map Analysis :: {TITLE}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{TITLE}</h1>
|
||||
<ul>
|
||||
<li><a href="{ROOT}/instances/index.html">Instances</a></li>
|
||||
<li><a href="{ROOT}/index.html">Tiles</a></li>
|
||||
</ul>'''
|
||||
tmpl_footer = '''
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
presentable_attributes=[
|
||||
'path',
|
||||
'id',
|
||||
'filename',
|
||||
'line'
|
||||
]
|
||||
|
||||
def MakePage(**kwargs):
|
||||
rewt = '.'
|
||||
depth = kwargs.get('depth', 0)
|
||||
if depth > 0:
|
||||
rewt = '/'.join(['..'] * depth)
|
||||
title = kwargs.get('title', 'LOL NO TITLE')
|
||||
body = kwargs.get('body', '')
|
||||
return (tmpl_head + body + tmpl_footer).replace('{TITLE}', title).replace('{ROOT}', rewt)
|
||||
|
||||
if not os.path.isfile(args.project):
|
||||
print('DM Environment file {0} does not exist.'.format(args.theirs))
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.isfile(args.map):
|
||||
print('Map {0} does not exist.'.format(args.theirs))
|
||||
sys.exit(1)
|
||||
|
||||
tree = ObjectTree()
|
||||
tree.ProcessFilesFromDME(args.project)
|
||||
dmm = Map(tree)
|
||||
dmm.readMap(args.map)
|
||||
|
||||
basedir = os.path.join(os.path.dirname(args.project), 'analysis', os.path.basename(args.map))
|
||||
|
||||
if not os.path.isdir(basedir):
|
||||
os.makedirs(os.path.join(basedir,'instances'))
|
||||
os.makedirs(os.path.join(basedir,'tiles'))
|
||||
|
||||
# Dump instances
|
||||
instance_info = {}
|
||||
for atom in dmm.instances:
|
||||
if atom.path not in instance_info:
|
||||
instance_info[atom.path] = []
|
||||
instance_info[atom.path] += [atom.id]
|
||||
|
||||
with open(os.path.join(basedir, 'instances', str(atom.id) + '.html'), 'w') as f:
|
||||
body = '<h2>Atom Data:</h2><table class="prettytable"><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody>'
|
||||
for attr in presentable_attributes:
|
||||
body += '<tr><th>{0}</th><td>{1}</td></tr>'.format(attr, getattr(atom, attr, None))
|
||||
body += '</tbody></table>'
|
||||
|
||||
body += '<h2>Map-Specified Properties:</h2><table class="prettytable"><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody>'
|
||||
for attr_name in atom.mapSpecified:
|
||||
body += '<tr><th>{0}</th><td>{1}</td></tr>'.format(attr_name, atom.getProperty(attr_name, None))
|
||||
body += '</tbody></table>'
|
||||
|
||||
body += '<h2>All Properties:</h2><table class="prettytable"><thead><tr><th>Name</th><th>Value</th><th>File/Line</th></tr></thead><tbody>'
|
||||
for attr_name in sorted(atom.properties.keys()):
|
||||
attr = atom.properties[attr_name]
|
||||
body += '<tr><th>{0}</th><td>{1}</td><td>{2}:{3}</td></tr>'.format(attr_name, attr.value, attr.filename, attr.line)
|
||||
body += '</tbody></table>'
|
||||
f.write(MakePage(title='Instance #{0}'.format(atom.id), depth=1, body=body))
|
||||
with open(os.path.join(basedir, 'instances', 'index.html'), 'w') as idx:
|
||||
body = '<ul>'
|
||||
for atype, instances in instance_info.items():
|
||||
body += '<li><b>{0}</b><ul>'.format(atype)
|
||||
for iid in instances:
|
||||
body += '<li><a href="{{ROOT}}/instances/{0}.html">#{0}</a></li>'.format(iid)
|
||||
body += '</ul></li>'
|
||||
body += "</ul>"
|
||||
idx.write(MakePage(title='Instance Index'.format(atom.id), depth=1, body=body))
|
||||
|
||||
# Tiles
|
||||
with open(os.path.join(basedir, 'index.html'), 'w') as f:
|
||||
body = '<table class="prettytable"><thead><tr><th>Icon</th><th>ID</th><th>Instances</th></tr></thead><tbody>'
|
||||
for tile in dmm.tileTypes:
|
||||
body += '<tr><td><img src="tiles/{0}.png" height="96" width="96" /></td><th>{0}</th><td><ul>'.format(tile.ID)
|
||||
for atom in tile.SortAtoms():
|
||||
body += '<li><a href="{{ROOT}}/instances/{0}.html">#{0}</a> - {1}</li>'.format(atom.id,atom.path)
|
||||
body += '</ul></td></tr>'
|
||||
img = tile.RenderToMapTile(0, os.path.dirname(sys.argv[1]), MapRenderFlags.RENDER_STARS)
|
||||
if img is None: continue
|
||||
pass_2 = tile.RenderToMapTile(1, os.path.dirname(sys.argv[1]), 0)
|
||||
if pass_2 is not None:
|
||||
img.paste(pass_2,(0,0,96,96),pass_2)
|
||||
img.save(os.path.join(basedir, 'tiles', '{0}.png'.format(tile.ID)), 'PNG')
|
||||
body += '</tbody></table>'
|
||||
f.write(MakePage(title='Tile Index'.format(atom.id), depth=0, body=body))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,120 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
fixMap.py - Apply various fixes to a map.
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
import sys, argparse
|
||||
from byond.map import Map
|
||||
from byond.objtree import ObjectTree
|
||||
#from byond.basetypes import BYONDString, BYONDValue, Atom, PropertyFlags
|
||||
#from byond.directions import *
|
||||
|
||||
from byond import mapfixes
|
||||
|
||||
|
||||
opt = argparse.ArgumentParser() # version='0.1')
|
||||
opt.add_argument('-n', '--namespace', dest='namespaces', type=str, nargs='*', default=[], help='MapFix namespace to load (ss13, vgstation).')
|
||||
opt.add_argument('-N', '--no-deps', dest='no_dependencies', action='store_true', help='Stop loading of namespace dependencies.')
|
||||
opt.add_argument('-f', '--fix-script', dest='fixscripts', type=str, nargs='*', help='A script that specifies property and type replacements.')
|
||||
|
||||
opt.add_argument('dme', nargs='?', default='baystation12.dme', type=str,help='Project file.', metavar='environment.dme')
|
||||
opt.add_argument('map', type=str,help='Map to fix.', metavar='map.dmm')
|
||||
|
||||
args = opt.parse_args()
|
||||
|
||||
actions = []
|
||||
|
||||
mapfixes.Load()
|
||||
actions += mapfixes.GetFixesForNS(args.namespaces, not args.no_dependencies)
|
||||
|
||||
tree = ObjectTree()
|
||||
tree.ProcessFilesFromDME(args.dme)
|
||||
|
||||
for fixscript in args.fixscripts:
|
||||
with open(fixscript, 'r') as repl:
|
||||
ln = 0
|
||||
errors = 0
|
||||
for line in repl:
|
||||
ln += 1
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
if line.strip() == '':
|
||||
continue
|
||||
# PROPERTY: step_x > pixel_x
|
||||
# TYPE: /obj/item/key > /obj/item/weapon/key/janicart
|
||||
subject, action = line.split(':')
|
||||
subject = subject.lower()
|
||||
if subject == 'property':
|
||||
old, new = action.split('>')
|
||||
actions += [mapfixes.base.RenameProperty(old.strip(), new.strip())]
|
||||
if subject == 'type' or subject == 'type!':
|
||||
force = subject == 'type!'
|
||||
old, new = action.split('>')
|
||||
newtype = new.strip()
|
||||
if tree.GetAtom(newtype) is None:
|
||||
print('{0}:{1}: {2}'.format(sys.argv[2], ln, line.strip('\r\n')))
|
||||
print(' ERROR: Unable to find replacement type "{0}".'.format(newtype))
|
||||
errors += 1
|
||||
actions += [mapfixes.base.ChangeType(old.strip(), newtype, force)]
|
||||
if errors > 0:
|
||||
print('!!! {0} errors, please fix them.'.format(errors))
|
||||
sys.exit(1)
|
||||
print('Changes to make:')
|
||||
for action in actions:
|
||||
print(' * ' + str(action))
|
||||
dmm = Map(tree, forgiving_atom_lookups=1)
|
||||
dmm.readMap(args.map)
|
||||
dmm.writeMap2(args.map.replace('.dmm', '.dmm2'))
|
||||
for iid in xrange(len(dmm.instances)):
|
||||
atom = dmm.getInstance(iid)
|
||||
changes = []
|
||||
for action in actions:
|
||||
action.SetTree(tree)
|
||||
if action.Matches(atom):
|
||||
atom = action.Fix(atom)
|
||||
changes += [str(action)]
|
||||
atom.id = iid
|
||||
|
||||
'''
|
||||
compiled_atom = tree.GetAtom(atom.path)
|
||||
if compiled_atom is not None:
|
||||
for propname in list(atom.properties.keys()):
|
||||
if propname not in compiled_atom.properties and propname not in ('req_access_txt','req_one_access_txt'):
|
||||
del atom.properties[propname]
|
||||
if propname in atom.mapSpecified:
|
||||
atom.mapSpecified.remove(propname)
|
||||
changes += ['Dropped property {0} (not found in compiled atom)'.format(propname)]
|
||||
'''
|
||||
dmm.setInstance(iid, atom)
|
||||
if len(changes) > 0:
|
||||
print('{0} (#{1}):'.format(atom.path, atom.id))
|
||||
for change in changes:
|
||||
print(' * ' + change)
|
||||
#for atom, _ in atomsToFix.items():
|
||||
# print('Atom {0} needs id_tag.'.format(atom))
|
||||
with open(args.map + '.missing', 'w') as f:
|
||||
for atom in sorted(dmm.missing_atoms):
|
||||
f.write(atom + "\n")
|
||||
print('--- Saving...')
|
||||
dmm.writeMap(args.map + '.fixed', Map.WRITE_OLD_IDS)
|
||||
dmm.writeMap2(args.map.replace('.dmm', '.dmm2') + '.fixed')
|
||||
@@ -1,96 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import os, argparse, logging, sys
|
||||
|
||||
# Tell Python where to find BYONDTools.
|
||||
# Assuming we're in icons/mob/in-hand
|
||||
sys.path.append('../../../tools/BYONDTools') # For byond
|
||||
sys.path.append('../../../tools/BYONDTools/scripts') # For dmi
|
||||
|
||||
from byond.objtree import ObjectTree
|
||||
from byond.basetypes import Atom
|
||||
from byond.map import Map, MapRenderFlags
|
||||
"""
|
||||
Usage:
|
||||
$ python dmmrender.py path/to/your/project.dme path/to/your/map.dmm
|
||||
|
||||
generateMap.py - Creates an image of a DMM map.
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def renderMap(args):
|
||||
outfile = args.map + '.{z}.png'
|
||||
if args.area:
|
||||
kwargs['area'] = args.area
|
||||
outfile = args.area[0].replace('/', '_') + '.png'
|
||||
if args.render_types:
|
||||
print(repr(args.render_types))
|
||||
kwargs['render_types'] = args.render_types
|
||||
if args.outfile:
|
||||
outfile = args.outfile
|
||||
if os.path.isdir(outfile):
|
||||
title, _ = os.path.splitext(os.path.basename(args.map))
|
||||
outfile = os.path.join(outfile, '{}.{{z}}.png'.format(title))
|
||||
dmm.generateImage(outfile, os.path.dirname(args.project), renderflags, **kwargs)
|
||||
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s [%(levelname)-8s]: %(message)s',
|
||||
datefmt='%m/%d/%Y %I:%M:%S %p',
|
||||
level=logging.INFO # ,
|
||||
# filename='logs/main.log',
|
||||
# filemode='w'
|
||||
)
|
||||
opt = argparse.ArgumentParser()
|
||||
opt.add_argument('project', metavar="project.dme")
|
||||
opt.add_argument('map', metavar="map.dmm")
|
||||
opt.add_argument('--render-stars', dest='render_stars', default=False, action='store_true', help="Render space. Normally off to prevent ballooning the image size.")
|
||||
opt.add_argument('--render-areas', dest='render_areas', default=False, action='store_true', help="Render area overlays.")
|
||||
opt.add_argument('--render-only', dest='render_types', action='append', help="Render ONLY these types. Can be used multiple times to specify more types.")
|
||||
opt.add_argument('--area', dest='area', type=list, nargs='*', default=None, help="Specify an area to restrict rendering to.")
|
||||
opt.add_argument('-O', '--out', dest='outfile', type=str, default=None, help="What to name the file ({z} will be replaced with z-level)")
|
||||
opt.add_argument('--area-list', dest='areas', type=str, default=None, help="A file with area_file.png = /area/path on each line")
|
||||
args = opt.parse_args()
|
||||
if os.path.isfile(args.project):
|
||||
tree = ObjectTree()
|
||||
tree.ProcessFilesFromDME(args.project)
|
||||
dmm = Map(tree)
|
||||
dmm.readMap(args.map)
|
||||
renderflags = 0
|
||||
if args.render_stars:
|
||||
renderflags |= MapRenderFlags.RENDER_STARS
|
||||
if args.render_areas:
|
||||
renderflags |= MapRenderFlags.RENDER_AREAS
|
||||
kwargs = {}
|
||||
if args.areas:
|
||||
with open(args.areas) as f:
|
||||
for line in f:
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
if '=' not in line:
|
||||
continue
|
||||
outfile, area = line.split('=')
|
||||
args.area = area.strip().split(',')
|
||||
args.outfile = outfile.strip()
|
||||
renderMap(args)
|
||||
else:
|
||||
renderMap(args)
|
||||
@@ -1,210 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
from byond.DMI import DMI,State
|
||||
from byond import directions
|
||||
import os, sys, shutil
|
||||
import ImageChops
|
||||
import math, operator
|
||||
from PIL import Image
|
||||
|
||||
def rmsdiff(im1, im2):
|
||||
"Calculate the root-mean-square difference between two images"
|
||||
diff = ImageChops.difference(im1, im2)
|
||||
h = diff.histogram()
|
||||
sq = (value * (idx ** 2) for idx, value in enumerate(h))
|
||||
sum_of_squares = sum(sq)
|
||||
rms = math.sqrt(sum_of_squares / float(im1.size[0] * im1.size[1]))
|
||||
return rms
|
||||
|
||||
def equal(im1, im2):
|
||||
return ImageChops.difference(im1, im2).getbbox() is None
|
||||
|
||||
quadDefs = [
|
||||
# x1,y1,x2,y2
|
||||
[0, 0, 15, 15],
|
||||
[16, 0, 31, 15],
|
||||
[0, 16, 15, 31],
|
||||
[16, 16, 31, 31]
|
||||
]
|
||||
|
||||
extract = [
|
||||
'floor',
|
||||
# 'redcorner',
|
||||
'white',
|
||||
'dark',
|
||||
'bar',
|
||||
'cafeteria',
|
||||
'redfull',
|
||||
'whiteredfull',
|
||||
'bluefull',
|
||||
'whitebluefull',
|
||||
'greenfull',
|
||||
'whitegreenfull',
|
||||
'yellowfull',
|
||||
'whiteyellowfull',
|
||||
'neutralfull',
|
||||
'orangefull',
|
||||
'purplefull',
|
||||
'whitepurplefull',
|
||||
'floorgrime',
|
||||
'brown',
|
||||
'vaultfull'
|
||||
]
|
||||
|
||||
colors = [
|
||||
'red',
|
||||
'whitered',
|
||||
'blue',
|
||||
'whiteblue',
|
||||
'green',
|
||||
'whitegreen',
|
||||
'yellow',
|
||||
'whiteyellow',
|
||||
'neutral',
|
||||
'orange',
|
||||
'purple',
|
||||
'whitepurple',
|
||||
'grime',
|
||||
'brown',
|
||||
'vault'
|
||||
]
|
||||
|
||||
arrangements={
|
||||
'stripe': [
|
||||
[False,False,True,True], # S
|
||||
[True,True,False,False], # N
|
||||
[False,True,False,True], # E
|
||||
[True,False,True,False], # W
|
||||
[False,True,True,True], # SE
|
||||
[True,False,True,True], # SW
|
||||
[True,True,False,True], # NE
|
||||
[True,True,True,False], # NW
|
||||
],
|
||||
'corner': [
|
||||
[False,False,False,True], # S
|
||||
[True,False,False,False], # N
|
||||
[False,True,False,False], # E
|
||||
[False,False,True,False], # W
|
||||
],
|
||||
'full': [
|
||||
[True,True,True,True]
|
||||
]
|
||||
}
|
||||
|
||||
tileDefs={
|
||||
'white':{
|
||||
'base':'white',
|
||||
'arrangements':['stripe','corner','full'],
|
||||
'colors':['whitered','whiteblue','whitegreen','whitegreen','whiteyellow','whitepurple']
|
||||
},
|
||||
'grey':{
|
||||
'base':'floor',
|
||||
'arrangements':['stripe','corner','full'],
|
||||
'colors':[
|
||||
'red',
|
||||
'blue',
|
||||
'green',
|
||||
'yellow',
|
||||
'neutral',
|
||||
'orange',
|
||||
'purple',
|
||||
'brown',
|
||||
'white'
|
||||
]
|
||||
},
|
||||
'dark':{
|
||||
'base':'dark',
|
||||
'arrangements':['stripe','corner','full'],
|
||||
'colors':[
|
||||
'floor',
|
||||
'red',
|
||||
'blue',
|
||||
'green',
|
||||
'yellow',
|
||||
'neutral',
|
||||
'orange',
|
||||
'purple',
|
||||
'brown',
|
||||
'vault'
|
||||
]
|
||||
}
|
||||
}
|
||||
knownQuads = [
|
||||
{}, {}, {}, {}
|
||||
]
|
||||
def isKnownQuad(i, im, icon_state):
|
||||
for name, kq in knownQuads[i].items():
|
||||
if equal(kq, im):
|
||||
return True
|
||||
return False
|
||||
floors = DMI(sys.argv[1])
|
||||
floors.loadAll()
|
||||
basedir = 'floor_quads'
|
||||
if os.path.isdir('floor_quads'):
|
||||
shutil.rmtree(basedir)
|
||||
os.makedirs('floor_quads')
|
||||
for icon_state in extract:
|
||||
if icon_state not in floors.states:
|
||||
print('Can\'t find state {0}!'.format(icon_state))
|
||||
continue
|
||||
for d in range(floors.states[icon_state].dirs):
|
||||
dirf = 0
|
||||
dirn = 'SOUTH'
|
||||
if floors.states[icon_state].dirs > 1:
|
||||
dirf = directions.IMAGE_INDICES[d]
|
||||
dirn = directions.getNameFromDir(dirf)
|
||||
print('{0} {1} {2}'.format(icon_state, dirn, floors.states[icon_state].dirs))
|
||||
img = floors.getFrame(icon_state, dirf, 0)
|
||||
for i in range(len(quadDefs)):
|
||||
quad = img.crop(quadDefs[i])
|
||||
if isKnownQuad(i, quad, icon_state):
|
||||
print(' Skipping quad #{}'.format(i + 1))
|
||||
continue
|
||||
color = icon_state
|
||||
if color.endswith('full'):
|
||||
color = color[:-4]
|
||||
qpath = os.path.join(basedir, str(i))
|
||||
qfile = os.path.join(qpath, '{0}.png'.format(color))
|
||||
if not os.path.isdir(qpath):
|
||||
os.makedirs(qpath)
|
||||
quad.save(qfile, 'PNG')
|
||||
knownQuads[i][color] = quad
|
||||
|
||||
nfloors = DMI('nfloors.dmi')
|
||||
for tileName,tileDef in tileDefs.items():
|
||||
base = floors.getFrame(tileDef['base'],directions.SOUTH,0)
|
||||
for color in tileDef['colors']:
|
||||
for arrangement in tileDef['arrangements']:
|
||||
arrname=''
|
||||
arrange=[False,False,False,False]
|
||||
if isinstance(arrangement,str):
|
||||
arrange=arrangements[arrangement]
|
||||
arrname=arrangement
|
||||
elif isinstance(arrangement,list):
|
||||
arrange=arrangement[1:]
|
||||
arrname=arrangement[0]
|
||||
state='{base} {color} {arrangement}'.format(base=tileDef['base'],color=color,arrangement=arrname)
|
||||
nstate=State(state)
|
||||
nstate.dirs=len(arrange)
|
||||
nstate.frames=1
|
||||
nstate.icons=[None for _ in range(nstate.dirs)]
|
||||
#statedebug = DMI(state+'.dmi')
|
||||
nfloors.states[state]=nstate
|
||||
for d in range(len(arrange)):
|
||||
cmap = arrange[d]
|
||||
dirf = 0
|
||||
dirn = 'SOUTH'
|
||||
if len(arrange) > 1:
|
||||
dirf = directions.IMAGE_INDICES[d]
|
||||
dirn = directions.getNameFromDir(dirf)
|
||||
print(' Generating state {0} ({1})...'.format(repr(state),dirn))
|
||||
#print(repr(arrange))
|
||||
img=Image.new('RGBA',(32,32))
|
||||
img.paste(base)
|
||||
for i in range(len(cmap)):
|
||||
bbox=quadDefs[i]
|
||||
if cmap[i]:
|
||||
img.paste(knownQuads[i][color],bbox)
|
||||
nfloors.setFrame(state, dirf, 0, img)
|
||||
#statedebug.states[state]=nfloors.states[state]
|
||||
#statedebug.save(state+'.dmi')
|
||||
nfloors.save('nfloors.dmi')
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on Feb 28, 2014 to test a bug in DreamMaker.
|
||||
|
||||
Requires arial font.
|
||||
'''
|
||||
from byond.DMI import DMI, State
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
def makeDMI():
|
||||
dmi = DMI('state_limit.dmi')
|
||||
#
|
||||
for i in range(513):
|
||||
# Make a new tile
|
||||
img = Image.new('RGBA', (32, 32))
|
||||
# Set up PIL's drawing stuff
|
||||
draw = ImageDraw.Draw(img)
|
||||
# Define a font.
|
||||
font = ImageFont.truetype('arial.ttf', 10)
|
||||
# Draw the tile number
|
||||
draw.text((10, 0), str(i + 1), (0, 0, 0), font=font)
|
||||
# Make state
|
||||
state_name='state {0}'.format(i+1)
|
||||
state=State(state_name)
|
||||
state.dirs=1
|
||||
state.frames=1
|
||||
state.icons=[img]
|
||||
# Add state to DMI
|
||||
dmi.states[state_name]=state
|
||||
#save
|
||||
dmi.save('state_limit.dmi', sort=False)
|
||||
if __name__ == '__main__':
|
||||
makeDMI()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on Apr 29, 2014
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import argparse,os
|
||||
|
||||
from byond.objtree import ObjectTree
|
||||
from byond.basetypes import Proc
|
||||
|
||||
def dumpSubTypes(atom):
|
||||
print('{}:{}: {}'.format(atom.filename,atom.line,atom.path))
|
||||
for rpath,catom in atom.children.items():
|
||||
if not isinstance(catom,Proc):
|
||||
dumpSubTypes(catom)
|
||||
|
||||
if __name__ == '__main__':
|
||||
opt = argparse.ArgumentParser()
|
||||
opt.add_argument('project', metavar="project.dme")
|
||||
opt.add_argument('--subtypes',type=str,help="List all subtypes of the given type")
|
||||
args = opt.parse_args()
|
||||
if os.path.isfile(args.project):
|
||||
tree = ObjectTree()
|
||||
tree.ProcessFilesFromDME(args.project)
|
||||
if args.subtypes:
|
||||
atom = tree.GetAtom(args.subtypes)
|
||||
dumpSubTypes(atom)
|
||||
@@ -1,121 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import sys, re
|
||||
from byond.basetypes import Proc
|
||||
from byond.objtree import ObjectTree
|
||||
|
||||
class CodeScan:
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
self.atom = None
|
||||
self.proc = None
|
||||
|
||||
def SetContext(self, atom, proc):
|
||||
self.atom = atom
|
||||
self.proc = proc
|
||||
|
||||
def MatchAtom(self, atom):
|
||||
return True
|
||||
|
||||
def MatchProc(self, atom, proc):
|
||||
return True
|
||||
|
||||
def ScanLine(self, line):
|
||||
return []
|
||||
|
||||
class RegexScanner(CodeScan):
|
||||
def __init__(self, id, regex, warning, in_procnames=()):
|
||||
CodeScan.__init__(self, id)
|
||||
self.regex = regex
|
||||
self.warning = warning
|
||||
self.in_procnames = in_procnames
|
||||
|
||||
def MatchProc(self, atom, proc):
|
||||
# print(proc.path)
|
||||
return self.in_procnames == () or proc.name in self.in_procnames
|
||||
|
||||
def ScanLine(self, line):
|
||||
m = self.regex.search(line)
|
||||
if m is not None:
|
||||
return [self.warning]
|
||||
return []
|
||||
|
||||
rules = [
|
||||
RegexScanner(
|
||||
id='sleep-in-process',
|
||||
warning='sleep() should not be used in process().',
|
||||
regex=re.compile(r'\bsleep\(([0-9]+)\)\b'),
|
||||
in_procnames=('process')
|
||||
),
|
||||
RegexScanner(
|
||||
id='spawn-in-process',
|
||||
warning='spawn() should not be used in process().',
|
||||
regex=re.compile(r'\bspawn(\(([0-9]*)\))?\b'),
|
||||
in_procnames=('process')
|
||||
),
|
||||
RegexScanner(
|
||||
id='del-in-ex_act',
|
||||
warning='del() should not be used in ex_act(). Consider replacing with qdel.',
|
||||
regex=re.compile(r'\bdel(\(.*\))?\b'),
|
||||
in_procnames=('ex_act')
|
||||
),
|
||||
]
|
||||
|
||||
otr = ObjectTree()
|
||||
otr.ProcessFilesFromDME(sys.argv[1], '.dm')
|
||||
procs = 0
|
||||
alerts = 0
|
||||
for path in otr.Atoms:
|
||||
atom = otr.GetAtom(path)
|
||||
if isinstance(atom,Proc): continue
|
||||
proceed = False
|
||||
skipping = []
|
||||
for rule in rules:
|
||||
if rule.MatchAtom(atom):
|
||||
proceed = True
|
||||
else:
|
||||
skipping += [rule]
|
||||
if not proceed: continue
|
||||
for childName in atom.children:
|
||||
warnings = {}
|
||||
child = atom.children[childName]
|
||||
if isinstance(child, Proc):
|
||||
proceed = False
|
||||
for rule in rules:
|
||||
if rule not in skipping and rule.MatchProc(atom, child):
|
||||
proceed = True
|
||||
else:
|
||||
skipping += [rule]
|
||||
if not proceed: continue
|
||||
|
||||
'''
|
||||
if 'process' in path + ' - ' + childName:
|
||||
print(path + ' - ' + childName)
|
||||
'''
|
||||
# print(path + ' - ' + childName)
|
||||
procs += 1
|
||||
min_indent = child.getMinimumIndent()
|
||||
# Should be 1, so find the difference.
|
||||
indent_delta = 1 - min_indent
|
||||
for i in range(len(child.code)):
|
||||
line_warnings = []
|
||||
indent, code = child.code[i]
|
||||
indent = max(1, indent + indent_delta)
|
||||
if code.strip() == '':
|
||||
o = '\n'
|
||||
else:
|
||||
o = (indent * '\t') + code.strip() + '\n'
|
||||
code = o.strip('\n\r')
|
||||
for rule in rules:
|
||||
if rule in skipping: continue
|
||||
rule.SetContext(atom, child)
|
||||
line_warnings += rule.ScanLine(code)
|
||||
if len(line_warnings):
|
||||
warnings['{0}:{1}: {2}'.format(child.filename, child.line + i, code)] = line_warnings
|
||||
alerts += len(line_warnings)
|
||||
if len(warnings) > 0:
|
||||
print('IN {0}/{1}:'.format(path, childName))
|
||||
for context in warnings:
|
||||
print(' {0}'.format(context))
|
||||
for warning in warnings[context]:
|
||||
print(' WARNING: {0}'.format(warning))
|
||||
print('{0} processed procs, {1} alerts raised'.format(procs, alerts))
|
||||
@@ -1,83 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Run within icons/mob/in-hand.
|
||||
|
||||
Usage:
|
||||
$ cd icons/mob/in-hands
|
||||
$ python ss13_makeinhands.py
|
||||
|
||||
ss13_makeinhands.py - Generates a large DMI from several smaller DMIs.
|
||||
Specifically used for making icons/mob/items_(left|right)hand.dmi
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
'''
|
||||
import os, sys, logging
|
||||
|
||||
ToBuild = {
|
||||
# ' file to build': 'directory to pull from/',
|
||||
'../items_lefthand.dmi': 'left/',
|
||||
'../items_righthand.dmi': 'right/'
|
||||
}
|
||||
|
||||
# Tell Python where to find BYONDTools.
|
||||
# Assuming we're in icons/mob/in-hand
|
||||
sys.path.append('../../../tools/BYONDTools') # For byond
|
||||
sys.path.append('../../../tools/BYONDTools/scripts') # For dmi
|
||||
|
||||
from byond.DMI import DMI
|
||||
from dmi import compare_all
|
||||
|
||||
def buildDMI(directory, output):
|
||||
dmi = DMI(output)
|
||||
logging.info('Creating {0}...'.format(output))
|
||||
for root, _, files in os.walk(directory):
|
||||
for filename in files:
|
||||
if filename.endswith('.dmi') and not filename.endswith('.new.dmi'):
|
||||
filepath = os.path.join(root, filename)
|
||||
logging.info('Adding {0}...'.format(filename, output))
|
||||
subdmi = DMI(filepath)
|
||||
subdmi.loadAll()
|
||||
if subdmi.icon_height != 32 or subdmi.icon_width != 32:
|
||||
logging.warn('Skipping {0} - Invalid icon size.'.format(filepath))
|
||||
changes = 0
|
||||
for state_name in subdmi.states:
|
||||
if state_name in dmi.states:
|
||||
logging.warn('Skipping state {0}:{1} - State exists.'.format(filepath, subdmi.states[state_name].displayName()))
|
||||
continue
|
||||
dmi.states[state_name] = subdmi.states[state_name]
|
||||
changes += 1
|
||||
logging.info('Added {0} states.'.format(changes))
|
||||
# save
|
||||
logging.info('Saving {0} states to {1}...'.format(len(dmi.states), output))
|
||||
dmi.save(output)
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s [%(levelname)-8s]: %(message)s',
|
||||
datefmt='%m/%d/%Y %I:%M:%S %p',
|
||||
level=logging.INFO # ,
|
||||
# filename='logs/main.log',
|
||||
# filemode='w'
|
||||
)
|
||||
# Cheating, but useful for checking for unsync'd stuff
|
||||
compare_all('left/', 'right/', 'in-hand_sync_report.txt', None, newfile_theirs=False, newfile_mine=False, check_changed=False)
|
||||
for output, input_dir in ToBuild.items():
|
||||
buildDMI(input_dir, output)
|
||||
@@ -1,209 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import os, sys
|
||||
"""
|
||||
Usage:
|
||||
$ python countstrings.py path/to/your.dme .dm
|
||||
|
||||
CountStrings.py - Counts strings in DreamMaker code
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
def CountStringsIn(filename):
|
||||
with open(filename, 'r') as f:
|
||||
with open(filename + '.str', 'w') as debug:
|
||||
numStrings = 0
|
||||
inString = False
|
||||
inMegaString = False
|
||||
blockCommentLevel = 0
|
||||
embeddedLevel = 0
|
||||
lastChar = ''
|
||||
escaped = False
|
||||
buffer = ''
|
||||
while(True):
|
||||
c = f.read(1)
|
||||
if not c:
|
||||
if inString:
|
||||
print('{0}: UNTERMINATED STRING!'.format(filename))
|
||||
return numStrings
|
||||
if not inString:
|
||||
if c == '/':
|
||||
if lastChar == '/' and blockCommentLevel == 0:
|
||||
# debug.write("[LINECOMMENT:{0}]".format(f.tell()))
|
||||
# Seek to EOL.
|
||||
while(c not in '\r\n'):
|
||||
c = f.read(1)
|
||||
# debug.write("[ENDCOMMENT:{0}]".format(f.tell()))
|
||||
lastChar = ''
|
||||
continue
|
||||
if c == '*':
|
||||
if lastChar == '/':
|
||||
# debug.write("[BLOCKCOMMENT:{0}]".format(f.tell()))
|
||||
blockCommentLevel += 1
|
||||
while(blockCommentLevel > 0):
|
||||
c = f.read(1)
|
||||
if not c:
|
||||
return numStrings
|
||||
if c == '*':
|
||||
if lastChar == '/':
|
||||
blockCommentLevel += 1
|
||||
elif c == '/':
|
||||
if lastChar == '*':
|
||||
blockCommentLevel -= 1
|
||||
lastChar = c
|
||||
# debug.write("[ENDCOMMENT:{0}]".format(f.tell()))
|
||||
lastChar = ''
|
||||
continue
|
||||
elif c == '"':
|
||||
if lastChar == '{':
|
||||
# debug.write("[MEGASTRING:{0}]".format(f.tell()))
|
||||
inString = True
|
||||
inMegaString = True
|
||||
continue
|
||||
else:
|
||||
inString = True
|
||||
# debug.write("[NEWSTRING:{0}]".format(f.tell()))
|
||||
inMegaString = False
|
||||
continue
|
||||
elif c == '{':
|
||||
lastChar = c
|
||||
continue
|
||||
else:
|
||||
lastChar = c
|
||||
else:
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
escaped = False
|
||||
# debug.write("[ESCAPE:{0}]".format(repr(c)))
|
||||
if inString:
|
||||
buffer += '\\' + c
|
||||
lastChar = c
|
||||
continue
|
||||
if c in ('[', ']'):
|
||||
if c == '[':
|
||||
embeddedLevel += 1
|
||||
else:
|
||||
embeddedLevel -= 1
|
||||
buffer += c # +"<{0}>".format(str(embeddedLevel))
|
||||
lastChar = c
|
||||
continue
|
||||
if embeddedLevel > 0:
|
||||
buffer += c
|
||||
lastChar = c
|
||||
continue
|
||||
if inMegaString:
|
||||
if c == '}' and lastChar == '"':
|
||||
# debug.write("[ENDMEGASTRING]")
|
||||
inString = False
|
||||
inMegaString = False
|
||||
escaped = False
|
||||
numStrings += 1
|
||||
debug.write("\n[{0}]={1}".format(numStrings, repr(buffer)))
|
||||
buffer = ''
|
||||
continue
|
||||
else:
|
||||
if c == '"':
|
||||
inString = False
|
||||
# debug.write("[ENDSTRING:{0}]".format(f.tell()))
|
||||
numStrings += 1
|
||||
escaped = False
|
||||
debug.write("\n[{0}]={1}".format(numStrings, repr(buffer)))
|
||||
buffer = ''
|
||||
continue
|
||||
buffer += c
|
||||
lastChar = c
|
||||
return numStrings
|
||||
|
||||
def ProcessFiles(top='.', ext='.dm'):
|
||||
numStringsTotal = 0
|
||||
numStrings = 0
|
||||
numFilesTotal = 0
|
||||
maxStringsInFile = [0, '']
|
||||
for root, _, files in os.walk(top):
|
||||
for filename in files:
|
||||
filepath = os.path.join(root, filename)
|
||||
if filepath.endswith(ext):
|
||||
numStrings = CountStringsIn(filepath)
|
||||
numStringsTotal += numStrings
|
||||
if numStrings > maxStringsInFile[0]:
|
||||
maxStringsInFile = [numStrings, filepath]
|
||||
numFilesTotal += 1
|
||||
print(','.join([filepath, str(numStrings)]))
|
||||
print('>>> Total Strings: {0}'.format(numStringsTotal))
|
||||
print('>>> Total Files: {0}'.format(numFilesTotal))
|
||||
print('>>> Max Strings: {0} in {1}'.format(maxStringsInFile[0], maxStringsInFile[1]))
|
||||
|
||||
def ProcessFilesFromDME(dmefile='baystation12.dme', ext='.dm'):
|
||||
numStringsTotal = 0
|
||||
numStrings = 0
|
||||
numFilesTotal = 0
|
||||
maxStringsInFile = [0, '']
|
||||
rootdir = os.path.dirname(dmefile)
|
||||
with open(os.path.join(rootdir, 'stringcounts.csv'), 'w') as csv:
|
||||
with open(dmefile, 'r') as dmeh:
|
||||
for line in dmeh:
|
||||
if line.startswith('#include'):
|
||||
inString = False
|
||||
# escaped=False
|
||||
filename = ''
|
||||
for c in line:
|
||||
"""
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
if
|
||||
escaped = False
|
||||
continue
|
||||
"""
|
||||
if c == '"':
|
||||
inString = not inString
|
||||
if not inString:
|
||||
filepath = os.path.join(rootdir, filename)
|
||||
if filepath.endswith(ext):
|
||||
numStrings = CountStringsIn(filepath)
|
||||
numStringsTotal += numStrings
|
||||
if numStrings > maxStringsInFile[0]:
|
||||
maxStringsInFile = [numStrings, filepath]
|
||||
numFilesTotal += 1
|
||||
csv.write(','.join([filepath, str(numStrings)]) + "\n")
|
||||
filename = ''
|
||||
continue
|
||||
else:
|
||||
if inString:
|
||||
filename += c
|
||||
print('>>> Total Strings: {0}'.format(numStringsTotal))
|
||||
print('>>> Total Files: {0}'.format(numFilesTotal))
|
||||
print('>>> Max Strings: {0} in {1}'.format(maxStringsInFile[0], maxStringsInFile[1]))
|
||||
|
||||
if os.path.isdir(sys.argv[1]):
|
||||
for root, _, files in os.walk(sys.argv[1]):
|
||||
for filename in files:
|
||||
filepath = os.path.join(root, filename)
|
||||
if filepath.endswith('.dme'):
|
||||
ProcessFilesFromDME(filepath, sys.argv[2])
|
||||
sys.exit(0)
|
||||
if os.path.isfile(sys.argv[1]):
|
||||
ProcessFilesFromDME(sys.argv[1], sys.argv[2])
|
||||
# ProcessFiles(sys.argv[1], sys.argv[2])
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
import glob, os, sys
|
||||
from setuptools import setup
|
||||
from setuptools.command.install import install as _install
|
||||
|
||||
scripts = [
|
||||
'dmm',
|
||||
'dmi',
|
||||
'dmindent',
|
||||
'dmmrender',
|
||||
'dmmfix',
|
||||
|
||||
'ss13_makeinhands'
|
||||
]
|
||||
|
||||
def _post_install(dir):
|
||||
from subprocess import call
|
||||
print('dir={}'.format(dir))
|
||||
call([sys.executable, 'byondtools-postinstall.py'], cwd=dir)
|
||||
|
||||
|
||||
class install(_install):
|
||||
def run(self):
|
||||
_install.run(self)
|
||||
# install_lib
|
||||
self.execute(_post_install, (self.install_scripts,), msg="Running post install task")
|
||||
|
||||
options = {}
|
||||
if sys.platform == "win32":
|
||||
scripts.append("byondtools-postinstall")
|
||||
scripts = ['scripts/{}.py'.format(x) for x in scripts]
|
||||
|
||||
setup(name='BYONDTools',
|
||||
version='0.1.0',
|
||||
description='Tools and interfaces for interacting with the BYOND game engine.',
|
||||
url='http://github.com/N3X15/BYONDTools',
|
||||
author='N3X15',
|
||||
author_email='nexisentertainment@gmail.com',
|
||||
license='MIT',
|
||||
packages=['byond'],
|
||||
install_requires=[
|
||||
'Pillow'
|
||||
],
|
||||
tests_require=['unittest-xml-reporting'],
|
||||
test_suite='tests',
|
||||
scripts=scripts,
|
||||
zip_safe=False,
|
||||
cmdclass={'install': install})
|
||||
@@ -1,27 +0,0 @@
|
||||
'''
|
||||
Created on Jan 1, 2014
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import unittest
|
||||
|
||||
class AtomTest(unittest.TestCase):
|
||||
def test_copy_consistency(self):
|
||||
from byond.basetypes import Atom, BYONDString, BYONDValue
|
||||
atom = Atom('/datum/test',__file__,0)
|
||||
atom.properties={
|
||||
'dir': BYONDValue(2),
|
||||
'name': BYONDString('test datum')
|
||||
}
|
||||
atom.mapSpecified=['dir','name']
|
||||
|
||||
atom2=atom.copy()
|
||||
|
||||
atom_serialized=atom.MapSerialize()
|
||||
atom2_serialized=atom2.MapSerialize()
|
||||
|
||||
self.assertEqual(atom_serialized, atom2_serialized)
|
||||
|
||||
if __name__ == "__main__":
|
||||
#import sys;sys.argv = ['', 'Test.testName']
|
||||
unittest.main()
|
||||
@@ -1,70 +0,0 @@
|
||||
'''
|
||||
Created on Jan 1, 2014
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import unittest
|
||||
|
||||
class MapParserTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from byond.map import Map, Tile
|
||||
self.dmm = Map()
|
||||
|
||||
def test_basic_SplitAtoms_operation(self):
|
||||
testStr = '/obj/effect/landmark{name = "carpspawn"},/obj/structure/lattice,/turf/space,/area'
|
||||
expectedOutput = ['/obj/effect/landmark{name = "carpspawn"}', '/obj/structure/lattice', '/turf/space', '/area']
|
||||
|
||||
out = self.dmm.SplitAtoms(testStr)
|
||||
self.assertListEqual(out, expectedOutput)
|
||||
|
||||
def test_basic_SplitProperties_operation(self):
|
||||
testStr = 'd1 = 1; d2 = 2; icon_state = "1-2"; tag = ""'
|
||||
expectedOutput = ['d1 = 1', ' d2 = 2', ' icon_state = "1-2"', ' tag = ""']
|
||||
|
||||
out = self.dmm.SplitProperties(testStr)
|
||||
self.assertListEqual(out, expectedOutput)
|
||||
|
||||
def test_basic_consumeTile_operation(self):
|
||||
from byond.map import Map, Tile
|
||||
'''
|
||||
"aaK" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 2;
|
||||
icon_state = "1-2";
|
||||
tag = ""
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
|
||||
dir = 4
|
||||
},
|
||||
/turf/simulated/floor{
|
||||
icon_state = "floorgrime"
|
||||
},
|
||||
/area/security/prison
|
||||
)
|
||||
'''
|
||||
testStr = '"aaK" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/floor{icon_state = "floorgrime"},/area/security/prison)'
|
||||
out = self.dmm.consumeTile(testStr, 0)
|
||||
print('IIDs: {0}'.format(repr(out.instances)))
|
||||
|
||||
self.assertEquals(out.origID, 'aaK', 'origID')
|
||||
self.assertEquals(len(out.instances), 4, 'instances size')
|
||||
self.assertEquals(len(out.GetAtom(0).properties), 4, 'instances[0] properties')
|
||||
self.assertIn('d1', out.GetAtom(0).properties, 'd1 not present in properties')
|
||||
self.assertListEqual(out.GetAtom(0).mapSpecified,['d1','d2','icon_state','tag'])
|
||||
|
||||
self.assertEquals(len(out.GetAtom(2).properties), 1, 'Failure to parse /turf/simulated/floor{icon_state = "floorgrime"}')
|
||||
self.assertIn('icon_state', out.GetAtom(2).properties, 'Failure to parse /turf/simulated/floor{icon_state = "floorgrime"}')
|
||||
|
||||
self.assertEqual(out.MapSerialize(Tile.FLAG_USE_OLD_ID), testStr)
|
||||
|
||||
def test_consumeTile_landmark(self):
|
||||
from byond.map import Map, Tile
|
||||
testStr='"aah" = (/obj/effect/landmark{name = "carpspawn"},/obj/structure/lattice,/turf/space,/area)'
|
||||
out = self.dmm.consumeTile(testStr, 0)
|
||||
self.assertEqual(out.MapSerialize(Tile.FLAG_USE_OLD_ID), testStr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# import sys;sys.argv = ['', 'Test.testName']
|
||||
unittest.main()
|
||||
@@ -1,35 +0,0 @@
|
||||
'''
|
||||
Created on Feb 26, 2014
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import unittest
|
||||
#from byond.map import Map
|
||||
'''
|
||||
class MapRenderingTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.dmm = Map()
|
||||
|
||||
def test_basic_bbox(self):
|
||||
correct_bbox=(
|
||||
3584,4382,
|
||||
3616,4414
|
||||
)
|
||||
# 1126, 440
|
||||
# 1126, 470
|
||||
|
||||
#3584, 4288
|
||||
tile_x,tile_y=(112,134)
|
||||
|
||||
pixel_x=0
|
||||
pixel_y=-30
|
||||
|
||||
icon_height=32
|
||||
icon_width=32
|
||||
|
||||
bbox = self.dmm.tilePosToBBox(tile_x, tile_y, pixel_x,pixel_y, icon_height,icon_width)
|
||||
self.assertTupleEqual(correct_bbox, bbox)
|
||||
|
||||
if __name__ == "__main__":
|
||||
#import sys;sys.argv = ['', 'Test.testName']
|
||||
unittest.main()'''
|
||||
@@ -1,74 +0,0 @@
|
||||
'''
|
||||
Created on Jan 5, 2014
|
||||
|
||||
@author: Rob
|
||||
'''
|
||||
import unittest
|
||||
|
||||
class ObjectTreeTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from byond.objtree import ObjectTree
|
||||
self.tree = ObjectTree()
|
||||
|
||||
def test_consumeVariable_basics(self):
|
||||
test_string = 'var/obj/item/weapon/chainsaw = new'
|
||||
name, data = self.tree.consumeVariable(test_string, '', 0)
|
||||
|
||||
self.assertEqual(name, 'chainsaw')
|
||||
self.assertEqual(data.type, '/obj/item/weapon')
|
||||
self.assertEqual(data.value, 'new')
|
||||
self.assertEqual(data.declaration, True)
|
||||
self.assertEqual(data.inherited, False)
|
||||
self.assertEqual(data.special, None)
|
||||
|
||||
def test_consumeVariable_alternate_array_declaration_01(self):
|
||||
test_string = 'var/appearance_keylist[0]'
|
||||
name, data = self.tree.consumeVariable(test_string, '', 0)
|
||||
|
||||
self.assertEqual(name, 'appearance_keylist')
|
||||
self.assertEqual(data.type, '/list')
|
||||
self.assertEqual(data.value, None)
|
||||
self.assertEqual(data.size, 0)
|
||||
self.assertEqual(data.declaration, True)
|
||||
self.assertEqual(data.inherited, False)
|
||||
self.assertEqual(data.special, None)
|
||||
|
||||
def test_consumeVariable_alternate_array_declaration_02(self):
|
||||
test_string = 'var/medical[] = list()'
|
||||
name, data = self.tree.consumeVariable(test_string, '', 0)
|
||||
|
||||
self.assertEqual(name, 'medical')
|
||||
self.assertEqual(data.type, '/list')
|
||||
self.assertEqual(data.value, None)
|
||||
self.assertEqual(data.size, -1)
|
||||
self.assertEqual(data.declaration, True)
|
||||
self.assertEqual(data.inherited, False)
|
||||
self.assertEqual(data.special, None)
|
||||
|
||||
def test_consumeVariable_complex_types(self):
|
||||
test_string = 'var/datum/gas_mixture/air_temporary'
|
||||
name, data = self.tree.consumeVariable(test_string, '', 0)
|
||||
|
||||
self.assertEqual(name, 'air_temporary')
|
||||
self.assertEqual(data.type, '/datum/gas_mixture')
|
||||
self.assertEqual(data.value, None)
|
||||
self.assertEqual(data.size, None)
|
||||
self.assertEqual(data.declaration, True)
|
||||
self.assertEqual(data.inherited, False)
|
||||
self.assertEqual(data.special, None)
|
||||
|
||||
def test_consumeVariable_file_ref(self):
|
||||
test_string = 'icon = \'butts.dmi\''
|
||||
name, data = self.tree.consumeVariable(test_string, '', 0)
|
||||
|
||||
self.assertEqual(name, 'icon')
|
||||
self.assertEqual(data.type, '/icon')
|
||||
self.assertEqual(str(data.value), 'butts.dmi')
|
||||
self.assertEqual(data.size, None)
|
||||
self.assertEqual(data.declaration, False)
|
||||
self.assertEqual(data.inherited, False)
|
||||
self.assertEqual(data.special, None)
|
||||
|
||||
if __name__ == "__main__":
|
||||
#import sys;sys.argv = ['', 'Test.testName']
|
||||
unittest.main()
|
||||
@@ -1,9 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from Atom import *
|
||||
from MapParser import *
|
||||
from MapRendering import *
|
||||
from ObjectTree import *
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,13 +0,0 @@
|
||||
# Tox (http://tox.testrun.org/) is a tool for running tests
|
||||
# in multiple virtualenvs. This configuration file will run the
|
||||
# test suite on all supported python versions. To use it, "pip install tox"
|
||||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py27
|
||||
|
||||
[testenv:py27]
|
||||
deps =
|
||||
pytest
|
||||
Pillow
|
||||
commands = py.test tests/runtests.py --junit-xml=pyunit-py27.xml
|
||||
Binary file not shown.
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
*/
|
||||
|
||||
var/list/config_stream = list()
|
||||
var/list/servers = list()
|
||||
var/list/servernames = list()
|
||||
var/list/adminfiles = list()
|
||||
var/list/adminkeys = list()
|
||||
|
||||
proc/gen_configs()
|
||||
|
||||
config_stream = dd_file2list("config.txt")
|
||||
|
||||
var/server_gen = 0 // if the stream is looking for servers
|
||||
var/admin_gen = 0 // if the stream is looking for admins
|
||||
for(var/line in config_stream)
|
||||
|
||||
if(line == "\[SERVERS\]")
|
||||
server_gen = 1
|
||||
if(admin_gen)
|
||||
admin_gen = 0
|
||||
|
||||
else if(line == "\[ADMINS\]")
|
||||
admin_gen = 1
|
||||
if(server_gen)
|
||||
server_gen = 0
|
||||
|
||||
else
|
||||
if(findtext(line, ".") && !findtext(line, "##"))
|
||||
if(server_gen)
|
||||
var/filterline = replacetext(line, " ", "")
|
||||
var/serverlink = copytext(filterline, findtext( filterline, ")") + 1)
|
||||
servers.Add(serverlink)
|
||||
servernames.Add( copytext(line, findtext(line, "("), findtext(line, ")") + 1))
|
||||
|
||||
else if(admin_gen)
|
||||
adminfiles.Add(line)
|
||||
world << line
|
||||
|
||||
|
||||
// Generate the list of admins now
|
||||
|
||||
for(var/file in adminfiles)
|
||||
var/admin_config_stream = dd_file2list(file)
|
||||
|
||||
for(var/line in admin_config_stream)
|
||||
|
||||
var/akey = copytext(line, 1, findtext(line, " "))
|
||||
adminkeys.Add(akey)
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
// DM Environment file for Redirect_Tgstation.dme.
|
||||
// All manual changes should be made outside the BEGIN_ and END_ blocks.
|
||||
// New source code should be placed in .dm files: choose File/New --> Code File.
|
||||
|
||||
// BEGIN_INTERNALS
|
||||
// END_INTERNALS
|
||||
|
||||
// BEGIN_FILE_DIR
|
||||
#define FILE_DIR .
|
||||
// END_FILE_DIR
|
||||
|
||||
// BEGIN_PREFERENCES
|
||||
// END_PREFERENCES
|
||||
|
||||
// BEGIN_INCLUDE
|
||||
#include "Configurations.dm"
|
||||
#include "Redirector.dm"
|
||||
#include "textprocs.dm"
|
||||
#include "skin.dmf"
|
||||
// END_INCLUDE
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
*/
|
||||
|
||||
/* TODO: work on server selection for detected admins */
|
||||
|
||||
|
||||
#define ADMINS 1
|
||||
#define PLAYERS 0
|
||||
|
||||
var/player_weight = 1 // players are more likely to join a server with less players
|
||||
var/admin_weight = 5 // admins are more likely to join a server with less admins
|
||||
|
||||
var/player_substr = "players=" // search for this substring to locate # of players
|
||||
var/admin_substr = "admins=" // search for this to locate # of admins
|
||||
|
||||
world
|
||||
name = "TGstation Redirector"
|
||||
|
||||
New()
|
||||
..()
|
||||
gen_configs()
|
||||
|
||||
/datum/server
|
||||
var/players = 0
|
||||
var/admins = 0
|
||||
var/weight = 0 // lower weight is good; highet weight is bad
|
||||
|
||||
var/link = ""
|
||||
|
||||
mob/Login()
|
||||
..()
|
||||
|
||||
var/list/weights = list()
|
||||
var/list/servers = list()
|
||||
for(var/x in global.servers)
|
||||
|
||||
world << "[x] [servernames[ global.servers.Find(x) ]]"
|
||||
|
||||
var/info = world.Export("[x]?status")
|
||||
var/datum/server/S = new()
|
||||
S.players = extract(info, PLAYERS)
|
||||
S.admins = extract(info, ADMINS)
|
||||
|
||||
S.weight += player_weight * S.players
|
||||
S.link = x
|
||||
|
||||
world << S.players
|
||||
world << S.admins
|
||||
|
||||
weights.Add(S.weight)
|
||||
servers.Add(S)
|
||||
|
||||
var/lowest = min(weights)
|
||||
var/serverlink
|
||||
for(var/datum/server/S in servers)
|
||||
if(S.weight == lowest)
|
||||
serverlink = S.link
|
||||
|
||||
src << link(serverlink)
|
||||
|
||||
proc/extract(var/data, var/type = PLAYERS)
|
||||
|
||||
var/nextpos = 0
|
||||
|
||||
if(type == PLAYERS)
|
||||
|
||||
nextpos = findtextEx(data, player_substr)
|
||||
nextpos += length(player_substr)
|
||||
|
||||
else
|
||||
|
||||
nextpos = findtextEx(data, admin_substr)
|
||||
nextpos += length(admin_substr)
|
||||
|
||||
var/returnval = ""
|
||||
|
||||
for(var/i = 1, i <= 10, i++)
|
||||
|
||||
var/interval = copytext(data, nextpos + (i-1), nextpos + i)
|
||||
if(interval == "&")
|
||||
break
|
||||
else
|
||||
returnval += interval
|
||||
|
||||
return returnval
|
||||
@@ -1,12 +0,0 @@
|
||||
[SERVERS]
|
||||
## Simply enter a list of servers to poll. Be sure to specify a server name in parentheses.
|
||||
|
||||
(Sibyl #1) byond://game.nanotrasen.com:1337
|
||||
|
||||
(Sibyl #2) byond://game.nanotrasen.com:2337
|
||||
|
||||
|
||||
[ADMINS]
|
||||
## Specify some standard Windows filepaths (you may use relative paths) for admin txt lists to poll.
|
||||
|
||||
C:\SS13\config\admins.txt
|
||||
@@ -1,149 +0,0 @@
|
||||
macro "macro"
|
||||
elem
|
||||
name = "North+REP"
|
||||
command = ".north"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "South+REP"
|
||||
command = ".south"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "East+REP"
|
||||
command = ".east"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "West+REP"
|
||||
command = ".west"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Northeast+REP"
|
||||
command = ".northeast"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Northwest+REP"
|
||||
command = ".northwest"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Southeast+REP"
|
||||
command = ".southeast"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Southwest+REP"
|
||||
command = ".southwest"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Center+REP"
|
||||
command = ".center"
|
||||
is-disabled = false
|
||||
|
||||
|
||||
menu "menu"
|
||||
elem
|
||||
name = "&Quit"
|
||||
command = ".quit"
|
||||
category = "&File"
|
||||
is-checked = false
|
||||
can-check = false
|
||||
group = ""
|
||||
is-disabled = false
|
||||
saved-params = "is-checked"
|
||||
|
||||
|
||||
window "window"
|
||||
elem "window"
|
||||
type = MAIN
|
||||
pos = 281,0
|
||||
size = 594x231
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #000000
|
||||
background-color = #000000
|
||||
is-visible = false
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = true
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = "pos;size;is-minimized;is-maximized"
|
||||
on-size = ""
|
||||
title = ""
|
||||
titlebar = true
|
||||
statusbar = false
|
||||
can-close = true
|
||||
can-minimize = true
|
||||
can-resize = true
|
||||
is-pane = false
|
||||
is-minimized = false
|
||||
is-maximized = false
|
||||
can-scroll = none
|
||||
icon = ""
|
||||
image = ""
|
||||
image-mode = stretch
|
||||
keep-aspect = false
|
||||
transparent-color = none
|
||||
alpha = 255
|
||||
macro = "macro"
|
||||
menu = ""
|
||||
on-close = ""
|
||||
elem "servers"
|
||||
type = GRID
|
||||
pos = 8,8
|
||||
size = 576x152
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #ffffff
|
||||
background-color = #000000
|
||||
is-visible = true
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = false
|
||||
border = none
|
||||
drop-zone = true
|
||||
right-click = false
|
||||
saved-params = ""
|
||||
on-size = ""
|
||||
cells = 1x1
|
||||
current-cell = 1,1
|
||||
show-lines = none
|
||||
small-icons = true
|
||||
show-names = true
|
||||
enable-http-images = false
|
||||
link-color = #0000ff
|
||||
visited-color = #ff00ff
|
||||
line-color = #c0c0c0
|
||||
style = ""
|
||||
is-list = false
|
||||
elem "output1"
|
||||
type = OUTPUT
|
||||
pos = 8,168
|
||||
size = 576x56
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #ffffff
|
||||
background-color = #000000
|
||||
is-visible = true
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = true
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = "max-lines"
|
||||
on-size = ""
|
||||
link-color = #0000ff
|
||||
visited-color = #ff00ff
|
||||
style = ""
|
||||
enable-http-images = false
|
||||
max-lines = 1000
|
||||
image = ""
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
|
||||
NOTE: The below functions are part of BYOND user Deadron's "TextHandling" library.
|
||||
[ http://www.byond.com/developer/Deadron/TextHandling ]
|
||||
*/
|
||||
|
||||
|
||||
proc
|
||||
///////////////////
|
||||
// Reading files //
|
||||
///////////////////
|
||||
dd_file2list(file_path, separator = "\n")
|
||||
var/file
|
||||
if (isfile(file_path))
|
||||
file = file_path
|
||||
else
|
||||
file = file(file_path)
|
||||
return dd_text2list(file2text(file), separator)
|
||||
|
||||
|
||||
////////////////////
|
||||
// Replacing text //
|
||||
////////////////////
|
||||
dd_replacetext(text, search_string, replacement_string)
|
||||
// A nice way to do this is to split the text into an array based on the search_string,
|
||||
// then put it back together into text using replacement_string as the new separator.
|
||||
var/list/textList = dd_text2list(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
|
||||
|
||||
dd_replaceText(text, search_string, replacement_string)
|
||||
var/list/textList = dd_text2List(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Prefix checking //
|
||||
/////////////////////
|
||||
dd_hasprefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = lentext(prefix) + 1
|
||||
return findtext(text, prefix, start, end)
|
||||
|
||||
dd_hasPrefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = lentext(prefix) + 1
|
||||
return findtextEx(text, prefix, start, end)
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Suffix checking //
|
||||
/////////////////////
|
||||
dd_hassuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start) return findtext(text, suffix, start)
|
||||
|
||||
dd_hasSuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start) return findtextEx(text, suffix, start)
|
||||
|
||||
/////////////////////////////
|
||||
// Turning text into lists //
|
||||
/////////////////////////////
|
||||
dd_text2list(text, separator)
|
||||
var/textlength = lentext(text)
|
||||
var/separatorlength = lentext(separator)
|
||||
var/list/textList = new /list()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
while (1) // Loop forever.
|
||||
findPosition = findtext(text, separator, searchPosition, 0)
|
||||
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
|
||||
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
|
||||
|
||||
searchPosition = findPosition + separatorlength // Skip over separator.
|
||||
if (findPosition == 0) // Didn't find anything at end of string so stop here.
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength) // Found separator at very end of string.
|
||||
textList += "" // So add empty element.
|
||||
return textList
|
||||
|
||||
dd_text2List(text, separator)
|
||||
var/textlength = lentext(text)
|
||||
var/separatorlength = lentext(separator)
|
||||
var/list/textList = new /list()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
while (1) // Loop forever.
|
||||
findPosition = findtextEx(text, separator, searchPosition, 0)
|
||||
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
|
||||
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
|
||||
|
||||
searchPosition = findPosition + separatorlength // Skip over separator.
|
||||
if (findPosition == 0) // Didn't find anything at end of string so stop here.
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength) // Found separator at very end of string.
|
||||
textList += "" // So add empty element.
|
||||
return textList
|
||||
|
||||
dd_list2text(list/the_list, separator)
|
||||
var/total = the_list.len
|
||||
if (total == 0) // Nothing to work with.
|
||||
return
|
||||
|
||||
var/newText = "[the_list[1]]" // Treats any object/number as text also.
|
||||
var/count
|
||||
for (count = 2, count <= total, count++)
|
||||
if (separator) newText += separator
|
||||
newText += "[the_list[count]]"
|
||||
return newText
|
||||
|
||||
dd_centertext(message, length)
|
||||
var/new_message = message
|
||||
var/size = length(message)
|
||||
if (size == length)
|
||||
return new_message
|
||||
if (size > length)
|
||||
return copytext(new_message, 1, length + 1)
|
||||
|
||||
// Need to pad text to center it.
|
||||
var/delta = length - size
|
||||
if (delta == 1)
|
||||
// Add one space after it.
|
||||
return new_message + " "
|
||||
|
||||
// Is this an odd number? If so, add extra space to front.
|
||||
if (delta % 2)
|
||||
new_message = " " + new_message
|
||||
delta--
|
||||
|
||||
// Divide delta in 2, add those spaces to both ends.
|
||||
delta = delta / 2
|
||||
var/spaces = ""
|
||||
for (var/count = 1, count <= delta, count++)
|
||||
spaces += " "
|
||||
return spaces + new_message + spaces
|
||||
|
||||
dd_limittext(message, length)
|
||||
// Truncates text to limit if necessary.
|
||||
var/size = length(message)
|
||||
if (size <= length)
|
||||
return message
|
||||
else
|
||||
return copytext(message, 1, length + 1)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,314 +0,0 @@
|
||||
/* Runtime Condenser by Nodrak
|
||||
* This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance
|
||||
* of the runtime will log the proc, source, usr and src, the rest will just add to the total. Infinite loops will
|
||||
* also be caught and displayed (if any) above the list of runtimes.
|
||||
*
|
||||
* How to use:
|
||||
* 1) Copy and paste your list of runtimes from Dream Daemon into input.exe
|
||||
* 2) Run RuntimeCondenser.exe
|
||||
* 3) Open output.txt for a condensed report of the runtimes
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//Make all of these global. It's bad yes, but it's a small program so it really doesn't affect anything.
|
||||
//Because hardcoded numbers are bad :(
|
||||
const unsigned short maxStorage = 99; //100 - 1
|
||||
|
||||
//What we use to read input
|
||||
string currentLine = "Blank";
|
||||
string nextLine = "Blank";
|
||||
|
||||
//Stores lines we want to keep to print out
|
||||
string storedRuntime[maxStorage+1];
|
||||
string storedProc[maxStorage+1];
|
||||
string storedSource[maxStorage+1];
|
||||
string storedUsr[maxStorage+1];
|
||||
string storedSrc[maxStorage+1];
|
||||
|
||||
//Stat tracking stuff for output
|
||||
unsigned int totalRuntimes = 0;
|
||||
unsigned int totalUniqueRuntimes = 0;
|
||||
unsigned int totalInfiniteLoops = 0;
|
||||
unsigned int totalUniqueInfiniteLoops = 0;
|
||||
|
||||
//Misc
|
||||
unsigned int numRuntime[maxStorage+1]; //Number of times a specific runtime has occured
|
||||
bool checkNextLines = false; //Used in case byond has condensed a large number of similar runtimes
|
||||
int storedIterator = 0; //Used to remember where we stored the runtime
|
||||
|
||||
bool readFromFile()
|
||||
{
|
||||
//Open file to read
|
||||
ifstream inputFile("input.txt");
|
||||
|
||||
if(inputFile.is_open())
|
||||
{
|
||||
while(!inputFile.eof()) //Until end of file
|
||||
{
|
||||
//If we've run out of storage
|
||||
if(storedRuntime[maxStorage] != "Blank") break;
|
||||
|
||||
//Update our lines
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//After finding a new runtime, check to see if there are extra values to store
|
||||
if(checkNextLines)
|
||||
{
|
||||
//Skip ahead
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//If we find this, we have new stuff to store
|
||||
if(nextLine.find("usr:") != std::string::npos)
|
||||
{
|
||||
//Store more info
|
||||
storedSource[storedIterator] = currentLine;
|
||||
storedUsr[storedIterator] = nextLine;
|
||||
|
||||
//Skip ahead again
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//Store the last of the info
|
||||
storedSrc[storedIterator] = nextLine;
|
||||
}
|
||||
checkNextLines = false;
|
||||
}
|
||||
|
||||
//Found an infinite loop!
|
||||
if(currentLine.find("Infinite loop suspected") != std::string::npos || currentLine.find("Maximum recursion level reached") != std::string::npos)
|
||||
{
|
||||
totalInfiniteLoops++;
|
||||
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//We've already encountered this
|
||||
if(currentLine == storedRuntime[i])
|
||||
{
|
||||
numRuntime[i]++;
|
||||
break;
|
||||
}
|
||||
|
||||
//We've never encoutnered this
|
||||
if(storedRuntime[i] == "Blank")
|
||||
{
|
||||
storedRuntime[i] = currentLine;
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine); //Skip the "if this is not an infinite loop" line
|
||||
storedProc[i] = nextLine;
|
||||
numRuntime[i] = 1;
|
||||
checkNextLines = true;
|
||||
storedIterator = i;
|
||||
totalUniqueInfiniteLoops++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Found a runtime!
|
||||
else if(currentLine.find("runtime error:") != std::string::npos)
|
||||
{
|
||||
totalRuntimes++;
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//We've already encountered this
|
||||
if(currentLine == storedRuntime[i])
|
||||
{
|
||||
numRuntime[i]++;
|
||||
break;
|
||||
}
|
||||
|
||||
//We've never encoutnered this
|
||||
if(storedRuntime[i] == "Blank")
|
||||
{
|
||||
storedRuntime[i] = currentLine;
|
||||
storedProc[i] = nextLine;
|
||||
numRuntime[i] = 1;
|
||||
checkNextLines = true;
|
||||
storedIterator = i;
|
||||
totalUniqueRuntimes++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeToFile()
|
||||
{
|
||||
//Open and clear the file
|
||||
ofstream outputFile("Output.txt", ios::trunc);
|
||||
|
||||
if(outputFile.is_open())
|
||||
{
|
||||
outputFile << "Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n";
|
||||
if(totalUniqueInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "Total unique infinite loops: " << totalUniqueInfiniteLoops << endl;
|
||||
}
|
||||
if(totalInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "Total infinite loops: " << totalInfiniteLoops << endl;
|
||||
}
|
||||
outputFile << "Total unique runtimes: " << totalUniqueRuntimes << endl;
|
||||
outputFile << "Total runtimes: " << totalRuntimes << endl << endl;
|
||||
|
||||
//Display a warning if we've hit the maximum space we've allocated for storage
|
||||
if(totalUniqueRuntimes + totalUniqueInfiniteLoops >= maxStorage)
|
||||
{
|
||||
outputFile << "Warning: The maximum number of unique runtimes has been hit. If there were more, they have been cropped out.\n\n";
|
||||
}
|
||||
|
||||
|
||||
//If we have infinite loops, display them first.
|
||||
if(totalInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "** Infinite loops **";
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos)
|
||||
{
|
||||
if(numRuntime[i] != 0) outputFile << endl << endl << "The following infinite loop has occured " << numRuntime[i] << " time(s).\n";
|
||||
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
|
||||
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
|
||||
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
|
||||
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
|
||||
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
|
||||
}
|
||||
}
|
||||
outputFile << endl << endl; //For spacing
|
||||
}
|
||||
|
||||
|
||||
//Do runtimes next
|
||||
outputFile << "** Runtimes **";
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos) continue;
|
||||
|
||||
if(numRuntime[i] != 0) outputFile << endl << endl << "The following runtime has occured " << numRuntime[i] << " time(s).\n";
|
||||
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
|
||||
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
|
||||
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
|
||||
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
|
||||
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
|
||||
}
|
||||
outputFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void sortRuntimes()
|
||||
{
|
||||
string tempRuntime[maxStorage+1];
|
||||
string tempProc[maxStorage+1];
|
||||
string tempSource[maxStorage+1];
|
||||
string tempUsr[maxStorage+1];
|
||||
string tempSrc[maxStorage+1];
|
||||
unsigned int tempNumRuntime[maxStorage+1];
|
||||
unsigned int highestCount = 0; //Used for descending order
|
||||
// int keepLooping = 0;
|
||||
|
||||
//Move all of our data into temporary arrays. Also clear the stored data (not necessary but.. just incase)
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//Get the largest occurance of a single runtime
|
||||
if(highestCount < numRuntime[i])
|
||||
{
|
||||
highestCount = numRuntime[i];
|
||||
}
|
||||
|
||||
tempRuntime[i] = storedRuntime[i]; storedRuntime[i] = "Blank";
|
||||
tempProc[i] = storedProc[i]; storedProc[i] = "Blank";
|
||||
tempSource[i] = storedSource[i]; storedSource[i] = "Blank";
|
||||
tempUsr[i] = storedUsr[i]; storedUsr[i] = "Blank";
|
||||
tempSrc[i] = storedSrc[i]; storedSrc[i] = "Blank";
|
||||
tempNumRuntime[i] = numRuntime[i]; numRuntime[i] = 0;
|
||||
}
|
||||
|
||||
while(highestCount > 0)
|
||||
{
|
||||
for(int i=0; i <= maxStorage; i++) //For every runtime
|
||||
{
|
||||
if(tempNumRuntime[i] == highestCount) //If the number of occurances of that runtime is equal to our current highest
|
||||
{
|
||||
for(int j=0; j <= maxStorage; j++) //Find the next available slot and store the info
|
||||
{
|
||||
if(storedRuntime[j] == "Blank") //Found an empty spot
|
||||
{
|
||||
storedRuntime[j] = tempRuntime[i];
|
||||
storedProc[j] = tempProc[i];
|
||||
storedSource[j] = tempSource[i];
|
||||
storedUsr[j] = tempUsr[i];
|
||||
storedSrc[j] = tempSrc[i];
|
||||
numRuntime[j] = tempNumRuntime[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
highestCount--; //Lower our 'highest' by one and continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
char exit; //Used to stop the program from immediatly exiting
|
||||
|
||||
//Start everything fresh. "Blank" should never occur in the runtime logs on its own.
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
storedRuntime[i] = "Blank";
|
||||
storedProc[i] = "Blank";
|
||||
storedSource[i] = "Blank";
|
||||
storedUsr[i] = "Blank";
|
||||
storedSrc[i] = "Blank";
|
||||
numRuntime[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
if(readFromFile())
|
||||
{
|
||||
cout << "Input read successfully!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Input failed to open, shutting down.\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sortRuntimes();
|
||||
|
||||
if(writeToFile())
|
||||
{
|
||||
cout << "Output was successful!\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "The output file could not be opened, shutting down.\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.
|
||||
|
||||
Total unique runtimes: 25
|
||||
Total runtimes: 767
|
||||
|
||||
** Runtimes **
|
||||
|
||||
The following runtime has occured 269 time(s).
|
||||
runtime error: Cannot read null.viruses
|
||||
proc name: cure (/datum/disease/proc/cure)
|
||||
source file: disease.dm,156
|
||||
usr: null
|
||||
src: Space Retrovirus (/datum/disease/dnaspread)
|
||||
|
||||
|
||||
The following runtime has occured 199 time(s).
|
||||
runtime error: Cannot read null.has_gravity
|
||||
proc name: throw at (/atom/movable/proc/throw_at)
|
||||
source file: throwing.dm,194
|
||||
usr: Reese Marcotte (/mob/living/carbon/human)
|
||||
src: Reese Marcotte (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 165 time(s).
|
||||
runtime error: Cannot read null.slot_flags
|
||||
proc name: db click (/mob/living/carbon/human/db_click)
|
||||
source file: inventory.dm,1083
|
||||
usr: Puke Chunks (/mob/living/carbon/human)
|
||||
src: Puke Chunks (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 25 time(s).
|
||||
runtime error: Cannot read null.flags
|
||||
proc name: relaymove (/obj/effect/dummy/spell_jaunt/relaymove)
|
||||
|
||||
|
||||
The following runtime has occured 24 time(s).
|
||||
runtime error: Cannot read null.len
|
||||
proc name: mergeRecordLists (/proc/mergeRecordLists)
|
||||
source file: helpers.dm,260
|
||||
usr: Wintermute (/mob/living/silicon/ai)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 20 time(s).
|
||||
runtime error: Cannot read null.total_volume
|
||||
proc name: attackby (/obj/machinery/reagentgrinder/attackby)
|
||||
source file: Chemistry-Machinery.dm,751
|
||||
usr: Reese Marcotte (/mob/living/carbon/human)
|
||||
src: All-In-One Grinder (/obj/machinery/reagentgrinder)
|
||||
|
||||
|
||||
The following runtime has occured 16 time(s).
|
||||
runtime error: Cannot read null.broadcasting
|
||||
proc name: radio menu (/mob/living/silicon/robot/proc/radio_menu)
|
||||
source file: robot.dm,857
|
||||
usr: Engineering Cyborg -432 (/mob/living/silicon/robot)
|
||||
src: Engineering Cyborg -432 (/mob/living/silicon/robot)
|
||||
|
||||
|
||||
The following runtime has occured 7 time(s).
|
||||
runtime error: unexpected stat
|
||||
proc name: Stat (/mob/living/silicon/robot/Stat)
|
||||
source file: robot.dm,227
|
||||
usr: Michigan Slim (/mob/living/carbon/human)
|
||||
src: Engineering Cyborg -133 (/mob/living/silicon/robot)
|
||||
|
||||
|
||||
The following runtime has occured 7 time(s).
|
||||
runtime error: Cannot read null.current
|
||||
proc name: check completion (/datum/objective/download/check_completion)
|
||||
source file: objective.dm,411
|
||||
usr: null
|
||||
src: /datum/objective/download (/datum/objective/download)
|
||||
|
||||
|
||||
The following runtime has occured 6 time(s).
|
||||
runtime error: Cannot create objects of type null.
|
||||
proc name: Topic (/obj/machinery/computer/rdconsole/Topic)
|
||||
source file: rdconsole.dm,381
|
||||
usr: Matthew Hoff (/mob/living/carbon/human)
|
||||
src: Core R&D Console (/obj/machinery/computer/rdconsole/core)
|
||||
|
||||
|
||||
The following runtime has occured 6 time(s).
|
||||
runtime error: Cannot read null.fields
|
||||
proc name: mergeRecordLists (/proc/mergeRecordLists)
|
||||
source file: helpers.dm,263
|
||||
usr: Wintermute (/mob/living/silicon/ai)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: undefined variable /client/var/loc
|
||||
proc name: get turf (/proc/get_turf)
|
||||
source file: helper_procs.dm,38
|
||||
usr: the ghost (/mob/dead/observer)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: Cannot read null.nodes
|
||||
proc name: merge powernets (/datum/powernet/proc/merge_powernets)
|
||||
source file: power.dm,401
|
||||
usr: Darin Keppel (/mob/living/carbon/human)
|
||||
src: /datum/powernet (/datum/powernet)
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: Cannot read null.reagents
|
||||
proc name: fire syringe (/obj/item/weapon/gun/syringe/proc/fire_syringe)
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: undefined proc or verb /obj/machinery/space_heater/attack().
|
||||
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: list index out of bounds
|
||||
proc name: mergeConnectedNetworksOnTurf (/obj/structure/cable/proc/mergeConnectedNetworksOnTurf)
|
||||
source file: cable.dm,520
|
||||
usr: Josue Sandford (/mob/living/carbon/human)
|
||||
src: the power cable (/obj/structure/cable)
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: Cannot read null.loc
|
||||
proc name: Life (/mob/living/simple_animal/corgi/Ian/Life)
|
||||
source file: corgi.dm,304
|
||||
usr: null
|
||||
src: Captain Ian (/mob/living/simple_animal/corgi/Ian)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined proc or verb /obj/machinery/portable_atmospherics/canister/toxins/attack().
|
||||
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined variable /datum/preferences/var/fields
|
||||
proc name: Topic (/obj/machinery/computer/cloning/Topic)
|
||||
source file: cloning.dm,370
|
||||
usr: Logan Graves (/mob/living/carbon/human)
|
||||
src: Cloning console (/obj/machinery/computer/cloning)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined variable /turf/simulated/floor/plating/var/mineral
|
||||
proc name: attackby (/turf/simulated/wall/attackby)
|
||||
source file: turf.dm,600
|
||||
usr: Monte Smail (/mob/living/carbon/human)
|
||||
src: the plating (176,172,5) (/turf/simulated/floor/plating)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.blood_DNA
|
||||
proc name: update inv w uniform (/mob/living/carbon/human/update_inv_w_uniform)
|
||||
source file: update_icons.dm,372
|
||||
usr: null
|
||||
src: Chip Harshman (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot execute null.dropped().
|
||||
proc name: drop l hand (/mob/proc/drop_l_hand)
|
||||
source file: inventory.dm,104
|
||||
usr: Jeb Stone (/mob/living/carbon/human)
|
||||
src: Jeb Stone (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.w_class
|
||||
proc name: attackby (/obj/item/weapon/storage/attackby)
|
||||
source file: storage.dm,187
|
||||
usr: Samuel York (/mob/living/carbon/human)
|
||||
src: the backpack (/obj/item/weapon/storage/backpack)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.amount
|
||||
proc name: attackby (/obj/machinery/constructable_frame/machine_frame/attackby)
|
||||
source file: constructable_frame.dm,27
|
||||
usr: Quinton Bould (/mob/living/carbon/human)
|
||||
src: the machine frame (/obj/machinery/constructable_frame/machine_frame)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot modify null.status.
|
||||
proc name: death (/mob/living/silicon/robot/death)
|
||||
Binary file not shown.
@@ -1,20 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnstandardnessTestForDM", "UnstandardnessTestForDM\UnstandardnessTestForDM.csproj", "{A0EEBFC9-41D4-474D-853D-126AFDFB82DE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A0EEBFC9-41D4-474D-853D-126AFDFB82DE}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{A0EEBFC9-41D4-474D-853D-126AFDFB82DE}.Debug|x86.Build.0 = Debug|x86
|
||||
{A0EEBFC9-41D4-474D-853D-126AFDFB82DE}.Release|x86.ActiveCfg = Release|x86
|
||||
{A0EEBFC9-41D4-474D-853D-126AFDFB82DE}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Binary file not shown.
@@ -1,160 +0,0 @@
|
||||
namespace UnstandardnessTestForDM
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.listBox1 = new System.Windows.Forms.ListBox();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.listBox2 = new System.Windows.Forms.ListBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.panel1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Location = new System.Drawing.Point(12, 12);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(222, 23);
|
||||
this.button1.TabIndex = 0;
|
||||
this.button1.Text = "Locate all #defines";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// listBox1
|
||||
//
|
||||
this.listBox1.FormattingEnabled = true;
|
||||
this.listBox1.Location = new System.Drawing.Point(12, 82);
|
||||
this.listBox1.Name = "listBox1";
|
||||
this.listBox1.Size = new System.Drawing.Size(696, 160);
|
||||
this.listBox1.TabIndex = 1;
|
||||
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.panel1.Controls.Add(this.listBox2);
|
||||
this.panel1.Controls.Add(this.label4);
|
||||
this.panel1.Controls.Add(this.label3);
|
||||
this.panel1.Controls.Add(this.label2);
|
||||
this.panel1.Controls.Add(this.label1);
|
||||
this.panel1.Location = new System.Drawing.Point(12, 297);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(696, 244);
|
||||
this.panel1.TabIndex = 2;
|
||||
//
|
||||
// listBox2
|
||||
//
|
||||
this.listBox2.FormattingEnabled = true;
|
||||
this.listBox2.Location = new System.Drawing.Point(8, 71);
|
||||
this.listBox2.Name = "listBox2";
|
||||
this.listBox2.Size = new System.Drawing.Size(683, 160);
|
||||
this.listBox2.TabIndex = 4;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(5, 55);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(69, 13);
|
||||
this.label4.TabIndex = 3;
|
||||
this.label4.Text = "Referenced: ";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(5, 42);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(40, 13);
|
||||
this.label3.TabIndex = 2;
|
||||
this.label3.Text = "Value: ";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(5, 29);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(61, 13);
|
||||
this.label2.TabIndex = 1;
|
||||
this.label2.Text = "Defined in: ";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||
this.label1.Location = new System.Drawing.Point(3, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(79, 29);
|
||||
this.label1.TabIndex = 0;
|
||||
this.label1.Text = "label1";
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(9, 38);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(81, 13);
|
||||
this.label5.TabIndex = 3;
|
||||
this.label5.Text = "Files searched: ";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(720, 553);
|
||||
this.Controls.Add(this.label5);
|
||||
this.Controls.Add(this.panel1);
|
||||
this.Controls.Add(this.listBox1);
|
||||
this.Controls.Add(this.button1);
|
||||
this.Name = "Form1";
|
||||
this.Text = "Unstandardness Test For DM";
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.panel1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label1;
|
||||
public System.Windows.Forms.ListBox listBox2;
|
||||
public System.Windows.Forms.Label label5;
|
||||
public System.Windows.Forms.ListBox listBox1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,484 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace UnstandardnessTestForDM
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
DMSource source;
|
||||
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
source = new DMSource();
|
||||
source.mainform = this;
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
source.find_all_defines();
|
||||
generate_define_report();
|
||||
}
|
||||
|
||||
public void generate_define_report()
|
||||
{
|
||||
|
||||
TextWriter tw = new StreamWriter("DEFINES REPORT.txt");
|
||||
|
||||
tw.WriteLine("Unstandardness Test For DM report for DEFINES");
|
||||
tw.WriteLine("Generated on " + DateTime.Now);
|
||||
tw.WriteLine("Total number of defines " + source.defines.Count());
|
||||
tw.WriteLine("Total number of Files " + source.filessearched);
|
||||
tw.WriteLine("Total number of references " + source.totalreferences);
|
||||
tw.WriteLine("Total number of errorous defines " + source.errordefines);
|
||||
tw.WriteLine("------------------------------------------------");
|
||||
|
||||
foreach (Define d in source.defines)
|
||||
{
|
||||
tw.WriteLine(d.name);
|
||||
tw.WriteLine("\tValue: " + d.value);
|
||||
tw.WriteLine("\tComment: " + d.comment);
|
||||
tw.WriteLine("\tDefined in: " + d.location + " : " + d.line);
|
||||
tw.WriteLine("\tNumber of references: " + d.references.Count());
|
||||
foreach (String s in d.references)
|
||||
{
|
||||
tw.WriteLine("\t\t" + s);
|
||||
}
|
||||
}
|
||||
|
||||
tw.WriteLine("------------------------------------------------");
|
||||
tw.WriteLine("SUCCESS");
|
||||
|
||||
tw.Close();
|
||||
|
||||
}
|
||||
|
||||
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Define d = (Define)listBox1.Items[listBox1.SelectedIndex];
|
||||
label1.Text = d.name;
|
||||
label2.Text = "Defined in: " + d.location + " : " + d.line;
|
||||
label3.Text = "Value: " + d.value;
|
||||
label4.Text = "References: " + d.references.Count();
|
||||
listBox2.Items.Clear();
|
||||
foreach (String s in d.references)
|
||||
{
|
||||
listBox2.Items.Add(s);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex) { Console.WriteLine("ERROR HERE: " + ex.Message); }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class DMSource
|
||||
{
|
||||
public List<Define> defines;
|
||||
public const int FLAG_DEFINE = 1;
|
||||
public Form1 mainform;
|
||||
|
||||
public int filessearched = 0;
|
||||
public int totalreferences = 0;
|
||||
public int errordefines = 0;
|
||||
|
||||
public List<String> filenames;
|
||||
|
||||
public DMSource()
|
||||
{
|
||||
defines = new List<Define>();
|
||||
filenames = new List<String>();
|
||||
}
|
||||
|
||||
public void find_all_defines()
|
||||
{
|
||||
find_all_files();
|
||||
foreach(String filename in filenames){
|
||||
searchFileForDefines(filename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void find_all_files()
|
||||
{
|
||||
filenames = new List<String>();
|
||||
String dmefilename = "";
|
||||
|
||||
foreach (string f in Directory.GetFiles("."))
|
||||
{
|
||||
if (f.ToLower().EndsWith(".dme"))
|
||||
{
|
||||
dmefilename = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmefilename.Equals(""))
|
||||
{
|
||||
MessageBox.Show("dme file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
using (var reader = File.OpenText(dmefilename))
|
||||
{
|
||||
String s;
|
||||
while (true)
|
||||
{
|
||||
s = reader.ReadLine();
|
||||
|
||||
if (!(s is String))
|
||||
break;
|
||||
|
||||
if (s.StartsWith("#include"))
|
||||
{
|
||||
int start = s.IndexOf("\"")+1;
|
||||
s = s.Substring(start, s.Length - 11);
|
||||
|
||||
if (s.EndsWith(".dm"))
|
||||
{
|
||||
filenames.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
s = s.Trim(' ');
|
||||
if (s == "") { continue; }
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void DirSearch(string sDir, int flag)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string d in Directory.GetDirectories(sDir))
|
||||
{
|
||||
foreach (string f in Directory.GetFiles(d))
|
||||
{
|
||||
if (f.ToLower().EndsWith(".dm"))
|
||||
{
|
||||
if ((flag & FLAG_DEFINE) > 0)
|
||||
{
|
||||
searchFileForDefines(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
DirSearch(d, flag);
|
||||
}
|
||||
}
|
||||
catch (System.Exception excpt)
|
||||
{
|
||||
Console.WriteLine("ERROR IN DIRSEARCH");
|
||||
Console.WriteLine(excpt.Message);
|
||||
Console.WriteLine(excpt.Data);
|
||||
Console.WriteLine(excpt.ToString());
|
||||
Console.WriteLine(excpt.StackTrace);
|
||||
Console.WriteLine("END OF ERROR IN DIRSEARCH");
|
||||
}
|
||||
}
|
||||
|
||||
//DEFINES
|
||||
public void searchFileForDefines(String fileName)
|
||||
{
|
||||
filessearched++;
|
||||
FileInfo f = new FileInfo(fileName);
|
||||
List<String> lines = new List<String>();
|
||||
List<String> lines_without_comments = new List<String>();
|
||||
|
||||
mainform.label5.Text = "Files searched: " + filessearched + "; Defines found: " + defines.Count() + "; References found: " + totalreferences + "; Errorous defines: " + errordefines;
|
||||
mainform.label5.Refresh();
|
||||
|
||||
//This code segment reads the file and stores it into the lines variable.
|
||||
using (var reader = File.OpenText(fileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
String s;
|
||||
while (true)
|
||||
{
|
||||
s = reader.ReadLine();
|
||||
lines.Add(s);
|
||||
s = s.Trim(' ');
|
||||
if (s == "") { continue; }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
reader.Close();
|
||||
}
|
||||
|
||||
mainform.listBox1.Items.Add("ATTEMPTING: " + fileName);
|
||||
lines_without_comments = remove_comments(lines);
|
||||
|
||||
/*TextWriter tw = new StreamWriter(fileName);
|
||||
foreach (String s in lines_without_comments)
|
||||
{
|
||||
tw.WriteLine(s);
|
||||
}
|
||||
tw.Close();
|
||||
mainform.listBox1.Items.Add("REWRITE: "+fileName);*/
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < lines_without_comments.Count; i++)
|
||||
{
|
||||
String line = lines_without_comments[i];
|
||||
|
||||
if (!(line is string))
|
||||
continue;
|
||||
|
||||
//Console.WriteLine("LINE: " + line);
|
||||
|
||||
foreach (Define define in defines)
|
||||
{
|
||||
|
||||
if (line.IndexOf(define.name) >= 0)
|
||||
{
|
||||
define.references.Add(fileName + " : " + i);
|
||||
totalreferences++;
|
||||
}
|
||||
}
|
||||
|
||||
if( line.ToLower().IndexOf("#define") >= 0 )
|
||||
{
|
||||
line = line.Trim();
|
||||
line = line.Replace('\t', ' ');
|
||||
//Console.WriteLine("LINE = "+line);
|
||||
String[] slist = line.Split(' ');
|
||||
if(slist.Length >= 3){
|
||||
//slist[0] has the value of "#define"
|
||||
String name = slist[1];
|
||||
String value = slist[2];
|
||||
|
||||
for (int j = 3; j < slist.Length; j++)
|
||||
{
|
||||
value += " " + slist[j];
|
||||
//Console.WriteLine("LISTITEM["+j+"] = "+slist[j]);
|
||||
}
|
||||
|
||||
value = value.Trim();
|
||||
|
||||
String comment = "";
|
||||
|
||||
if (value.IndexOf("//") >= 0)
|
||||
{
|
||||
comment = value.Substring(value.IndexOf("//"));
|
||||
value = value.Substring(0, value.IndexOf("//"));
|
||||
}
|
||||
|
||||
comment = comment.Trim();
|
||||
value = value.Trim();
|
||||
|
||||
Define d = new Define(fileName,i,name,value,comment);
|
||||
defines.Add(d);
|
||||
mainform.listBox1.Items.Add(d);
|
||||
mainform.listBox1.Refresh();
|
||||
}else{
|
||||
Define d = new Define(fileName, i, "ERROR ERROR", "Something went wrong here", line);
|
||||
errordefines++;
|
||||
defines.Add(d);
|
||||
mainform.listBox1.Items.Add(d);
|
||||
mainform.listBox1.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Console.WriteLine(e.Message);
|
||||
Console.WriteLine(e.StackTrace);
|
||||
MessageBox.Show("Exception: " + e.Message + " | " + e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
bool iscomment = false;
|
||||
int ismultilinecomment = 0;
|
||||
bool isstring = false;
|
||||
bool ismultilinestring = false;
|
||||
int escapesequence = 0;
|
||||
int stringvar = 0;
|
||||
|
||||
public List<String> remove_comments(List<String> lines)
|
||||
{
|
||||
List<String> r = new List<String>();
|
||||
|
||||
iscomment = false;
|
||||
ismultilinecomment = 0;
|
||||
isstring = false;
|
||||
ismultilinestring = false;
|
||||
|
||||
bool skiponechar = false; //Used so the / in */ doesn't get written;
|
||||
|
||||
for (int i = 0; i < lines.Count(); i++)
|
||||
{
|
||||
|
||||
String line = lines[i];
|
||||
|
||||
if (!(line is String))
|
||||
continue;
|
||||
|
||||
iscomment = false;
|
||||
isstring = false;
|
||||
char ca = ' ';
|
||||
escapesequence = 0;
|
||||
|
||||
String newline = "";
|
||||
|
||||
int k = line.Length;
|
||||
|
||||
for (int j = 0; j < k; j++)
|
||||
{
|
||||
|
||||
char c = line.ToCharArray()[j];
|
||||
|
||||
if (escapesequence == 0)
|
||||
if (normalstatus())
|
||||
{
|
||||
if (ca == '/' && c == '/')
|
||||
{
|
||||
c = ' ';
|
||||
iscomment = true;
|
||||
|
||||
newline = newline.Remove(newline.Length - 1);
|
||||
k = line.Length;
|
||||
}
|
||||
if (ca == '/' && c == '*')
|
||||
{
|
||||
c = ' ';
|
||||
ismultilinecomment = 1;
|
||||
newline = newline.Remove(newline.Length - 1);
|
||||
k = line.Length;
|
||||
}
|
||||
if (c == '"')
|
||||
{
|
||||
isstring = true;
|
||||
}
|
||||
if (ca == '{' && c == '"')
|
||||
{
|
||||
ismultilinestring = true;
|
||||
}
|
||||
}
|
||||
else if (isstring)
|
||||
{
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
escapesequence = 2;
|
||||
}
|
||||
else if (stringvar > 0)
|
||||
{
|
||||
if (c == ']')
|
||||
{
|
||||
stringvar--;
|
||||
}
|
||||
else if (c == '[')
|
||||
{
|
||||
stringvar++;
|
||||
}
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
isstring = false;
|
||||
}
|
||||
else if (c == '[')
|
||||
{
|
||||
stringvar++;
|
||||
}
|
||||
}
|
||||
else if (ismultilinestring)
|
||||
{
|
||||
if (ca == '"' && c == '}')
|
||||
{
|
||||
ismultilinestring = false;
|
||||
}
|
||||
}
|
||||
else if (ismultilinecomment > 0)
|
||||
{
|
||||
if (ca == '/' && c == '*')
|
||||
{
|
||||
c = ' '; //These things are here to prevent /*/ from bieng interpreted as the start and end of a comment.
|
||||
skiponechar = true;
|
||||
ismultilinecomment++;
|
||||
}
|
||||
if (ca == '*' && c == '/')
|
||||
{
|
||||
c = ' '; //These things are here to prevent /*/ from bieng interpreted as the start and end of a comment.
|
||||
skiponechar = true;
|
||||
ismultilinecomment--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iscomment && (ismultilinecomment==0) && !skiponechar)
|
||||
{
|
||||
newline += c;
|
||||
}
|
||||
|
||||
if (skiponechar)
|
||||
{
|
||||
skiponechar = false;
|
||||
}
|
||||
if (escapesequence > 0)
|
||||
{
|
||||
escapesequence--;
|
||||
}
|
||||
else
|
||||
{
|
||||
ca = c;
|
||||
}
|
||||
}
|
||||
|
||||
r.Add(newline.TrimEnd());
|
||||
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private bool normalstatus()
|
||||
{
|
||||
return !isstring && !ismultilinestring && (ismultilinecomment==0) && !iscomment && (escapesequence == 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class Define
|
||||
{
|
||||
public String location;
|
||||
public int line;
|
||||
public String name;
|
||||
public String value;
|
||||
public String comment;
|
||||
public List<String> references;
|
||||
|
||||
public Define(String location, int line, String name, String value, String comment)
|
||||
{
|
||||
this.location = location;
|
||||
this.line = line;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.comment = comment;
|
||||
this.references = new List<String>();
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
return "DEFINE: \""+name+"\" is defined as \""+value+"\" AT "+location+" : "+line;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace UnstandardnessTestForDM
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("UnstandardnessTestForDM")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("UnstandardnessTestForDM")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("c0e09000-1840-4416-8bb2-d86a8227adf1")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.239
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace UnstandardnessTestForDM.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UnstandardnessTestForDM.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.239
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace UnstandardnessTestForDM.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{A0EEBFC9-41D4-474D-853D-126AFDFB82DE}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UnstandardnessTestForDM</RootNamespace>
|
||||
<AssemblyName>UnstandardnessTestForDM</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
-11
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
-18
@@ -1,18 +0,0 @@
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\bin\Debug\UnstandardnessTestForDM.exe
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\bin\Debug\UnstandardnessTestForDM.pdb
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\ResolveAssemblyReference.cache
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.Form1.resources
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.Properties.Resources.resources
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\GenerateResource.read.1.tlog
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\GenerateResource.write.1.tlog
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.exe
|
||||
c:\users\baloh\documents\visual studio 2010\Projects\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.pdb
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\bin\Debug\UnstandardnessTestForDM.exe
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\bin\Debug\UnstandardnessTestForDM.pdb
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\ResolveAssemblyReference.cache
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.Form1.resources
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.Properties.Resources.resources
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\GenerateResource.read.1.tlog
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\GenerateResource.write.1.tlog
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.exe
|
||||
C:\Users\Baloh\Desktop\tgs13\tools\UnstandardnessTestForDM\UnstandardnessTestForDM\obj\x86\Debug\UnstandardnessTestForDM.pdb
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -1,123 +0,0 @@
|
||||
import os, sys
|
||||
"""
|
||||
Usage:
|
||||
$ python countstrings.py path/to/your.dme .dm
|
||||
|
||||
CountStrings.py - Counts strings in DreamMaker code
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
def CountStringsIn(f):
|
||||
numStrings = 0
|
||||
inString = False
|
||||
escaped = False
|
||||
while(True):
|
||||
c = f.read(1)
|
||||
if not c:
|
||||
return numStrings
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
escaped = False
|
||||
continue
|
||||
if c == '"':
|
||||
inString = not inString
|
||||
if not inString:
|
||||
numStrings += 1
|
||||
continue
|
||||
return numStrings
|
||||
|
||||
def ProcessFiles(top='.', ext='.dm'):
|
||||
numStringsTotal = 0
|
||||
numStrings = 0
|
||||
numFilesTotal = 0
|
||||
maxStringsInFile = [0, '']
|
||||
for root, _, files in os.walk(top):
|
||||
for filename in files:
|
||||
filepath = os.path.join(root, filename)
|
||||
if filepath.endswith(ext):
|
||||
with open(filepath, 'r') as f:
|
||||
numStrings = CountStringsIn(f)
|
||||
numStringsTotal += numStrings
|
||||
if numStrings > maxStringsInFile[0]:
|
||||
maxStringsInFile = [numStrings, filepath]
|
||||
numFilesTotal += 1
|
||||
print(','.join([filepath, str(numStrings)]))
|
||||
print('>>> Total Strings: {0}'.format(numStringsTotal))
|
||||
print('>>> Total Files: {0}'.format(numFilesTotal))
|
||||
print('>>> Max Strings: {0} in {1}'.format(maxStringsInFile[0], maxStringsInFile[1]))
|
||||
|
||||
def ProcessFilesFromDME(dmefile='baystation12.dme', ext='.dm'):
|
||||
numStringsTotal = 0
|
||||
numStrings = 0
|
||||
numFilesTotal = 0
|
||||
maxStringsInFile = [0, '']
|
||||
rootdir = os.path.dirname(dmefile)
|
||||
with open(os.path.join(rootdir,'stringcounts.csv'),'w') as csv:
|
||||
with open(dmefile,'r') as dmeh:
|
||||
for line in dmeh:
|
||||
if line.startswith('#include'):
|
||||
inString = False
|
||||
#escaped=False
|
||||
filename=''
|
||||
for c in line:
|
||||
"""
|
||||
if c == '\\' and not escaped:
|
||||
escaped = True
|
||||
continue
|
||||
if escaped:
|
||||
if
|
||||
escaped = False
|
||||
continue
|
||||
"""
|
||||
if c == '"':
|
||||
inString = not inString
|
||||
if not inString:
|
||||
filepath = os.path.join(rootdir, filename)
|
||||
if filepath.endswith(ext):
|
||||
with open(filepath, 'r') as f:
|
||||
numStrings = CountStringsIn(f)
|
||||
numStringsTotal += numStrings
|
||||
if numStrings > maxStringsInFile[0]:
|
||||
maxStringsInFile = [numStrings, filepath]
|
||||
numFilesTotal += 1
|
||||
csv.write(','.join([filepath, str(numStrings)])+"\n")
|
||||
filename=''
|
||||
continue
|
||||
else:
|
||||
if inString:
|
||||
filename += c
|
||||
print('>>> Total Strings: {0}'.format(numStringsTotal))
|
||||
print('>>> Total Files: {0}'.format(numFilesTotal))
|
||||
print('>>> Max Strings: {0} in {1}'.format(maxStringsInFile[0], maxStringsInFile[1]))
|
||||
|
||||
if os.path.isdir(sys.argv[1]):
|
||||
for root, _, files in os.walk(sys.argv[1]):
|
||||
for filename in files:
|
||||
filepath = os.path.join(root, filename)
|
||||
if filepath.endswith('.dme'):
|
||||
ProcessFilesFromDME(filepath,sys.argv[2])
|
||||
sys.exit(0)
|
||||
if os.path.isfile(sys.argv[1]):
|
||||
ProcessFilesFromDME(sys.argv[1],sys.argv[2])
|
||||
#ProcessFiles(sys.argv[1], sys.argv[2])
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import re, os, sys, fnmatch
|
||||
|
||||
|
||||
# Regex pattern to extract the directory path in a #define FILE_DIR
|
||||
filedir_pattern = re.compile(r'^#define\s*FILE_DIR\s*"(.*?)"')
|
||||
|
||||
# Regex pattern to extract any single quoted piece of text. This can also
|
||||
# match single quoted strings inside of double quotes, which is part of a
|
||||
# regular text string and should not be replaced. The replacement function
|
||||
# however will any match that doesn't appear to be a filename so these
|
||||
# extra matches should not be a problem.
|
||||
rename_pattern = re.compile(r"'(.+?)'")
|
||||
|
||||
# Only filenames matching this pattern will have their resources renamed
|
||||
source_pattern = re.compile(r"^.*?\.(dm|dmm)$")
|
||||
|
||||
# Open the .dme file and return a list of all FILE_DIR paths in it
|
||||
def read_filedirs(filename):
|
||||
result = []
|
||||
dme_file = file(filename, "rt")
|
||||
|
||||
# Read each line from the file and check for regex pattern match
|
||||
for row in dme_file:
|
||||
match = filedir_pattern.match(row)
|
||||
if match:
|
||||
result.append(match.group(1))
|
||||
|
||||
dme_file.close()
|
||||
return result
|
||||
|
||||
# Search through a list of directories, and build a dictionary which
|
||||
# maps every file to its full pathname (relative to the .dme file)
|
||||
# If the same filename appears in more than one directory, the earlier
|
||||
# directory in the list takes preference.
|
||||
def index_files(file_dirs):
|
||||
result = {}
|
||||
|
||||
# Reverse the directory list so the earlier directories take precedence
|
||||
# by replacing the previously indexed file of the same name
|
||||
for directory in reversed(file_dirs):
|
||||
for name in os.listdir(directory):
|
||||
# Replace backslash path separators on Windows with forward slash
|
||||
# Force "name" to lowercase when used as a key since BYOND resource
|
||||
# names are case insensitive, even on Linux.
|
||||
if name.find(".") == -1:
|
||||
continue
|
||||
result[name.lower()] = directory.replace('\\', '/') + '/' + name
|
||||
|
||||
return result
|
||||
|
||||
# Recursively search for every .dm/.dmm file in the .dme file directory. For
|
||||
# each file, search it for any resource names in single quotes, and replace
|
||||
# them with the full path previously found by index_files()
|
||||
def rewrite_sources(resources):
|
||||
# Create a closure for the regex replacement function to capture the
|
||||
# resources dictionary which can't be passed directly to this function
|
||||
def replace_func(name):
|
||||
key = name.group(1).lower()
|
||||
if key in resources:
|
||||
replacement = resources[key]
|
||||
else:
|
||||
replacement = name.group(1)
|
||||
return "'" + replacement + "'"
|
||||
|
||||
# Search recursively for all .dm and .dmm files
|
||||
for (dirpath, dirs, files) in os.walk("."):
|
||||
for name in files:
|
||||
if source_pattern.match(name):
|
||||
path = dirpath + '/' + name
|
||||
source_file = file(path, "rt")
|
||||
output_file = file(path + ".tmp", "wt")
|
||||
|
||||
# Read file one line at a time and perform replacement of all
|
||||
# single quoted resource names with the fullpath to that resource
|
||||
# file. Write the updated text back out to a temporary file.
|
||||
for row in source_file:
|
||||
row = rename_pattern.sub(replace_func, row)
|
||||
output_file.write(row)
|
||||
|
||||
output_file.close()
|
||||
source_file.close()
|
||||
|
||||
# Delete original source file and replace with the temporary
|
||||
# output. On Windows, an atomic rename() operation is not
|
||||
# possible like it is under POSIX.
|
||||
os.remove(path)
|
||||
os.rename(path + ".tmp", path)
|
||||
|
||||
dirs = read_filedirs("tgstation.dme");
|
||||
resources = index_files(dirs)
|
||||
rewrite_sources(resources)
|
||||
@@ -1,6 +0,0 @@
|
||||
the compiled exe file for the Unstandardness text for DM program is in:
|
||||
UnstandardnessTestForDM\bin\Debug\UnstandardnessTestForDM.exe
|
||||
of
|
||||
UnstandardnessTestForDM\bin\Release\UnstandardnessTestForDM.exe
|
||||
|
||||
You have to move it to the root folder (where the dme file is) and run it from there for it to work.
|
||||
Reference in New Issue
Block a user