This commit is contained in:
Gergely Polonkai 2015-11-04 13:46:33 +01:00
parent b180214152
commit 1dfc4601d7
7 changed files with 321 additions and 27 deletions

View File

@ -1,2 +1,10 @@
class Buffer(object):
pass
def __init__(self):
self.__size = 0
self.__data = ''
def setSize(self, size):
self.__size = size
def getData(self):
return self.__data

97
einsteingame/formatter.py Normal file
View File

@ -0,0 +1,97 @@
import struct
from enum import Enum
class Formatter(object):
class CmdType(Enum):
EMPTY_CMD = 0
TEXT_COMMAND = 1
INT_ARG = 2
STRING_ARG = 3
DOUBLE_ARG = 4
FLOAT_ARG = 5
def __init__(self, data, offset):
cnt = struct.unpack('i', data[offset:offset + 4])[0]
if cnt == 0:
commandsCnt = argsCnt = 0
commands = NULL
args = NULL
offset += 4
commands = []
commandsCnt = 0
maxArg = 0
argNo = None
for i in range(0, cnt):
typ = data[offset]
offset += 1
size = struct.unpack('i', data[offset:offset + 4])[0]
offset += 4
if typ == 1:
commands.append({
"type": self.CmdType.TEXT_COMMAND,
"data": data[offset:offset + size].decode('utf-8'),
})
elif typ == 2:
argNo = struct.unapack('i', data[offset:offset + 4])[0]
if argNo > maxArg:
maxArg = argNo
commands.append({
"type": self.CmdType.INT_ARG,
"data": argNo,
})
elif typ == 3:
argNo = struct.unapack('i', data[offset:offset + 4])[0]
if argNo > maxArg:
maxArg = argNo
commands.append({
"type": self.CmdType.STRING_ARG,
"data": argNo,
})
elif typ == 3:
argNo = struct.unapack('i', data[offset:offset + 4])[0]
if argNo > maxArg:
maxArg = argNo
commands.append({
"type": self.CmdType.FLOAT_ARG,
"data": argNo,
})
elif typ == 3:
argNo = struct.unapack('i', data[offset:offset + 4])[0]
if argNo > maxArg:
maxArg = argNo
commands.append({
"type": self.CmdType.DOUBLE_ARG,
"data": argNo,
})
offset += size;
argsCnt = maxArg
if argsCnt == 0:
args = None
else:
args = []
for i in range(0, len(commands)):
args.append[0]
for i in range(0, len(commands)):
c = commands[i]
if c.type == INT_ARG or c.type == STRING_ARG or c.type == FLOAT_ARG or c.type == DOUBLE_ARG:
no = c.data
args[no - 1] = c.type

View File

