Workwork
This commit is contained in:
parent
b180214152
commit
1dfc4601d7
@ -1,2 +1,10 @@
|
|||||||
class Buffer(object):
|
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
97
einsteingame/formatter.py
Normal 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
|
@ -2,10 +2,21 @@ from locale import setlocale, LC_ALL, LC_NUMERIC
|
|||||||
|
|
||||||
class Locale(object):
|
class Locale(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.__country = None
|
||||||
|
self.__language = None
|
||||||
|
|
||||||
self.parseLocale(setlocale(LC_ALL, ""))
|
self.parseLocale(setlocale(LC_ALL, ""))
|
||||||
# hack because of numbers in Lua
|
# hack because of numbers in Lua
|
||||||
setlocale(LC_NUMERIC, "C")
|
setlocale(LC_NUMERIC, "C")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def country(self):
|
||||||
|
return self.__country
|
||||||
|
|
||||||
|
@property
|
||||||
|
def language(self):
|
||||||
|
return self.__language
|
||||||
|
|
||||||
def parseLocale(self, name):
|
def parseLocale(self, name):
|
||||||
pos = name.find('.')
|
pos = name.find('.')
|
||||||
|
|
||||||
@ -21,17 +32,16 @@ class Locale(object):
|
|||||||
pos = langAndCountry.find('_')
|
pos = langAndCountry.find('_')
|
||||||
|
|
||||||
if pos < 0:
|
if pos < 0:
|
||||||
language = langAndCountry
|
self.__language = langAndCountry
|
||||||
country = ""
|
self.__country = ''
|
||||||
else:
|
else:
|
||||||
language = langAndCountry[0:pos]
|
self.__language = langAndCountry[0:pos]
|
||||||
country = langAndCountry[pos + 1:]
|
self.__country = langAndCountry[pos + 1:]
|
||||||
|
|
||||||
language = language.lower()
|
self.__language = self.__language.lower()
|
||||||
country = country.lower()
|
self.__country = self.__country.lower()
|
||||||
encoding = encoding.upper()
|
encoding = encoding.upper()
|
||||||
|
|
||||||
|
|
||||||
def splitFileName(fileName):
|
def splitFileName(fileName):
|
||||||
"""
|
"""
|
||||||
Returns tuple of name, extension, lang, country
|
Returns tuple of name, extension, lang, country
|
||||||
@ -87,10 +97,10 @@ def getScore(lang, country, locale):
|
|||||||
|
|
||||||
score = 0
|
score = 0
|
||||||
|
|
||||||
if locale.getCountry() == country:
|
if locale.country == country:
|
||||||
score += 2
|
score += 2
|
||||||
|
|
||||||
if locale.getLanguage() == lang:
|
if locale.language == lang:
|
||||||
score += 4
|
score += 4
|
||||||
|
|
||||||
return score
|
return score
|
||||||
|
@ -11,7 +11,8 @@ gi.require_version('Clutter', '1.0')
|
|||||||
from gi.repository import Clutter
|
from gi.repository import Clutter
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
|
|
||||||
from .resources import ResourcesCollection
|
from .messages import msg
|
||||||
|
from .resources import ResourcesCollection, resources
|
||||||
from .utils import ensureDirExists
|
from .utils import ensureDirExists
|
||||||
|
|
||||||
win32 = False
|
win32 = False
|
||||||
@ -19,8 +20,7 @@ apple = False
|
|||||||
developer = True
|
developer = True
|
||||||
|
|
||||||
PREFIX = '/usr'
|
PREFIX = '/usr'
|
||||||
# Clutter.init()
|
|
||||||
#
|
|
||||||
# stage = Clutter.Stage()
|
# stage = Clutter.Stage()
|
||||||
# stage.connect('destroy', lambda x: Clutter.main_quit())
|
# stage.connect('destroy', lambda x: Clutter.main_quit())
|
||||||
# stage.title = 'Test'
|
# stage.title = 'Test'
|
||||||
@ -48,6 +48,21 @@ PREFIX = '/usr'
|
|||||||
# stage.show()
|
# stage.show()
|
||||||
# Clutter.main()
|
# 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):
|
def loadResources(selfPath):
|
||||||
dirs = []
|
dirs = []
|
||||||
|
|
||||||
@ -65,7 +80,7 @@ def loadResources(selfPath):
|
|||||||
dirs.append("res")
|
dirs.append("res")
|
||||||
dirs.append(".")
|
dirs.append(".")
|
||||||
resources = ResourcesCollection(dirs)
|
resources = ResourcesCollection(dirs)
|
||||||
msg.load()
|
msg.load(resources)
|
||||||
|
|
||||||
def main(script, *args):
|
def main(script, *args):
|
||||||
ensureDirExists(os.environ["HOME"] + "/.einstein")
|
ensureDirExists(os.environ["HOME"] + "/.einstein")
|
||||||
@ -73,7 +88,5 @@ def main(script, *args):
|
|||||||
loadResources(sys.argv[0])
|
loadResources(sys.argv[0])
|
||||||
initScreen()
|
initScreen()
|
||||||
initAudio()
|
initAudio()
|
||||||
menu()
|
# menu()
|
||||||
getStorage().flush()
|
# getStorage().flush()
|
||||||
|
|
||||||
# screen.doneCursors();
|
|
||||||
|
66
einsteingame/messages.py
Normal file
66
einsteingame/messages.py
Normal 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()
|
@ -1,6 +1,7 @@
|
|||||||
from os import listdir
|
from os import listdir
|
||||||
import struct
|
import struct
|
||||||
import io
|
import io
|
||||||
|
import zlib
|
||||||
|
|
||||||
from .buffer import Buffer
|
from .buffer import Buffer
|
||||||
from .i18n import splitFileName, getScore, locale
|
from .i18n import splitFileName, getScore, locale
|
||||||
@ -9,16 +10,73 @@ class ResourceError(Exception):
|
|||||||
def __init__(self, code=None):
|
def __init__(self, code=None):
|
||||||
self.code = code
|
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):
|
class ResourceFile(object):
|
||||||
def __init__(self, fileName, buf=None):
|
def __init__(self, fileName, buf=None):
|
||||||
self.__name = fileName
|
self.__name = fileName
|
||||||
|
|
||||||
if buf is not None:
|
if buf is not None:
|
||||||
buffer = buf
|
self.__buffer = buf
|
||||||
ownBuffer = False
|
self.__ownBuffer = False
|
||||||
else:
|
else:
|
||||||
buffer = Buffer()
|
self.__buffer = Buffer()
|
||||||
ownBuffer = True
|
self.__ownBuffer = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.__stream = open(self.__name, 'rb')
|
self.__stream = open(self.__name, 'rb')
|
||||||
@ -37,6 +95,27 @@ class ResourceFile(object):
|
|||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise Exception("Error loading resource file '{}': {}".format(self.__name, e.message))
|
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):
|
def readInt(self):
|
||||||
return struct.unpack('i', self.__stream.read(4))[0]
|
return struct.unpack('i', self.__stream.read(4))[0]
|
||||||
|
|
||||||
@ -55,7 +134,7 @@ class ResourceFile(object):
|
|||||||
|
|
||||||
def getDirectory(self):
|
def getDirectory(self):
|
||||||
try:
|
try:
|
||||||
self.__stream.seek(-8, io.SEEK_END);
|
self.__stream.seek(-8, io.SEEK_END)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise Exception("Error reading {} directory".format(self.__name))
|
raise Exception("Error reading {} directory".format(self.__name))
|
||||||
|
|
||||||
@ -63,7 +142,7 @@ class ResourceFile(object):
|
|||||||
count = self.readInt()
|
count = self.readInt()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.__stream.seek(start, io.SEEK_SET);
|
self.__stream.seek(start, io.SEEK_SET)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise Exception("Error reading {} directory".format(self.__name))
|
raise Exception("Error reading {} directory".format(self.__name))
|
||||||
|
|
||||||
@ -89,9 +168,13 @@ class ResourcesCollection:
|
|||||||
self.__files = []
|
self.__files = []
|
||||||
self.__buffer = None
|
self.__buffer = None
|
||||||
self.__resources = {}
|
self.__resources = {}
|
||||||
|
self.__groups = {}
|
||||||
self.loadResourceFiles(directories)
|
self.loadResourceFiles(directories)
|
||||||
self.processFiles()
|
self.processFiles()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.__resources.values())
|
||||||
|
|
||||||
def loadResourceFiles(self, directories):
|
def loadResourceFiles(self, directories):
|
||||||
for directory in directories:
|
for directory in directories:
|
||||||
try:
|
try:
|
||||||
@ -119,9 +202,18 @@ class ResourcesCollection:
|
|||||||
res = Resource(res_file, score, de, resName)
|
res = Resource(res_file, score, de, resName)
|
||||||
self.__resources[resName] = res
|
self.__resources[resName] = res
|
||||||
|
|
||||||
if len(de.group) > 0:
|
if len(de['group']) > 0:
|
||||||
groups[de.group].append(res)
|
if de['group'] not in self.__groups:
|
||||||
|
self.__groups[de['group']] = []
|
||||||
|
|
||||||
|
self.__groups[de['group']].append(res)
|
||||||
else:
|
else:
|
||||||
res.addVariant(file, score, de)
|
res.addVariant(res_file, score, de)
|
||||||
|
|
||||||
directory.clear()
|
directory.clear()
|
||||||
|
|
||||||
|
def forEachInGroup(self, group, func):
|
||||||
|
for resource in self.__groups[group]:
|
||||||
|
func(resource)
|
||||||
|
|
||||||
|
resources = None
|
||||||
|
8
einsteingame/screen.py
Normal file
8
einsteingame/screen.py
Normal 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
|
Loading…
x
Reference in New Issue
Block a user