0

textures: fix texturepath option not being used

If the first texture loaded was not in the pack, i.e. we fell back
on system textures, then the pack was ignored altogether for the
remainder of the render.

Here we fix this by using an OrderedDict instead of the split jars
and jarpath nonsense, and then always checking the custom textures
first and opening them if they are not already open, and putting
the jar file handle at the start of the OrderedDict.

We also switch around some logic to avoid unnecessary isdir calls
when we're using a resource pack.
This commit is contained in:
Nicolas F
2019-07-09 14:16:28 +02:00
parent 19042a7669
commit e0e33a9acb

View File

@@ -13,6 +13,7 @@
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>. # with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
from collections import OrderedDict
import sys import sys
import imp import imp
import os import os
@@ -86,8 +87,7 @@ class Textures(object):
self.texture_cache = {} self.texture_cache = {}
# once we find a jarfile that contains a texture, we cache the ZipFile object here # once we find a jarfile that contains a texture, we cache the ZipFile object here
self.jars = [] self.jars = OrderedDict()
self.jarpaths = []
## ##
## pickle support ## pickle support
@@ -101,7 +101,7 @@ class Textures(object):
del attributes[attr] del attributes[attr]
except KeyError: except KeyError:
pass pass
attributes['jars'] = [] attributes['jars'] = OrderedDict()
return attributes return attributes
def __setstate__(self, attrs): def __setstate__(self, attrs):
# regenerate textures, if needed # regenerate textures, if needed
@@ -162,8 +162,8 @@ class Textures(object):
"""Searches for the given file and returns an open handle to it. """Searches for the given file and returns an open handle to it.
This searches the following locations in this order: This searches the following locations in this order:
* In the directory textures_path given in the initializer if not already open
* In an already open resource pack or client jar file * In an already open resource pack or client jar file
* In the directory textures_path given in the initializer
* In the resource pack given by textures_path * In the resource pack given by textures_path
* The program dir (same dir as overviewer.py) for extracted textures * The program dir (same dir as overviewer.py) for extracted textures
* On Darwin, in /Applications/Minecraft for extracted textures * On Darwin, in /Applications/Minecraft for extracted textures
@@ -182,31 +182,11 @@ class Textures(object):
""" """
if verbose: logging.info("Starting search for {0}".format(filename)) if verbose: logging.info("Starting search for {0}".format(filename))
# we've sucessfully loaded something from here before, so let's quickly try
# this before searching again
# We might already know some jarpaths from other processes though.
if len(self.jarpaths) > len(self.jars):
for p in self.jarpaths:
self.jars.append(zipfile.ZipFile(p))
if len(self.jars) > 0:
for jar_num, jar in enumerate(self.jars):
try:
jar.getinfo(filename)
if verbose: logging.info("Found (cached) %s in '%s'", filename,
self.jarpaths[jar_num])
return jar.open(filename)
except (KeyError, IOError) as e:
pass
# A texture path was given on the command line. Search this location # A texture path was given on the command line. Search this location
# for the file first. # for the file first.
if self.find_file_local_path: if self.find_file_local_path:
if os.path.isdir(self.find_file_local_path): if (self.find_file_local_path not in self.jars
full_path = os.path.join(self.find_file_local_path, filename) and os.path.isfile(self.find_file_local_path)):
if os.path.isfile(full_path):
if verbose: logging.info("Found %s in '%s'", filename, full_path)
return open(full_path, mode)
elif os.path.isfile(self.find_file_local_path):
# Must be a resource pack. Look for the requested file within # Must be a resource pack. Look for the requested file within
# it. # it.
try: try:
@@ -216,11 +196,29 @@ class Textures(object):
pack.getinfo(filename) pack.getinfo(filename)
if verbose: logging.info("Found %s in '%s'", filename, if verbose: logging.info("Found %s in '%s'", filename,
self.find_file_local_path) self.find_file_local_path)
self.jars.append(pack) self.jars[self.find_file_local_path] = pack
self.jarpaths.append(self.find_file_local_path) # ok cool now move this to the start so we pick it first
self.jars.move_to_end(self.find_file_local_path, last=False)
return pack.open(filename) return pack.open(filename)
except (zipfile.BadZipfile, KeyError, IOError): except (zipfile.BadZipfile, KeyError, IOError):
pass pass
elif os.path.isdir(self.find_file_local_path):
full_path = os.path.join(self.find_file_local_path, filename)
if os.path.isfile(full_path):
if verbose: logging.info("Found %s in '%s'", filename, full_path)
return open(full_path, mode)
# We already have some jars open, better use them.
if len(self.jars) > 0:
for jarpath in self.jars:
try:
jar = self.jars[jarpath]
jar.getinfo(filename)
if verbose: logging.info("Found (cached) %s in '%s'", filename,
jarpath)
return jar.open(filename)
except (KeyError, IOError) as e:
pass
# If we haven't returned at this point, then the requested file was NOT # If we haven't returned at this point, then the requested file was NOT
# found in the user-specified texture path or resource pack. # found in the user-specified texture path or resource pack.
@@ -301,8 +299,7 @@ class Textures(object):
try: try:
jar.getinfo(filename) jar.getinfo(filename)
if verbose: logging.info("Found %s in '%s'", filename, jarpath) if verbose: logging.info("Found %s in '%s'", filename, jarpath)
self.jars.append(jar) self.jars[jarpath] = jar
self.jarpaths.append(jarpath)
return jar.open(filename) return jar.open(filename)
except (KeyError, IOError) as e: except (KeyError, IOError) as e:
pass pass