@ -2,10 +2,21 @@ from locale import setlocale, LC_ALL, LC_NUMERIC
class Locale(object):
def __init__(self):
self.__country = None
self.__language = None
self.parseLocale(setlocale(LC_ALL, ""))
# hack because of numbers in Lua
setlocale(LC_NUMERIC, "C")
@property
def country(self):
return self.__country
@property
def language(self):
return self.__language
def parseLocale(self, name):
pos = name.find('.')
@ -21,17 +32,16 @@ class Locale(object):
pos = langAndCountry.find('_')
if pos < 0:
language = langAndCountry
country = ""
self.__language = langAndCountry
self.__country = ''
else:
language = langAndCountry[0:pos]
country = langAndCountry[pos + 1:]
self.__language = langAndCountry[0:pos]
self.__country = langAndCountry[pos + 1:]
language = language.lower()
country = country.lower()
self.__language = self.__language.lower()
self.__country = self.__country.lower()
encoding = encoding.upper()
def splitFileName(fileName):
"""
Returns tuple of name, extension, lang, country
@ -87,10 +97,10 @@ def getScore(lang, country, locale):
score = 0
if locale.getCountry() == country:
if locale.country == country:
score += 2
if locale.getLanguage() == lang:
if locale.language == lang:
score += 4
return score

View File

@ -11,7 +11,8 @@ gi.require_version('Clutter', '1.0')
from gi.repository import Clutter
from gi.repository import GLib
from .resources import ResourcesCollection
from .messages import msg
from .resources import ResourcesCollection, resources
from .utils import ensureDirExists
win32 = False
@ -19,8 +20,7 @@ apple = False
developer = True
PREFIX = '/usr'
# Clutter.init()
#
# stage = Clutter.Stage()
# stage.connect('destroy', lambda x: Clutter.main_quit())
# stage.title = 'Test'
@ -48,6 +48,21 @@ PREFIX = '/usr'
# stage.show()
# Clutter.main()
stage = None
sound = None
def initScreen():
Clutter.init()
stage = Clutter.Stage()
stage.connect('destroy', lambda x: Clutter.main_quit())
stage.set_size(800, 600)
stage.title = 'Einstein'
def initAudio():
# sound = Sound()
pass
def loadResources(selfPath):
dirs = []
@ -65,7 +80,7 @@ def loadResources(selfPath):
dirs.append("res")
dirs.append(".")
resources = ResourcesCollection(dirs)
msg.load()
msg.load(resources)
def main(script, *args):
ensureDirExists(os.environ["HOME"] + "/.einstein")
@ -73,7 +88,5 @@ def main(script, *args):
loadResources(sys.argv[0])
initScreen()
initAudio()
menu()
getStorage().flush()
# screen.doneCursors();
# menu()
# getStorage().flush()

66
einsteingame/messages.py Normal file
View File

@ -0,0 +1,66 @@
import struct
from .buffer import Buffer
from .formatter import Formatter
class Messages(object):
def __init__(self):
self.__messages = {}
def load(self, resources):
buf = Buffer()
resources.forEachInGroup('messages', lambda res: self.loadFromResource(res, buf))
def loadFromResource(self, resource, buf):
if not resource:
return
cnt = resource.getVariantsCount()
for variant in resource.variants:
if variant:
try:
score = variant.i18nScore
data = variant.getData()
self.loadBundle(score, data)
except Exception as e:
print("Error loading text bundle {}: {}".format(resource.getName(), e))
raise
def loadBundle(self, score, data):
if data[0:3] != b"CMF":
raise Exception("Invalid format of message file!")
version = struct.unpack('i', data[3:7])[0]
if version != 1:
raise Exception("Unknown version of message file!")
offset = struct.unpack('i', data[len(data) - 4:])[0]
cnt = struct.unpack('i', data[offset:offset + 4])[0]
offset += 4
for i in range(0, cnt):
sz = struct.unpack('i', data[offset:offset + 4])[0]
offset += 4;
if sz > 0:
name = data[offset:offset + sz].decode('utf-8')
msgOffset = struct.unpack('i', data[offset + sz:offset + sz + 4])[0]
if name in self.__messages:
ss = self.__messages[name]
if ss['score'] <= score:
ss['score'] = score
ss['message'] = Formatter(data, msgOffset)
else:
self.__messages[name] = {
"score": score,
"message": Formatter(data, msgOffset),
}
offset += sz + 4
msg = Messages()

View File

@ -1,6 +1,7 @@
from os import listdir
import struct
import io
import zlib
from .buffer import Buffer
from .i18n import splitFileName, getScore, locale
@ -9,16 +10,73 @@ class ResourceError(Exception):
def __init__(self, code=None):
self.code = code
class ResVariant(object):
def __init__(self, resFile, i18nScore, dirEntry):
self.__file = resFile
self.__i18nScore = i18nScore
self.__offset = dirEntry['offset']
self.__unpackedSize = dirEntry['unpackedSize']
self.__packedSize = dirEntry['packedSize']
self.__level = dirEntry['level']
self.__refCnt = 0
self.__data = None
@property
def i18nScore(self):
return self.__i18nScore
def getData(self):
buf = Buffer()
buf.setSize(self.__unpackedSize)
if self.__refCnt == 0:
self.__data = self.__file.load(self.__offset, self.__packedSize, self.__unpackedSize, self.__level)
return self.__data
class Resource(object):
def __init__(self, file, i18nScore, entry, name):
self.__variants = []
self.__name = name
self.addVariant(file, i18nScore, entry)
def addVariant(self, file, i18nScore, entry):
if len(self.__variants) == 0:
self.__variants.append(ResVariant(file, i18nScore, entry))
return
try:
best_variant = [idx for idx, variant in enumerate(self.__variants) \
if variant.i18nScore == i18nScore][0]
self.__variants[best_variant] = ResVariant(file, i18nScore, entry)
except KeyError:
self.__variants.append(ResVariant(file, i18nScore, entry))
self.__variants.sort(key=lambda variant: variant.getI18nScore())
def getVariantsCount(self):
return len(self.__variants)
@property
def variants(self):
return self.__variants
def getName(self):
return self.__name
class ResourceFile(object):
def __init__(self, fileName, buf=None):
self.__name = fileName
if buf is not None:
buffer = buf
ownBuffer = False
self.__buffer = buf
self.__ownBuffer = False
else:
buffer = Buffer()
ownBuffer = True
self.__buffer = Buffer()
self.__ownBuffer = True
try:
self.__stream = open(self.__name, 'rb')
@ -37,6 +95,27 @@ class ResourceFile(object):
except IOError as e:
raise Exception("Error loading resource file '{}': {}".format(self.__name, e.message))
def load(self, offset, packedSize, unpackedSize, level):
try:
if level == 0:
self.__stream.seek(offset, io.SEEK_SET)
self.__stream.read()
return self.__stream.read(unpackedSize)
self.__stream.seek(offset, io.SEEK_SET)
data = self.__stream.read(packedSize)
return self.unpack(data)
except Exception as e:
print("Eror loading resource: {}".format(e))
raise
# void ResourceFile::unpack(char *in, int inSize, char *out, int outSize)
def unpack(self, data):
return zlib.decompress(data)
def readInt(self):
return struct.unpack('i', self.__stream.read(4))[0]
@ -55,7 +134,7 @@ class ResourceFile(object):
def getDirectory(self):
try:
self.__stream.seek(-8, io.SEEK_END);
self.__stream.seek(-8, io.SEEK_END)
except IOError:
raise Exception("Error reading {} directory".format(self.__name))
@ -63,7 +142,7 @@ class ResourceFile(object):
count = self.readInt()
try:
self.__stream.seek(start, io.SEEK_SET);
self.__stream.seek(start, io.SEEK_SET)
except IOError:
raise Exception("Error reading {} directory".format(self.__name))
@ -89,9 +168,13 @@ class ResourcesCollection:
self.__files = []
self.__buffer = None
self.__resources = {}
self.__groups = {}
self.loadResourceFiles(directories)
self.processFiles()
def __iter__(self):
return iter(self.__resources.values())
def loadResourceFiles(self, directories):
for directory in directories:
try:
@ -119,9 +202,18 @@ class ResourcesCollection:
res = Resource(res_file, score, de, resName)
self.__resources[resName] = res
if len(de.group) > 0:
groups[de.group].append(res)
if len(de['group']) > 0:
if de['group'] not in self.__groups:
self.__groups[de['group']] = []
self.__groups[de['group']].append(res)
else:
res.addVariant(file, score, de)
res.addVariant(res_file, score, de)
directory.clear()
def forEachInGroup(self, group, func):
for resource in self.__groups[group]:
func(resource)
resources = None

8
einsteingame/screen.py Normal file
View File

@ -0,0 +1,8 @@
class Screen(object):
def __init__(self):
self.__screen = None
self.__mouseImage = None
self.__mouseSave = None
self.__mouseVisible = None
self.__regionsList = None
self.__maxRegionsList = 0