From 1b3a4e8cb36c5822783ab7c65e6f7fdd2ad71d10 Mon Sep 17 00:00:00 2001 From: poikilos <7557867+poikilos@users.noreply.github.com> Date: Mon, 14 Mar 2016 02:36:41 -0400 Subject: [PATCH] working on modularization and decachunks plus folder detection and regression suite --- .gitignore | 1 + chunkymap-regen.py | 229 ++++---------- expertmm.py | 374 +++++++++++++++++++++- expertmmregressionsuite.py | 535 ++++++++++++++++++++++---------- expertmmregressiontmp.py | 10 - install-chunkymap-on-windows.py | 2 +- minetestinfo.py | 250 +++++++++++++++ minetestmeta.py | 35 --- web/chunkymap.php | 15 +- 9 files changed, 1059 insertions(+), 392 deletions(-) delete mode 100644 expertmmregressiontmp.py create mode 100644 minetestinfo.py delete mode 100644 minetestmeta.py diff --git a/.gitignore b/.gitignore index 7b36969..0d9b1a6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ chunkymapdata/ chunkymap-genresults/ chunkymap.yml +minetestmeta.yml # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/chunkymap-regen.py b/chunkymap-regen.py index 0b6ab7e..f97a654 100644 --- a/chunkymap-regen.py +++ b/chunkymap-regen.py @@ -13,7 +13,7 @@ import time import shutil import math -from minetestmeta import * +from minetestinfo import * from expertmm import * from PIL import Image, ImageDraw, ImageFont, ImageColor @@ -240,9 +240,6 @@ class MTChunks: is_backend_detected = None chunkymap_players_name = None chunkymap_players_path = None - config = None - config_name = None - config_path = None data_16px_path = None data_160px_path = None FLAG_EMPTY_HEXCOLOR = "#010000" @@ -257,21 +254,8 @@ class MTChunks: self.min_indent = " " self.decachunks = {} self.rendered_this_session_count = 0 - os_name="linux" - if (os.path.sep!="/"): - os_name="windows" - print("Windows detected") self.is_backend_detected = False self.mapvars = {} - self.config = {} - self.config_name = "chunkymap.yml" - self.config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), self.config_name) - self.config = get_dict_modified_by_conf_file(self.config, self.config_path, ":") - is_config_changed = False - if not os.path.isfile(self.config_path): - is_config_changed = True - print("Creating '"+self.config_path+"'") - #if self.config is None: self.mapvars["total_generated_count"] = 0 self.rendered_count = 0 self.preload_all_enable = True @@ -283,33 +267,6 @@ class MTChunks: self.refresh_map_enable = True self.refresh_players_enable = True self.chunks = {} - if "www_minetest_path" not in self.config.keys(): - self.config["www_minetest_path"] = "/var/www/html/minetest" - if os_name=="windows": - self.config["www_minetest_path"] = None - prioritized_try_paths = list() - prioritized_try_paths.append("C:\\wamp\\www") - prioritized_try_paths.append("C:\\www") - prioritized_try_paths.append("C:\\Program Files\\Apache Software Foundation\\Apache2.2\\htdocs") - - #prioritized_try_paths.append("C:\\Program Files\\Apache Software Foundation\\Apache2.2\\htdocs\\folder_test\\website") - for try_path in prioritized_try_paths: - try: - if os.path.isdir(try_path): - self.config["www_minetest_path"] = try_path - break - except: - pass - if self.config["www_minetest_path"] is None: - self.config["www_minetest_path"] = os.path.dirname(os.path.abspath(__file__)) - input_string = raw_input("Minetest website (blank for ["+self.config["www_minetest_path"]+"]): ") - if (len(input_string)>0): - self.config["www_minetest_path"] = input_string - is_config_changed = True - #print("Set www_minetest_path to '"+self.config["www_minetest_path"]+"'") - #else: - print("Using www_minetest_path '"+self.config["www_minetest_path"]+"'") - print("") self.refresh_map_seconds = 30 #does one chunk at a time so as not to interrupt player updates too often self.refresh_players_seconds = 5 @@ -319,83 +276,19 @@ class MTChunks: input_string = "" - - profile_path = None - if os_name=="windows": - profile_path = os.environ['USERPROFILE'] + if minetestinfo.get_var("primary_world_path") is not None: + if os.path.isdir(minetestinfo.get_var("primary_world_path")): + print ("Using primary_world_path '"+minetestinfo.get_var("primary_world_path")+"'") + else: + print ("ERROR: Missing world '"+minetestinfo.get_var("primary_world_path")+"'") + sys.exit(2) else: - profile_path = os.environ['HOME'] - - if "profile_minetest_path" not in self.config.keys(): - self.config["profile_minetest_path"] = os.path.join(profile_path,".minetest") - if (os_name=="windows"): - self.config["profile_minetest_path"] = "C:\\games\\Minetest" - input_string = raw_input("user minetest path containing worlds folder (blank for ["+self.config["profile_minetest_path"]+"]): ") - if (len(input_string)>0): - self.config["profile_minetest_path"] = input_string - is_config_changed = True - print("Using profile_minetest_path '"+self.config["profile_minetest_path"]+"'") - if not os.path.isdir(self.config["profile_minetest_path"]): - print("(WARNING: missing, so please close and update profile_minetest_path in '"+self.config_path+"' before next run)") - print("") - if "worlds_path" not in self.config.keys(): - self.config["worlds_path"] = os.path.join(self.config["profile_minetest_path"],"worlds") - is_config_changed = True - - auto_chosen_world = False - is_missing_world = False - if "world_path" in self.config.keys(): - if not os.path.isdir(self.config["world_path"]): - is_missing_world = True - if ("world_path" not in self.config.keys()) or is_missing_world: - print ("LOOKING FOR WORLDS IN " + self.config["worlds_path"]) - for base_path, dirnames, filenames in os.walk(self.config["worlds_path"]): - #for j in range(0,len(dirnames)): - # i = len(dirnames) - 0 - 1 - # if dirnames[i][0] == ".": - # print (" SKIPPING "+dirnames[i]) - # dirnames.remove_at(i) - world_count = 0 - for subdirname in dirnames: - print (" EXAMINING "+subdirname) - if subdirname[0]!=".": - world_count += 1 - index = 0 - world_number = 0 - for subdirname in dirnames: - print (" EXAMINING "+subdirname) - if subdirname[0]!=".": - #if (index == len(dirnames)-1): # skip first one because the one on my computer is big - if (subdirname!="world") or (world_number==(world_count-1)): - self.config["world_path"] = os.path.join(base_path, subdirname) # os.path.join(self.config["worlds_path"], "try7amber") - auto_chosen_world = True - break - world_number += 1 - index += 1 - if auto_chosen_world: - is_config_changed = True - break - if is_missing_world: - print("MISSING WORLD '"+self.config["world_path"]+"'") - if auto_chosen_world: - print("(so a default was picked below that you can change)") - else: - print("(and no world could be found in worlds_path '"+self.config["worlds_path"]+"')") - - input_string = raw_input("World path (or world name if above; blank for ["+self.config["world_path"]+"]): ") - if (len(input_string)>0): - - try_path = os.path.join(self.config["worlds_path"], input_string) - this_world_path = input_string - if (not os.path.isdir(this_world_path)) and os.path.isdir(try_path): - this_world_path = try_path - self.config["world_path"] = this_world_path - auto_chosen_world = False - is_config_changed = True - print ("Using world_path '"+self.config["world_path"]+"'") - if not os.path.isdir(self.config["world_path"]): - print("(ERROR: missing, so please close immediately and update world_path in '"+self.config_path+"' before next run)") - print("") + print ("ERROR: No primary_world_path") + sys.exit(2) + + #if not os.path.isdir(minetestinfo.get_var("primary_world_path")): + # print("(ERROR: missing, so please close immediately and update primary_world_path in '"+minetestinfo._config_path+"' before next run)") + #print("") self.python_exe_path = "python" if os_name=="windows": @@ -408,7 +301,7 @@ class MTChunks: pass # do nothing - worldmt_path = os.path.join(self.config["world_path"], "world.mt") + worldmt_path = os.path.join(minetestinfo.get_var("primary_world_path"), "world.mt") self.backend_string="sqlite3" if (os.path.isfile(worldmt_path)): ins = open(worldmt_path, 'r') @@ -443,13 +336,14 @@ class MTChunks: print("Chose image generator script: "+self.minetestmapper_py_path) if not os.path.isfile(self.minetestmapper_py_path): print("ERROR: script does not exist, so exiting "+__file__+".") - sys.exit() + sys.exit(2) self.colors_path = os.path.join(os.path.dirname(os.path.abspath(self.minetestmapper_py_path)), "colors.txt") if not os.path.isfile(self.colors_path): print("ERROR: missing '"+self.colors_path+"', so exiting "+__file__+".") - sys.exit() + sys.exit(2) + - self.chunkymap_data_path=os.path.join(self.config["www_minetest_path"],"chunkymapdata") + self.chunkymap_data_path=os.path.join(minetestinfo.get_var("www_minetest_path"),"chunkymapdata") self.chunkymapdata_worlds_path=os.path.join(self.chunkymap_data_path, "worlds") print("Using chunkymap_data_path '"+self.chunkymap_data_path+"'") #if not os.path.isdir(self.chunkymap_data_path): @@ -470,9 +364,7 @@ class MTChunks: self.deny_http_access(self.chunkymapdata_worlds_path) print(" (created .htaccess)") - - - self.world_name = os.path.basename(self.config["world_path"]) + self.world_name = os.path.basename(minetestinfo.get_var("primary_world_path")) self.chunkymap_thisworld_data_path = os.path.join(self.chunkymapdata_worlds_path, self.world_name) if not os.path.isdir(self.chunkymap_thisworld_data_path): os.makedirs(self.chunkymap_thisworld_data_path) @@ -566,8 +458,6 @@ class MTChunks: self.mapvars["max_chunkz"] = 0 if is_mapvars_changed: self.save_mapvars_if_changed() - if is_config_changed: - self.save_config() #def install_default_world_data(self): #source_web_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "web") @@ -582,8 +472,8 @@ class MTChunks: source_web_chunkymapdata_path = os.path.join(source_web_path, "chunkymapdata_default") source_web_chunkymapdata_world_path = os.path.join(source_web_chunkymapdata_path, "world") source_web_chunkymapdata_images_path = os.path.join(source_web_chunkymapdata_path, "images") - dest_web_path = self.config["www_minetest_path"] - dest_web_chunkymapdata_path = os.path.join(self.config["www_minetest_path"],"chunkymapdata") + dest_web_path = minetestinfo.get_var("www_minetest_path") + dest_web_chunkymapdata_path = os.path.join(minetestinfo.get_var("www_minetest_path"),"chunkymapdata") dest_web_chunkymapdata_images_path = os.path.join(dest_web_chunkymapdata_path,"images") install_list = list() install_list.append(InstalledFile("browser.php",source_web_path,dest_web_path)) @@ -596,6 +486,12 @@ class MTChunks: install_list.append(InstalledFile("start.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) install_list.append(InstalledFile("target_start.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) install_list.append(InstalledFile("compass-rose.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) + install_list.append(InstalledFile("arrow-wide-up.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) + install_list.append(InstalledFile("arrow-wide-down.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) + install_list.append(InstalledFile("arrow-wide-left.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) + install_list.append(InstalledFile("arrow-wide-right.png", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) + install_list.append(InstalledFile("chunk-blank.jpg", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) + install_list.append(InstalledFile("decachunk-blank.jpg", source_web_chunkymapdata_images_path, dest_web_chunkymapdata_images_path)) source_chunkymapdata_players = os.path.join(source_web_chunkymapdata_world_path, "players") dest_chunkymapdata_players = os.path.join(self.chunkymap_thisworld_data_path, "players") install_list.append(InstalledFile("singleplayer.png", source_chunkymapdata_players, dest_chunkymapdata_players)) @@ -616,7 +512,7 @@ class MTChunks: if source_mtime_seconds>installed_mtime_seconds: shutil.copyfile(source_path, installed_path) # DOES replace destination file else: - print("WARNING: cannot update file since can't find '"+source_path+"'") + raw_input("WARNING: cannot update file since can't find '"+source_path+"'") def deny_http_access(self, dir_path): @@ -634,8 +530,6 @@ class MTChunks: outs.write(""+"\n") outs.close() - def save_config(self): - save_conf_from_dict(self.config_path, self.config, ":") #locally unique identifier (unique to world only) def get_chunk_luid(self, chunky_x, chunky_z): @@ -696,9 +590,9 @@ class MTChunks: decachunky_x = self.get_decachunky_coord_from_chunky_coord(chunky_x) decachunky_z = self.get_decachunky_coord_from_chunky_coord(chunky_z) chunky_min_x = decachunky_x*10 - chunky_max_x = chunky_min_x + 15 # NOTE: + 15 even if negative since originally, floor was used + chunky_max_x = chunky_min_x + 9 # NOTE: ADD even if negative since originally, floor was used chunky_min_z = decachunky_z*10 - chunky_max_z = chunky_min_z + 15 # NOTE: + 15 even if negative since originally, floor was used + chunky_max_z = chunky_min_z + 9 # NOTE: ADD even if negative since originally, floor was used x_chunky_count = chunky_max_x-chunky_min_x+1 z_chunky_count = chunky_max_z-chunky_min_z+1 is_any_part_queued = False @@ -706,6 +600,7 @@ class MTChunks: queued_chunk_coords = None chunky_offset_z = 0 chunky_z = chunky_min_z + queued_index = None while chunky_z <= chunky_max_z: preview_strings[chunky_offset_z] = "" chunky_x = chunky_min_x @@ -716,6 +611,10 @@ class MTChunks: for index in range(self.todo_index,len(self.todo_positions)): if ivec2_equals(self.todo_positions[index], coords): is_any_part_queued = True + if queued_chunk_coords is None: + queued_chunk_coords = list() + queued_chunk_coords.append(coords) + queued_index = index break if is_any_part_queued: break @@ -730,10 +629,10 @@ class MTChunks: print("") print(" Rendering 160px decachunk "+str((decachunky_x, decachunky_z))) if self.verbose_enable: - print(" USING ("+str(len(chunky_coord_list))+") chunks (region "++":"++","++":"++"): "+str(chunky_coord_list)) + print(" USING ("+str(len(chunky_coord_list))+") chunks (region "+str(chunky_min_x)+":"+str(chunky_max_x)+","+str(chunky_min_z)+":"+str(chunky_max_z)+"): "+str(chunky_coord_list)) print("") else: - print(" USING ("+str(len(chunky_coord_list))+") chunks") + print(" USING ("+str(len(chunky_coord_list))+") chunks (region "+str(chunky_min_x)+":"+str(chunky_max_x)+","+str(chunky_min_z)+":"+str(chunky_max_z)+")") decachunk_global_coords = decachunky_x*160, decachunky_z*160 im = Image.new("RGB", (160, 160), self.FLAG_EMPTY_HEXCOLOR) decachunk_yaml_path = self.get_decachunk_yaml_path_from_decachunk(decachunky_x, decachunky_z) @@ -763,17 +662,17 @@ class MTChunks: im.paste(chunk_im, offset) contains_chunk_luids.append(self.get_chunk_luid(chunky_x, chunky_z)) except: - print("Could not finish "+participle+" in check_decachunk_containing_chunk:") + print(self.min_indent+"Could not finish "+participle+" in check_decachunk_containing_chunk:") view_traceback() else: preview_strings[chunky_offset_z] += "0" chunky_offset_z = z_chunky_count - 1 try: - print(self.min_indent+"Usable chunk images mask:") + print(self.min_indent+"Usable chunk images mask (height:"+str(z_chunky_count)+"):") while chunky_offset_z>=0: if preview_strings[chunky_offset_z] is None: preview_strings[chunky_offset_z] = "" - print(self.min_indent+" "+preview_strings[chunky_offset_z]) + print(self.min_indent+" "+str(chunky_offset_z)+":"+preview_strings[chunky_offset_z]) chunky_offset_z -= 1 except: print(self.min_indent+"Could not finish showing mask (this should never happen)") @@ -788,10 +687,10 @@ class MTChunks: decachunk_folder_path = self.get_decachunk_folder_path_from_decachunk(decachunky_x, decachunky_z) if not os.path.isdir(decachunk_folder_path): os.makedirs(decachunk_folder_path) - print(" Made folder '"+decachunk_folder_path+"'") + print(self.min_indent+"Made folder '"+decachunk_folder_path+"'") else: - print(" Found folder '"+decachunk_folder_path+"'") - print(" Saving '"+decachunk_image_path+"'") + print(self.min_indent+"Found folder '"+decachunk_folder_path+"'") + print(self.min_indent+"Saving '"+decachunk_image_path+"'") im.save(decachunk_image_path) decachunk_luid = self.get_decachunk_luid_from_decachunk(decachunky_x, decachunky_z) self.prepare_decachunk_meta_from_decachunk(decachunky_x, decachunky_z) @@ -804,7 +703,8 @@ class MTChunks: self.decachunks[decachunk_luid].metadata["contains_chunk_luids"] = None self.decachunks[decachunk_luid].save_yaml(decachunk_yaml_path) else: - print("Not rendering decachunk "+str((decachunky_x,decachunky_z))+" yet since contains queued chunk "+str(queued_chunk_coords)+".") + print(self.min_indent+"Not rendering decachunk "+str((decachunky_x,decachunky_z))+" yet since contains queued chunk "+str(queued_chunk_coords)) + print(self.min_indent+" (index:["+str(queued_index)+"]; len:"+str(len(self.todo_positions))+") .") def get_chunk_folder_path(self, chunky_x, chunky_z): result = None @@ -829,7 +729,7 @@ class MTChunks: if decachunky_x is not None and decachunky_z is not None: hectochunky_x = int(math.floor(float(decachunky_x)/10.0)) hectochunky_z = int(math.floor(float(decachunky_z)/10.0)) - result = os.path.join( os.path.join(self.data_160px_path, str(hectochunky_x)), str(hectochunky_x) ) + result = os.path.join( os.path.join(self.data_160px_path, str(hectochunky_x)), str(hectochunky_z) ) return result def create_chunk_folder(self, chunky_x, chunky_z): @@ -1001,7 +901,7 @@ class MTChunks: cmd_suffix = "" cmd_suffix = " > \""+genresult_path+"\"" #self.mapper_id = "minetestmapper-region" - cmd_no_out_string = self.python_exe_path + " \""+self.minetestmapper_py_path + "\" --region " + str(min_x) + " " + str(max_x) + " " + str(min_z) + " " + str(max_z) + " --maxheight "+str(self.mapvars["maxheight"])+" --minheight "+str(self.mapvars["minheight"])+" --pixelspernode "+str(self.mapvars["pixelspernode"])+" \""+self.config["world_path"]+"\" \""+tmp_png_path+"\"" + cmd_no_out_string = self.python_exe_path + " \""+self.minetestmapper_py_path + "\" --region " + str(min_x) + " " + str(max_x) + " " + str(min_z) + " " + str(max_z) + " --maxheight "+str(self.mapvars["maxheight"])+" --minheight "+str(self.mapvars["minheight"])+" --pixelspernode "+str(self.mapvars["pixelspernode"])+" \""+minetestinfo.get_var("primary_world_path")+"\" \""+tmp_png_path+"\"" cmd_string = cmd_no_out_string + cmd_suffix if self.minetestmapper_py_path==self.minetestmapper_custom_path:#if self.backend_string!="sqlite3": #if self.mapper_id=="minetestmapper-region": @@ -1011,7 +911,7 @@ class MTChunks: # mapper_id = "minetest-mapper" # NOTE: minetest-mapper is part of the minetest-data package, which can be installed alongside the git version of minetestserver # BUT *buntu Trusty version of it does NOT have geometry option - # cmd_string = "/usr/games/minetest-mapper --input \""+self.config["world_path"]+"\" --draworigin --geometry "+geometry_value_string+" --output \""+tmp_png_path+"\""+cmd_suffix + # cmd_string = "/usr/games/minetest-mapper --input \""+minetestinfo.get_var("primary_world_path")+"\" --draworigin --geometry "+geometry_value_string+" --output \""+tmp_png_path+"\""+cmd_suffix # such as sudo python minetestmapper --input "/home/owner/.minetest/worlds/FCAGameAWorld" --geometry -32:-32+64+64 --output /var/www/html/minetest/try1.png # OR try PYTHON version (looks for expertmm fork which has geometry option like C++ version does): #script_path = "/home/owner/minetest/util/minetestmapper.py" @@ -1023,8 +923,8 @@ class MTChunks: #script_path = region_capable_script_path geometry_string = str(min_x)+":"+str(min_z)+"+"+str(int(max_x)-int(min_x)+1)+"+"+str(int(max_z)-int(min_z)+1) # +1 since max-min is exclusive and width must be inclusive for minetestmapper.py #expertmm_region_string = str(min_x) + ":" + str(max_x) + "," + str(min_z) + ":" + str(max_z) - #cmd_string="sudo python "+script_path+" --input \""+self.config["world_path"]+"\" --geometry "+geometry_value_string+" --output \""+tmp_png_path+"\""+cmd_suffix - cmd_no_out_string = self.python_exe_path+" "+self.minetestmapper_py_path+" --bgcolor '"+self.FLAG_EMPTY_HEXCOLOR+"' --input \""+self.config["world_path"]+"\" --geometry "+geometry_string+" --output \""+tmp_png_path+"\"" + #cmd_string="sudo python "+script_path+" --input \""+minetestinfo.get_var("primary_world_path")+"\" --geometry "+geometry_value_string+" --output \""+tmp_png_path+"\""+cmd_suffix + cmd_no_out_string = self.python_exe_path+" "+self.minetestmapper_py_path+" --bgcolor '"+self.FLAG_EMPTY_HEXCOLOR+"' --input \""+minetestinfo.get_var("primary_world_path")+"\" --geometry "+geometry_string+" --output \""+tmp_png_path+"\"" cmd_string = cmd_no_out_string + cmd_suffix #sudo python /home/owner/minetest/util/minetestmapper.py --bgcolor '#010000' --input "/home/owner/.minetest/worlds/FCAGameAWorld" --output /var/www/html/minetest/chunkymapdata/entire.png > entire-mtmresult.txt #sudo python /home/owner/minetest/util/chunkymap/minetestmapper.py --input "/home/owner/.minetest/worlds/FCAGameAWorld" --geometry 0:0+16+16 --output /var/www/html/minetest/chunkymapdata/chunk_x0z0.png > /home/owner/minetest/util/chunkymap-genresults/chunk_x0z0_mapper_result.txt @@ -1137,7 +1037,7 @@ class MTChunks: def check_players(self): print("PROCESSING PLAYERS") - players_path = os.path.join(self.config["world_path"], "players") + players_path = os.path.join(minetestinfo.get_var("primary_world_path"), "players") player_count = 0 player_written_count = 0 players_moved_count = 0 @@ -1368,20 +1268,22 @@ class MTChunks: #print(min_indent+chunk_luid+": Not rendered on dest.") return result + + def _check_map_pseudorecursion_branchfrom(self, chunky_x, chunky_z): chunk_luid = self.get_chunk_luid(chunky_x, chunky_z) branched_pos = chunky_x-1, chunky_z #only add if not in list already, to prevent infinite re-branching - if branched_pos not in self.todo_positions: + if vec2_not_in(branched_pos,self.todo_positions): self.todo_positions.append(branched_pos) branched_pos = chunky_x+1, chunky_z - if branched_pos not in self.todo_positions: + if vec2_not_in(branched_pos, self.todo_positions): self.todo_positions.append(branched_pos) branched_pos = chunky_x, chunky_z-1 - if branched_pos not in self.todo_positions: + if vec2_not_in(branched_pos, self.todo_positions): self.todo_positions.append(branched_pos) branched_pos = chunky_x, chunky_z+1 - if branched_pos not in self.todo_positions: + if vec2_not_in(branched_pos, self.todo_positions): self.todo_positions.append(branched_pos) def check_map_pseudorecursion_iterate(self): # , redo_empty_enable=False): @@ -1449,7 +1351,6 @@ class MTChunks: return result def apply_auto_tags_by_worldgen_mods(self, chunky_x, chunky_z): - chunk_luid = self.get_chunk_luid(chunky_x, chunky_z) if chunk_luid not in self.chunks.keys(): self.prepare_chunk_meta(chunky_x, chunky_z) @@ -1463,12 +1364,16 @@ class MTChunks: tags_list[index]=tags_list[index].strip() else: tags_list = list() - #TODO: finish this - for mod_name in mtmeta.worldgen_mod_list: - mod_path = os.path.join(mtmeta.config["mods_path"], mod_name) - #if os.path.isdir(mod_path) - #if is_changed: - # self.save_chunk_meta(chunky_x, chunky_z) + + for mod_name in worldgen_mod_list: + if mod_name in loaded_mod_list: + if mod_name not in tags_list: + tags_list.append(mod_name) + is_changed = True + + if is_changed: + self.chunks[chunk_luid].metadata["tags"] = ','.join(tags_list) + self.save_chunk_meta(chunky_x, chunky_z) def correct_genresults_paths(self): count = 0 diff --git a/expertmm.py b/expertmm.py index 52748af..df67c67 100644 --- a/expertmm.py +++ b/expertmm.py @@ -2,6 +2,26 @@ import os import sys import traceback +verbose_enable = False + + +#formerly pcttext: +#uppercase_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#lowercase_chars = uppercase_chars.lower() +#letter_chars = uppercase_chars+lowercase_chars +digit_chars = "0123456789" +#identifier_chars = letter_chars+"_"+digit_chars +#identifier_and_dot_chars = identifier_chars + "." + +#formerly from expertmmregressionsuite: +alpha_upper_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +alpha_lower_chars = alpha_upper_chars.lower() +alpha_chars = alpha_upper_chars+alpha_lower_chars +#numeric_chars = "1234567890" +alnum_chars = alpha_chars+digit_chars +identifier_chars = alnum_chars+"_" +identifier_and_dot_chars = identifier_chars+"." + class InstalledFile: source_dir_path = None dest_dir_path = None @@ -12,7 +32,7 @@ class InstalledFile: self.source_dir_path=source_dir_path self.dest_dir_path=dest_dir_path -class ConsoleInputConfigFile: +class ConfigManager: #config_name = None _config_path = None _data = None @@ -25,29 +45,49 @@ class ConsoleInputConfigFile: self._ao = assignment_operator_string self._data = get_dict_modified_by_conf_file(self._data, self._config_path, self._ao) - #DOES ask for user input if does not exist - def ask_for_value_if_not_loaded(name, default_value, description): + #DOES ask for user input if does not exist. If default_value is none, do not add to _data if not given + def load_var_or_ask_console_input(self, name, default_value, description): + is_changed = False if name not in self._data: + print("") if default_value is None: + print("WARNING: this program does not have a default value for "+name+".") default_value = "" - answer = raw_input("Please specify "+description+" [blank for "+default_value+"]: ") + answer = raw_input("Please enter "+description+" ("+name+") [blank for "+default_value+"]: ") if answer is not None: answer = answer.strip() - if len(answer)>0: - self_data[name] = answer - else: - self_data[name] = default_value + + if answer is not None and len(answer)>0: + self._data[name] = answer + else: + self._data[name] = default_value + print("Using "+name+" '"+self._data[name]+"'") + is_changed = True + if not os.path.isfile(self._config_path): is_changed = True print("Creating '"+self._config_path+"'") if is_changed: self.save_yaml() + def prepare_var(self, name, default_value, description): + self.load_var_or_ask_console_input(name, default_value, description) + + def contains(self, name): + return (name in self._data.keys()) + + def remove_var(self, name): + try: + del self._data[name] + self.save_yaml() + except KeyError: + pass #DOES autosave IF different val - def set_val(name, val): + def set_var(self, name, val): is_changed = False if name not in self._data.keys(): + print("WARNING to developer: run prepare_var before set_val, so that variable has a default.") is_changed = True elif self._data[name] != val: is_changed = True @@ -55,13 +95,13 @@ class ConsoleInputConfigFile: self._data[name] = val self.save_yaml() - def get_val(name): + def get_var(self, name): result = None if name in self._data: result = self._data[name] return result - def save_yaml() + def save_yaml(self): save_conf_from_dict(self._config_path, self._data, self._ao, save_nulls_enable=False) def get_dict_deepcopy(old_dict): @@ -98,6 +138,15 @@ def is_dict_subset(new_dict, old_dict, verbose_messages_enable, verbose_dest_des view_traceback() return is_changed +def vec2_not_in(this_list, this_vec): + result = False + if this_list is not None and this_vec is not None: + for try_vec in this_list: + if try_vec[0]==this_vec[0] and try_vec[1]==this_vec[1]: + result = True + break + return result + def ivec2_equals(pos1, pos2): return (int(pos1[0])==int(pos2[0])) and (int(pos1[1])==int(pos2[1])) @@ -159,7 +208,7 @@ def print_file(path, min_indent=""): pass return line_count -def get_dict_modified_by_conf_file(this_dict, path,assignment_operator="="): +def get_dict_modified_by_conf_file(this_dict, path, assignment_operator="=", comment_delimiter="#", inline_comments_enable=False): results = this_dict #print ("Checking "+str(path)+" for settings...") if (results is None) or (type(results) is not dict): @@ -171,8 +220,10 @@ def get_dict_modified_by_conf_file(this_dict, path,assignment_operator="="): line = ins.readline() if line and len(line)>0: line_strip=line.strip() - if len(line_strip)>0 and not line_strip[0]=="#": # if not comment + if len(line_strip)>0 and line_strip[0]!=comment_delimiter: # if not comment if not line_strip[0]=="-": # ignore yaml arrays + if inline_comments_enable: + comment_index = line_strip.find(comment_delimiter) ao_index = line_strip.find(assignment_operator) if ao_index>=1: # intentionally skip zero-length variable names if ao_index=3 and len(list_b)>=3: result = (float(list_a[0]) == float(list_b[0])) and (float(list_a[1]) == float(list_b[1])) and (float(list_a[2]) == float(list_b[2])) return False + +def lastchar(val): + result = None + if (val is not None) and (len(val) > 0): + result = val[len(val)-1] + return result + +def get_indent_string(line): + ender_index = find_any_not(line," \t") + result = "" + if ender_index > -1: + result = line[:ender_index] + return result + +def is_identifier_valid(val, is_dot_allowed): + result = False + these_id_chars = identifier_chars + if is_dot_allowed: + these_id_chars = identifier_and_dot_chars + for index in range(0,len(val)): + if val[index] in these_id_chars: + result = True + else: + result = False + break + return result + + +#formerly get_params_len +def get_operation_chunk_len(val, start=0, step=1, line_counting_number=None): + result = 0 + openers = "([{" + closers = ")]}" + quotes = "'\"" + ender = len(val) + direction_msg = "after opening" + if step < 0: + tmp = openers + openers = closers + closers = tmp + ender = -1 + direction_msg = "before closing" + opens = "" + closes = "" + index = start + in_quote = None + line_message = "" + if (line_counting_number is not None) and (line_counting_number>-1): + line_message = "line "+str(line_counting_number)+": " + while (step > 0 and index < ender) or (step < 0 and index > ender): + opener_number = openers.find(val[index]) + closer_number = closers.find(val[index]) + expected_closer = None + if (len(closes)>0): + expected_closer = lastchar(closes) + quote_number = quotes.find(val[index]) + if (in_quote == None) and (opener_number > -1): + opens += openers[opener_number] + closes += closers[opener_number] + elif (in_quote == None) and (closer_number > -1): + if closers[closer_number] == expected_closer: + opens = opens[:len(opens)-1] + closes = closes[:len(closes)-1] + elif quote_number > -1: + if in_quote is None: + in_quote = val[index] + else: + if in_quote == val[index]: + if (index-1 == -1) or (val[index-1]!="\\"): + in_quote = None + index += step + result += 1 + if (in_quote is None) and (len(opens)==0) and ((index>=len(val)) or (val[index] not in identifier_and_dot_chars)): + break + return result + +def find_identifier(line, identifier_string, start=0): + result = -1 + start_index = start + if (identifier_string is not None) and (len(identifier_string) > 0) and (line is not None) and (len(line) > 0): + while True: + try_index = find_unquoted_not_commented(line, identifier_string, start=start_index) + if (try_index > -1): + if ((try_index==0) or (line[try_index-1] not in identifier_chars)) and ((try_index+len(identifier_string)==len(line)) or (line[try_index+len(identifier_string)] not in identifier_chars)): + result = try_index + #input(identifier_string+"starts after '"+line[try_index]+"' ends before '"+line[try_index+len(identifier_string)]+"'") + break + else: + #match is part of a different identifier, so skip it + #input(identifier_string+" does not after '"+line[try_index]+"' ends before '"+line[try_index+len(identifier_string)]+"'") + start_index = try_index + len(identifier_string) + else: + break + return result + +def get_newline_in_data(data): + newline = None + cr = "\r" + lf = "\n" + cr_index = -1 + lf_index = -1 + cr_index = data.find(cr) + lf_index = data.find(lf) + if (cr_index > -1) and (lf_index > -1): + if cr_index < lf_index: + newline = cr+lf + else: + newline = lf+cr + elif cr_index > -1: + newline = cr + elif lf_index > -1: + newline = lf + return newline + +def re_escape_visible(val): + result = val.replace("\n","\\n").replace("\n","\\n") + return result + +def get_newline(file_path): + data = None + with open (file_path, "r") as myfile: + data=myfile.read() + return get_newline_in_data(data) + + + +def is_allowed_in_variable_name_char(one_char): + result = False + if len(one_char) == 1: + if one_char in identifier_chars: + result = True + else: + print("error in is_allowed_in_variable_name_char: one_char must be 1 character") + return result + +def find_any_not(haystack, char_needles, start=None, step = 1): + result = -1 + if (len(char_needles)>0) and (len(haystack)>0): + endbefore = len(haystack) + if start is None: + if step > 0: + start = 0 + elif step < 0: + start = len(haystack)-1 + if step < 0: + endbefore = -1 + index = start + + while (step>0 and indexendbefore): + if not haystack[index:index+1] in char_needles: + result = index + break + index += step + return result + +def explode_unquoted(haystack, delimiter): + elements = list() + while True: + index = find_unquoted_not_commented(haystack, delimiter) + if index >= 0: + elements.append(haystack[:index]) + haystack = haystack[index+1:] + else: + break + elements.append(haystack) #rest of haystack is the param after last comma, else beginning if none + return elements + +#Finds needle in haystack where not quoted, taking into account escape +# sequence for single-quoted or double-quoted string inside haystack. +def find_unquoted_MAY_BE_COMMENTED(haystack, needle, start=0, endbefore=-1, step=1): + result = -1 + + prev_char = None + if (haystack is not None) and (needle is not None) and (len(needle)>0): + in_quote = None + if endbefore > len(haystack): + endbefore = len(haystack) + if endbefore<0: + endbefore = len(haystack) + index = start + if step<0: + index = endbefore - 1 + if verbose_enable: + print(" find_unquoted_not_commented in "+haystack.strip()+":") + while (step>0 and index<=(endbefore-len(needle))) or (step<0 and (index>=0)): + this_char = haystack[index:index+1] + if verbose_enable: + print(" {" + +"index:"+str(index)+";" + +"this_char:"+str(this_char)+";" + +"in_quote:"+str(in_quote)+";" + +"}") + if in_quote is None: + if (this_char == '"') or (this_char == "'"): + in_quote = this_char + elif haystack[index:index+len(needle)] == needle: + result = index + break + else: + if (this_char == in_quote) and (prev_char != "\\"): + in_quote = None + elif haystack[index:index+len(needle)] == needle: + result = index + break + prev_char = this_char + index += step + return result + +#DISCARDS whitespace, and never matches None to None +def find_dup(this_list, discard_whitespace_ignore_None_enable=True, ignore_list=None, ignore_numbers_enable=False): + result = -1 + + if type(this_list) is list: + for i1 in range(0,len(this_list)): + for i2 in range(0,len(this_list)): + i1_strip = None + i2_strip = None + if this_list[i1] is not None: + i1_strip = this_list[i1].strip() + if this_list[i2] is not None: + i2_strip = this_list[i2].strip() + if i1_strip!=None and len(i1_strip)>0 and i2_strip!=None and len(i2_strip)>0: + if (i1!=i2) and (ignore_list is None or i1_strip not in ignore_list) and i1_strip==i2_strip: + number1 = None + #number2 = None + if ignore_numbers_enable: + try: + number1 = int(i1_strip) + except: + try: + number1 = float(i1_strip) + except: + pass + #only need one since they already are known to match as text + #try: + #number2 = int(i2_strip) + #except: + #try: + #number2 = float(i2_strip) + #except: + #pass + if (ignore_numbers_enable and number1 is None) or ((not ignore_numbers_enable)): + result = i2 + if verbose_enable: + print("["+str(i1)+"]:"+str(this_list[i1])+" matches ["+str(i2)+"]:"+str(this_list[i2])) + break + if result>-1: + break + else: + input("ERROR in has_dups: "+str(this_list)+" is not a list") + return result +def has_dups(this_list): + return find_dup(this_list)>-1 +#region formerly pcttext.py + +def find_unquoted_not_commented(haystack, needle, start=0, endbefore=-1, step=1, comment_delimiter="#"): + result = -1 + + prev_char = None + if (haystack is not None) and (needle is not None) and (len(needle)>0): + in_quote = None + if endbefore > len(haystack): + endbefore = len(haystack) + if endbefore<0: + endbefore = len(haystack) + index = start + if step<0: + index = endbefore - 1 + if verbose_enable: + print(" find_unquoted_not_commented in "+haystack.strip()+":") + while (step>0 and index<=(endbefore-len(needle))) or (step<0 and (index>=0)): + this_char = haystack[index:index+1] + if verbose_enable: + print(" {" + +"index:"+str(index)+";" + +"this_char:"+str(this_char)+";" + +"in_quote:"+str(in_quote)+";" + +"}") + if in_quote is None: + if (this_char == comment_delimiter) or (haystack[index:index+3]=="\"\"\""): + break + elif (this_char == '"') or (this_char == "'"): + in_quote = this_char + elif haystack[index:index+len(needle)] == needle: + result = index + break + else: + if (this_char == in_quote) and (prev_char != "\\"): + in_quote = None + elif haystack[index:index+len(needle)] == needle: + result = index + break + prev_char = this_char + index += step + return result + +#endregion formerly pcttext.py diff --git a/expertmmregressionsuite.py b/expertmmregressionsuite.py index cf60d05..6915e09 100644 --- a/expertmmregressionsuite.py +++ b/expertmmregressionsuite.py @@ -12,6 +12,10 @@ module_list.append("keyword") module_list.append("inspect") module_list.append("traceback") +from expertmm import * + + + def view_traceback(): ex_type, ex, tb = sys.exc_info() print(str(ex_type)) @@ -24,7 +28,7 @@ class RegressionMismatch: side_b_string = None endswith_enable = None startswith_enable = None - + def __init__(self, side_a_string, side_b_string, startswith_enable, endswith_enable): self.side_a_string = side_a_string self.side_b_string = side_b_string @@ -35,9 +39,23 @@ global_case_sensitive_enable = None y_enable = False print("Initializing...") regression_mismatches = list() -independent_list = ["index","suffix","prefix","decachunk_x_path"] -print(" (Ignoring the following independent variables:") -print(','.join(independent_list)+")") +independent_list = ["index","suffix","prefix"] +independent_list.append("self") +independent_list.append("int") +independent_list.append("float") +independent_list.append("double") +independent_list.append("long") +independent_list.append("bool") +independent_list.append("str") +independent_list.append("string") +independent_list.append("strlen") +independent_list.append("len") +independent_list.append("os.path.join") +independent_list.append("open") +independent_list.append("close") +independent_list.append("None") +independent_list.append("null") +independent_list.append("NULL") #NOTE: "for decachunk_z_name in os.listdir(decachunk_x_path):" is ok since z folders are in x folder independent_endswith_list = list() for word in independent_list: @@ -83,7 +101,32 @@ if global_case_sensitive_enable is True: if y_enable: regression_mismatches.append(RegressionMismatch("X_","Y_",True,False)) regression_mismatches.append(RegressionMismatch("Y_","Z_",True,False)) +def is_dependend_variable(name): + result = False + for regression_mismatch in regression_mismatches: + if regression_mismatch.startswith_enable: + if startswith(name, regression_mismatch.side_a_string): + result = True + break + if startswith(name, regression_mismatch.side_b_string): + result = True + break + elif regression_mismatch.endswith_enable: + if endswith(name, regression_mismatch.side_a_string): + result = True + break + if endswith(name, regression_mismatch.side_b_string): + result = True + break + else: + if regression_mismatch.side_a_string in name: + result = True + break + elif regression_mismatch.side_a_string in name: + result = True + break + return result #splits by any non-alphanumeric characters #print(keyword.kwlist) # DOESN'T WORK (from linuxbochs on http://stackoverflow.com/questions/6315496/display-a-list-of-user-defined-functions-in-the-python-idle-session ): @@ -103,13 +146,16 @@ print(','.join(function_names)+")") print("") print("") def split_non_alnum(haystack, strip_enable=True, skip_keywords_enable=True): + global independent_list + global function_names + global module_list results = list() index = 0 start_index = 0 while index <= len(haystack): if index==len(haystack) or not haystack[index].isalnum(): word = haystack[start_index:index] - if (not skip_keywords_enable) or (word not in keyword.kwlist and word not in function_names): + if (not skip_keywords_enable) or (word not in keyword.kwlist and word not in function_names and word not in independent_list and word not in module_list): if strip_enable: results.append(word.strip()) else: @@ -118,36 +164,41 @@ def split_non_alnum(haystack, strip_enable=True, skip_keywords_enable=True): index += 1 return results -alpha_upper_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -alpha_lower_chars = alpha_upper_chars.lower() -alpha_chars = alpha_upper_chars+alpha_lower_chars -numeric_chars = "1234567890" -alnum_chars = alpha_chars+numeric_chars -identifier_chars = alnum_chars+"_" issue_count = 0 file_list = list() -def is_identifier(needle): - result = True - for index in range(0,len(needle)): - if needle[index] not in identifier_chars: - result = False - break - return result - -def split_non_identifier(haystack, strip_enable=True, skip_keywords_enable=True, skip_disoriented_enable=True): +#def is_identifier(needle, dot_continues_enable): +# result = True +# +# for index in range(0,len(needle)): +# if needle[index] not in identifier_chars: +# result = False +# break +# return result + +quote_list = "'\"" +def split_non_identifier(haystack, strip_enable=True, skip_keywords_enable=True, skip_independent_enable=True, dot_continues_enable=True): results = list() index = 0 start_index = 0 + is_in_quote_char = None + prev_char = None + escaped_dq_enable = True while index <= len(haystack): - if index==len(haystack) or not is_identifier(haystack[index]): + if index=2: @@ -251,161 +322,295 @@ def check_coord_mismatch(file_path): ins = open(file_path, 'r') line = True global min_indent + is_imported = False + problematic_line_count = 0 + inline_comment_delimiter = "#" + inline_line_break = None + file_path_lower = file_path.lower() + if len(file_path)>3 and (file_path_lower[-3:]==".cs"): + inline_comment_delimiter = "//" + inline_line_break = ";" + elif len(file_path)>2 and (file_path_lower[-2:]==".c"): + inline_comment_delimiter = "//" + inline_line_break = ";" + elif len(file_path)>2 and (file_path_lower[-2:]==".h"): + inline_comment_delimiter = "//" + inline_line_break = ";" + elif len(file_path)>4 and (file_path_lower[-4:]==".hpp"): + inline_comment_delimiter = "//" + inline_line_break = ";" + elif len(file_path)>4 and (file_path_lower[-4:]==".cpp"): + inline_comment_delimiter = "//" + inline_line_break = ";" + elif len(file_path)>4 and (file_path_lower[-4:]==".php"): + inline_comment_delimiter = "//" + inline_line_break = ";" + elif len(file_path)>3 and (file_path_lower[-3:]==".py"): + inline_comment_delimiter = "#" + elif len(file_path)>4 and (file_path_lower[-4:]==".pyw"): + inline_comment_delimiter = "#" + else: + answer=raw_input("what is the inline comment delimiter for the sourcecode file type of "+file_path+" [blank for "+inline_comment_delimiter+"]? ") + if len(answer)>0: + inline_comment_delimiter = answer + + dup_ignore_list = function_names+independent_list+module_list while line: line = ins.readline() + prev_issue_count = issue_count if line: line_strip = line.strip() - if (len(line_strip)>0) and (line_strip[0]!="#"): - ao_index = line_strip.find("=") - import_string = "import " - from_string = "from " - import_index = -1 - if line_strip[:len(import_string)]==import_string: - import_index = 0 - elif line_strip[:len(from_string)]==from_string: - import_string = from_string - import_index = line_strip.find(import_string) - if import_index>=0: - module_string = line_strip[import_index+len(import_string):].strip() - space_index = module_string.find(" ") - if space_index>-1: - module_string = module_string[:space_index] - if module_string not in module_list: - module_list.append(module_string) - try: - #tmp_tuples = list() - import_string = "import "+module_string - exec_string = "tmp_tuples = inspect.getmembers("+module_string+", inspect.isroutine)" - #exec exec_string - try_enable = False - outs = open('expertmmregressiontmp.py','w') - outs.write("def get_module_contents():"+"\n") - outs_indent = " " - outs.write(outs_indent+"results = None"+"\n") - if try_enable: - outs.write(outs_indent+"try:"+"\n") - outs_indent = " " - outs.write(outs_indent+"import inspect"+"\n") - outs.write(outs_indent+import_string+"\n") - outs.write(outs_indent+exec_string+"\n") - outs.write(outs_indent+"results = list()"+"\n") - outs.write(outs_indent+"for function_tuple in tmp_tuples:"+"\n") - outs.write(outs_indent+" results.append(function_tuple[0])"+"\n") - - outs_indent = " " - if try_enable: - outs.write(outs_indent+"except:"+"\n") - outs_indent = " " - outs.write(outs_indent+"print(\"Could not finish get_module_contents\")"+"\n") - outs_indent = " " - outs.write(outs_indent+"return results"+"\n") - outs.write("\n") - outs.close() - import expertmmregressiontmp - tmp_list = expertmmregressiontmp.get_module_contents() - new_list = None - if tmp_list is not None: - new_list = list() - for routine_string in tmp_list: - if routine_string not in function_list: - new_list.append(routine_string) - if new_list is not None: - function_list += new_list - print("Found "+str(len(new_list))+" new method(s) from '"+module_string+"' to ignore: "+','.join(new_list)) - else: - print("unable to import module named '"+module_string+"', so some routines may not be successfully ignored:") - except: - print("Could not finish importing module named '"+module_string+"', so some routines may not be successfully ignored:") - view_traceback() - if ao_index<0: - ao_index = line_strip.find(">") - if ao_index<0: - ao_index = line_strip.find("<") - if ao_index<0: - ao_index = line_strip.find(" in ") - if ao_index>0: # intentionally >0 instead of = - increase_indent() - names_string = line_strip[:ao_index].strip() - values_string = line_strip[ao_index+1:].strip() - name_list = split_non_identifier(names_string) - value_list = split_non_identifier(values_string) - message = None - is_line_problematic = False - for regression_mismatch in regression_mismatches: - both_present = False + comment_index = find_unquoted_MAY_BE_COMMENTED(line_strip, inline_comment_delimiter) + if comment_index>-1: + line_strip = line_strip[:comment_index] + sublines = list() + + + if inline_line_break is not None: + remaining_string = line_strip + while True: + inline_line_break_index = find_unquoted_MAY_BE_COMMENTED(remaining_string, inline_line_break) # do NOT check for INLINE COMMENT since already removed it using detected delimiter above + if inline_line_break_index<0: + break + sublines.append(remaining_string[:inline_line_break_index]) + remaining_string = remaining_string[inline_line_break_index+1:] + + if len(remaining_string)>0: + sublines.append(remaining_string) + else: + sublines.append(line_strip) + for subline in sublines: + line_strip = subline + if (len(line_strip)>0) and (line_strip[0]!="#"): + ao_index = line_strip.find("=") + import_string = "import " + from_string = "from " + import_index = -1 + if line_strip[:len(import_string)]==import_string: + import_index = 0 + elif line_strip[:len(from_string)]==from_string: + import_string = from_string + import_index = line_strip.find(import_string) + if import_index>=0: + module_string = line_strip[import_index+len(import_string):].strip() + space_index = module_string.find(" ") + if space_index>-1: + module_string = module_string[:space_index] + if module_string not in module_list: + module_list.append(module_string) + try: + #tmp_tuples = list() + import_string = "import "+module_string + #exec exec_string + try_enable = False + outs = open('expertmmregressiontmp.py','w') + outs.write("def get_module_contents():"+"\n") + outs_indent = " " + outs.write(outs_indent+"results = None"+"\n") + if try_enable: + outs.write(outs_indent+"try:"+"\n") + outs_indent = " " + outs.write(outs_indent+"import inspect"+"\n") + outs.write(outs_indent+import_string+"\n") + exec_string = "tmp_tuples = inspect.getmembers("+module_string+", inspect.isroutine)" + outs.write(outs_indent+exec_string+"\n") + outs.write(outs_indent+"results = list()"+"\n") + outs.write(outs_indent+"for function_tuple in tmp_tuples:"+"\n") + outs.write(outs_indent+" results.append(function_tuple[0])"+"\n") + + outs_indent = " " + if try_enable: + outs.write(outs_indent+"except:"+"\n") + outs_indent = " " + outs.write(outs_indent+"print(\"Could not finish get_module_contents\")"+"\n") + outs_indent = " " + outs.write(outs_indent+"return results"+"\n") + outs.write("\n") + outs.close() + if is_imported: + reload(expertmmregressiontmp) + else: + import expertmmregressiontmp + tmp_list = expertmmregressiontmp.get_module_contents() + os.remove("expertmmregressiontmp.py") + new_list = None + if tmp_list is not None: + new_list = list() + for routine_string in tmp_list: + if routine_string not in function_list: + new_list.append(routine_string) + if new_list is not None: + function_list += new_list + print("Found "+str(len(new_list))+" new method(s) from '"+module_string+"' to ignore: "+','.join(new_list)) + if len(new_list)>0: + dup_ignore_list = function_names+independent_list+module_list + else: + print("unable to import module named '"+module_string+"', so some routines may not be successfully ignored:") + del expertmmregressiontmp + except: + print("Could not finish importing module named '"+module_string+"', so some routines may not be successfully ignored:") + view_traceback() + if ao_index<0: + ao_index = line_strip.find(">") + if ao_index<0: + ao_index = line_strip.find("<") + if ao_index<0: + ao_index = line_strip.find(" in ") + + + + + if ao_index>0: # intentionally >0 instead of = + increase_indent() + names_string = line_strip[:ao_index].strip() + values_string = line_strip[ao_index+1:].strip() + name_list = split_non_identifier(names_string) + value_list = split_non_identifier(values_string) + message = None + message_prefix = " WARNING: " - only_mismatched_coord_is_present_string = " ERROR (only has mismatch): " - if regression_mismatch.startswith_enable: - if (any_startswith(name_list,regression_mismatch.side_a_string) and not any_startswith(name_list,regression_mismatch.side_b_string)) and any_startswith(value_list,regression_mismatch.side_b_string): - name_index = line.find(regression_mismatch.side_a_string) + 1 - if not both_present: - both_present = any_startswith(value_list,regression_mismatch.side_a_string) - message_prefix = only_mismatched_coord_is_present_string - if message is None: + this_start_index = 0 + names_string = line_strip[:ao_index].strip() + values_string = line_strip[ao_index+1:].strip() + name_list = split_non_identifier(names_string) + value_list = split_non_identifier(values_string) + + #while True: + #this_chunk_len = get_operation_chunk_len(line_strip,this_start_index,1,line_counting_number) + #if this_chunk_len<1: + #break + #partial_string = line_strip[this_start_index:this_start_index+this_chunk_len] + #this_start_index += this_chunk_len + + duplicate_index = find_dup(name_list,ignore_numbers_enable=True) + if duplicate_index>-1: + if name_list[duplicate_index] not in dup_ignore_list: + if is_dependend_variable(name_list[duplicate_index]): + name_index = line.find(name_list[duplicate_index]) + message_prefix = " WARNING: " + issue_count += 1 + message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"name '"+name_list[duplicate_index]+"' is used twice (perhaps other coord should have been used)") + print(message) + break + duplicate_index = find_dup(value_list) + if duplicate_index>-1: + if value_list[duplicate_index] not in dup_ignore_list: + if is_dependend_variable(value_list[duplicate_index]): + name_index = line.find(value_list[duplicate_index]) + message_prefix = " WARNING: " + issue_count += 1 + message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"value '"+value_list[duplicate_index]+"' is used twice (perhaps other coord should have been used)") + print(message) + break + + message = None + + for regression_mismatch in regression_mismatches: + both_present = False + only_mismatched_coord_is_present_string = " ERROR (only has mismatch): " + + message_prefix = " WARNING: " + if regression_mismatch.startswith_enable: + if (any_startswith(name_list,regression_mismatch.side_a_string) and not any_startswith(name_list,regression_mismatch.side_b_string)) and any_startswith(value_list,regression_mismatch.side_b_string): + name_index = line.find(regression_mismatch.side_a_string) + 1 + if not both_present: + both_present = any_startswith(value_list,regression_mismatch.side_a_string) + message_prefix = only_mismatched_coord_is_present_string + #if message is None: message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"name starts with "+regression_mismatch.side_a_string+", but "+regression_mismatch.side_b_string+" on right in check/assignment") - is_line_problematic = True - break - - elif (any_startswith(name_list,regression_mismatch.side_b_string) and not any_startswith(name_list,regression_mismatch.side_a_string)) and any_startswith(value_list,regression_mismatch.side_a_string): - name_index = line.find(regression_mismatch.side_b_string) + 1 - if not both_present: - both_present = any_startswith(value_list,regression_mismatch.side_b_string) - message_prefix = only_mismatched_coord_is_present_string - if message is None: + print(message) + issue_count += 1 + break + + elif (any_startswith(name_list,regression_mismatch.side_b_string) and not any_startswith(name_list,regression_mismatch.side_a_string)) and any_startswith(value_list,regression_mismatch.side_a_string): + name_index = line.find(regression_mismatch.side_b_string) + 1 + if not both_present: + both_present = any_startswith(value_list,regression_mismatch.side_b_string) + message_prefix = only_mismatched_coord_is_present_string + #if message is None: message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"name starts with "+regression_mismatch.side_b_string+", but "+regression_mismatch.side_a_string+" on right in check/assignment") - is_line_problematic = True - break - elif regression_mismatch.endswith_enable: - if (any_endswith(name_list,regression_mismatch.side_a_string) and not any_endswith(name_list,regression_mismatch.side_b_string)) and any_endswith(value_list,regression_mismatch.side_b_string): - name_index = line.find(regression_mismatch.side_a_string) + 1 - if not both_present: - both_present = any_endswith(value_list,regression_mismatch.side_a_string) - message_prefix = only_mismatched_coord_is_present_string - if message is None: + print(message) + issue_count += 1 + break + elif regression_mismatch.endswith_enable: + if (any_endswith(name_list,regression_mismatch.side_a_string) and not any_endswith(name_list,regression_mismatch.side_b_string)) and any_endswith(value_list,regression_mismatch.side_b_string): + name_index = line.find(regression_mismatch.side_a_string) + 1 + if not both_present: + both_present = any_endswith(value_list,regression_mismatch.side_a_string) + message_prefix = only_mismatched_coord_is_present_string + #if message is None: message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"name ends with "+regression_mismatch.side_a_string+", but "+regression_mismatch.side_b_string+" on right in check/assignment") - is_line_problematic = True - break - - elif (any_endswith(name_list,regression_mismatch.side_b_string) and not any_endswith(name_list,regression_mismatch.side_a_string)) and any_endswith(value_list,regression_mismatch.side_a_string): - name_index = line.find(regression_mismatch.side_b_string) + 1 - if not both_present: - both_present = any_endswith(value_list,regression_mismatch.side_b_string) - message_prefix = only_mismatched_coord_is_present_string - if message is None: - message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"name ends with "+regression_mismatch.side_b_string+", but "+regression_mismatch.side_a_string+" on right in check/assignment") - is_line_problematic = True - break - - else: - if (in_any_string(regression_mismatch.side_a_string, name_list) and not in_any_string(regression_mismatch.side_b_string, name_list)) and in_any_string(regression_mismatch.side_b_string, value_list): - value_index = line.find(regression_mismatch.side_a_string) + 1 - if not both_present: - both_present = in_any_string(regression_mismatch.side_a_string, value_list) - message_prefix = only_mismatched_coord_is_present_string - if message is None: + print(message) + issue_count += 1 + break + + elif (any_endswith(name_list,regression_mismatch.side_b_string) and not any_endswith(name_list,regression_mismatch.side_a_string)) and any_endswith(value_list,regression_mismatch.side_a_string): + name_index = line.find(regression_mismatch.side_b_string) + 1 + if not both_present: + both_present = any_endswith(value_list,regression_mismatch.side_b_string) + message_prefix = only_mismatched_coord_is_present_string + if message is None: + message = (file_path+" ("+str(line_counting_number)+","+str(name_index)+")"+message_prefix+"name ends with "+regression_mismatch.side_b_string+", but "+regression_mismatch.side_a_string+" on right in check/assignment") + print(message) + issue_count += 1 + break + + else: + if (in_any_string(regression_mismatch.side_a_string, name_list) and not in_any_string(regression_mismatch.side_b_string, name_list)) and in_any_string(regression_mismatch.side_b_string, value_list): + value_index = line.find(regression_mismatch.side_a_string) + 1 + if not both_present: + both_present = in_any_string(regression_mismatch.side_a_string, value_list) + message_prefix = only_mismatched_coord_is_present_string + #if message is None: message = (file_path+" ("+str(line_counting_number)+","+str(value_index)+")"+message_prefix+"name contains "+regression_mismatch.side_a_string+", but "+regression_mismatch.side_b_string+" on right in check/assignment") - is_line_problematic = True - break - elif (in_any_string(regression_mismatch.side_b_string, name_list) and not in_any_string(regression_mismatch.side_a_string, name_list)) and in_any_string(regression_mismatch.side_a_string, value_list): - value_index = line.find(regression_mismatch.side_b_string) + 1 - if not both_present: - both_present = in_any_string(regression_mismatch.side_b_string, value_list) - message_prefix = only_mismatched_coord_is_present_string - if message is None: + print(message) + issue_count += 1 + break + elif (in_any_string(regression_mismatch.side_b_string, name_list) and not in_any_string(regression_mismatch.side_a_string, name_list)) and in_any_string(regression_mismatch.side_a_string, value_list): + value_index = line.find(regression_mismatch.side_b_string) + 1 + if not both_present: + both_present = in_any_string(regression_mismatch.side_b_string, value_list) + message_prefix = only_mismatched_coord_is_present_string + #if message is None: message = (file_path+" ("+str(line_counting_number)+","+str(value_index)+")"+message_prefix+"name contains "+regression_mismatch.side_b_string+", but "+regression_mismatch.side_a_string+" on right side of check/assignment") - is_line_problematic = True - break - if message is not None: - print("") - print(message) - print(line_strip) - if is_line_problematic: - issue_count += 1 + print(message) + issue_count += 1 + break + if issue_count>prev_issue_count: + print("line "+str(line_counting_number)+": "+line.strip()) + if verbose_enable: + print(" ao_index:"+str(ao_index)) + print(" names: "+','.join(name_list)) + print(" values: "+','.join(value_list)) + print("") + problematic_line_count += 1 line_counting_number += 1 ins.close() +independent_list.append("decachunk_x_path") +independent_list.append("chunk_assoc") +independent_list.append("chunk_luid") +independent_list.append("file_name") +independent_list.append("chunkymap_view_zoom_multiplier") +independent_list.append("\"0\"") +independent_list.append("temp") +independent_list.append("haystack") +independent_list.append("needle") +independent_list.append("line_strip") +independent_list.append("self.chunks") +independent_list.append("self.mapvars") +independent_list.append(".metadata") +independent_list.append("\" \\\"\"") +independent_list.append("\" \"") +independent_list.append("player_position_tuple") + +print(" (Ignoring the following independent variables:") +print(','.join(independent_list)+")") +#verbose_enable = True check_coord_mismatch("chunkymap-regen.py") check_coord_mismatch(os.path.join("web","chunkymap.php")) print("Found "+str(issue_count)+" issue(s) in "+str(len(file_list))+" file(s)") +if (issue_count>0): + print("Please run again after these issues are fixed to check for more on same lines.") raw_input("Press enter to exit...") diff --git a/expertmmregressiontmp.py b/expertmmregressiontmp.py deleted file mode 100644 index 5bc31ce..0000000 --- a/expertmmregressiontmp.py +++ /dev/null @@ -1,10 +0,0 @@ -def get_module_contents(): - results = None - import inspect - import PIL - tmp_tuples = inspect.getmembers(PIL, inspect.isroutine) - results = list() - for function_tuple in tmp_tuples: - results.append(function_tuple[0]) - return results - diff --git a/install-chunkymap-on-windows.py b/install-chunkymap-on-windows.py index d915f40..55a5620 100644 --- a/install-chunkymap-on-windows.py +++ b/install-chunkymap-on-windows.py @@ -76,7 +76,7 @@ if is_detected: detected_msg = " (detected above)" print("") -answer = raw_input("Enter #of bits in your python architecture [blank for "+os_bits+detected_msg+"]: ") +answer = raw_input("Enter #of bits in your PYTHON architecture (may be different from #of bits of Windows) [blank for "+os_bits+detected_msg+"]: ") if answer is not None: answer = answer.strip() diff --git a/minetestinfo.py b/minetestinfo.py new file mode 100644 index 0000000..ebc3389 --- /dev/null +++ b/minetestinfo.py @@ -0,0 +1,250 @@ +import os +from expertmm import * + +#variables to eliminate from chunkymap-regen (and manage here instead): +#os_name +#self.config (use minetestinfo.get_val instead) +#config_name +#config_path +#profile_path + +worldgen_mod_list = list() +worldgen_mod_list.append("caverealms") +worldgen_mod_list.append("ethereal") +worldgen_mod_list.append("lapis") +worldgen_mod_list.append("mines") +worldgen_mod_list.append("mg") # this delays/prevents chunk generation and sometimes crashes in 0.4.13 release (tested on Windows 10) +worldgen_mod_list.append("moretrees") +worldgen_mod_list.append("moreores") +#worldgen_mod_list.append("nature_classic") # NOTE: plantlife_modpack has this and other stuff, but detecting this could help since it is unique to the modpack +worldgen_mod_list.append("plantlife_modpack") #ok if installed as modpack instead of putting individual mods in mods folder +worldgen_mod_list.append("pyramids") +worldgen_mod_list.append("railcorridors") +worldgen_mod_list.append("sea") +worldgen_mod_list.append("technic") +worldgen_mod_list.append("technic_worldgen") +worldgen_mod_list.append("tsm_mines") +worldgen_mod_list.append("tsm_pyramids") +worldgen_mod_list.append("tsm_railcorridors") + +loaded_mod_list = list() + +minetestinfo = ConfigManager(os.path.join(os.path.dirname(os.path.abspath(__file__)), "minetestmeta.yml"), ":") + +os_name="linux" +if (os.path.sep!="/"): + os_name="windows" + print("Windows detected") + +def init_minetestinfo(): + if not minetestinfo.contains("www_minetest_path"): + default_www_minetest_path = "/var/www/html/minetest" + if os_name=="windows": + default_www_minetest_path = None + prioritized_try_paths = list() + prioritized_try_paths.append("C:\\wamp\\www") + prioritized_try_paths.append("C:\\www") + prioritized_try_paths.append("C:\\Program Files\\Apache Software Foundation\\Apache2.2\\htdocs") + prioritized_try_paths.append("C:\\Inetpub\\Wwwroot") + + #prioritized_try_paths.append("C:\\Program Files\\Apache Software Foundation\\Apache2.2\\htdocs\\folder_test\\website") + for try_path in prioritized_try_paths: + try: + if os.path.isdir(try_path): + default_www_minetest_path = try_path + break + except: + pass + if default_www_minetest_path is None: + print("WARNING: could not detect website directory automatically. You need WAMP or similar web server with php 5 or higher to use minetest website scripts. You can change www_minetest_path to your server's website root later by editing '"+minetestinfo._config_path+"'") + default_www_minetest_path = os.path.dirname(os.path.abspath(__file__)) + + minetestinfo.prepare_var("www_minetest_path", default_www_minetest_path, "your web server directory (or other folder where minetest website features and data should be placed)") + + profile_path = None + if os_name=="windows": + profile_path = os.environ['USERPROFILE'] + else: + profile_path = os.environ['HOME'] + + default_profile_minetest_path = os.path.join(profile_path,".minetest") + if (os_name=="windows"): + default_profile_minetest_path = "C:\\games\\Minetest" + minetestinfo.prepare_var("profile_minetest_path", default_profile_minetest_path, "user minetest path containing worlds folder and debug.txt") + if not os.path.isdir(minetestinfo.get_var("profile_minetest_path")): + print("(WARNING: missing "+minetestinfo.get_var("profile_minetest_path")+", so please close and update profile_minetest_path in '"+minetestinfo._config_path+"' before next run)") + print("") + + if not minetestinfo.contains("worlds_path"): + minetestinfo._data["worlds_path"] = os.path.join(minetestinfo.get_var("profile_minetest_path"),"worlds") + minetestinfo.save_yaml() + + default_shared_minetest_path = "/usr/share/games/minetest" + try_path = "/usr/local/share/minetest" + if os_name == "windows": + default_shared_minetest_path = "C:\\Games\\Minetest" + elif os.path.isdir(try_path): + default_shared_minetest_path = try_path + + while True: + minetestinfo.prepare_var("shared_minetest_path", default_shared_minetest_path, "path containing Minetest's games folder") + games_path = os.path.join(minetestinfo.get_var("shared_minetest_path"), "games") + if not os.path.isdir(games_path): + answer=raw_input("WARNING: '"+minetestinfo.get_var("shared_minetest_path")+"' does not contain a games folder. If you use this shared_minetest_path, some features may not work correctly (such as adding worldgen mod labels to chunks, and future programs that may use this metadata to install minetest games). Are you sure you want to use y/n [blank for 'n' (no)]? ") + if answer.lower()=="y" or answer.lower()=="yes": + print("You can change the value of shared_minetest_path later by editing '"+minetestinfo._config_path+"'.") + print("") + break + else: + minetestinfo.remove_var("shared_minetest_path") + else: + break + load_world_and_mod_data() + + +def load_world_and_mod_data(): + #if games_path = + global loaded_mod_list + while len(loaded_mod_list) > 0 : loaded_mod_list.pop() # instead of remaking, pop to ensure global is changed + is_world_changed = False + auto_chosen_world = False + is_missing_world = False + + default_world_path = None + if minetestinfo.contains("primary_world_path"): + if not os.path.isdir(minetestinfo.get_var("primary_world_path")): + is_missing_world = True + print("primary_world_path ERROR: '"+minetestinfo.get_var("primary_world_path")+"' is not a folder.") + + + if (not minetestinfo.contains("primary_world_path")) or is_missing_world: + print ("LOOKING FOR WORLDS IN " + minetestinfo.get_var("worlds_path")) + for base_path, dirnames, filenames in os.walk(minetestinfo.get_var("worlds_path")): + #for j in range(0,len(dirnames)): + # i = len(dirnames) - 0 - 1 + # if dirnames[i][0] == ".": + # print (" SKIPPING "+dirnames[i]) + # dirnames.remove_at(i) + world_count = 0 + for subdirname in dirnames: + print (" EXAMINING "+subdirname) + if subdirname[0]!=".": + world_count += 1 + index = 0 + world_number = 0 + for subdirname in dirnames: + print (" EXAMINING "+subdirname) + if subdirname[0]!=".": + #if (index == len(dirnames)-1): # skip first one because the one on my computer is big + if (subdirname!="world") or (world_number==(world_count-1)): + default_world_path = os.path.join(base_path, subdirname) # os.path.join(minetestinfo.get_var("worlds_path"), "try7amber") + auto_chosen_world = True + break + world_number += 1 + index += 1 + if auto_chosen_world: + break + + if is_missing_world: + print("MISSING WORLD '"+minetestinfo.get_var("primary_world_path")+"'") + if default_world_path is not None: + print("(so a default was picked below that you can change)") + else: + print("(and no world could be found in worlds_path '"+minetestinfo.get_var("worlds_path")+"')") + + default_message = "" + if default_world_path is not None: + default_message = " (or world name if above; blank for ["+default_world_path+"])" + input_string = raw_input("World path"+default_message+": ") + if (len(input_string)>0): + try_path = os.path.join(minetestinfo.get_var("worlds_path"), input_string) + this_primary_world_path = input_string + if (not os.path.isdir(this_primary_world_path)) and os.path.isdir(try_path): + this_primary_world_path = try_path + minetestinfo._data["primary_world_path"] = this_primary_world_path + auto_chosen_world = False + minetestinfo.save_yaml() + + if get_world_var("gameid") != minetestinfo.get_var("game_path"): + is_world_changed = True + + if minetestinfo.contains("game_path") or is_world_changed: + if minetestinfo.contains("game_path"): + default_game_name = minetestinfo.get_var("game_path") + if default_game_name is None: + default_game_name = get_world_var("gameid") + if default_game_name is not None: + print("gameid "+default_game_name+" detected in world.") + + games_path = os.path.join(minetestinfo.get_var("shared_minetest_path"), "games") + game_blacklist = list() # is only used if there is no game defined in world + game_blacklist.append("minetest_game") + games_list = list() + if default_game_name is None: + if os.path.isdir(games_path): + folder_path = games_path + sub_names = os.listdir(folder_path) + real_count = 0 + for sub_name in sub_names: + if (sub_name[:1]!="."): + real_count += 1 + real_index = 0 + for sub_name in sub_names: + sub_path = os.path.join(folder_path,sub_name) + if os.path.isdir(sub_path): + if (sub_name[:1]!="."): + if (sub_name != "minetest_game") or (real_index>=real_count-1): + if default_game_name is None: + default_game_name = sub_name + games_list.append(sub_name) + real_index += 1 + if default_game_name is not None: + path_msg = "" + if len(games_list)>0: + path_msg = " (or game name listed above)" + for try_game_name in games_list: + print(" "+try_game_name) + minetestinfo.prepare_var("game_path",os.path.join(games_path,default_game_name),"game (your subgame) path"+path_msg) + + if (not os.path.isdir(minetestinfo.get_var("game_path"))): + try_path = os.path.join(games_path,minetestinfo.get_var("game_path")) + if os.path.isdir(try_path): + minetestinfo.set_var("game_path",try_path) + + mods_path = None + if minetestinfo.contains("game_path") and os.path.isdir(minetestinfo.get_var("game_path")): + mods_path = os.path.join(minetestinfo.get_var("game_path"), "mods") + folder_path = mods_path + for sub_name in os.listdir(folder_path): + sub_path = os.path.join(folder_path,sub_name) + if os.path.isdir(sub_path): + if (sub_name[:1]!="."): + if get_world_var("load_mod_"+sub_name) == True: + loaded_mod_list.append(sub_name) + else: + print("Could not find game folder '"+minetestinfo.get_var("game_path")+"'. Please fix game_path in '"+minetestinfo._config_path+"' to point to your subgame, so that game and mod management features will work.") + print("Mod list for current game: "+','.join(loaded_mod_list)) + #mods_path + #mod_path = os.path.join(mods_path, mod_name) + #if os.path.isdir(mod_path): + + #if default_game is None: + # game_names = os.listdir +world_mt_mapvars = None +world_mt_mapvars_world_path = None +def get_world_var(name): + result = None + global world_mt_mapvars_world_path + world_path = minetestinfo.get_var("world_path") + + #world_mt_mapvars = None + global world_mt_mapvars + if world_mt_mapvars is None or (world_path != world_mt_mapvars_world_path): + world_mt_mapvars_world_path = world_path + if world_path is not None: + world_mt_mapvars = get_dict_from_conf_file(os.path.join(world_path, "world.mt"),"=") + if (world_mt_mapvars is not None) and name in world_mt_mapvars: + result = world_mt_mapvars[name] + return result + +init_minetestinfo() diff --git a/minetestmeta.py b/minetestmeta.py deleted file mode 100644 index 1130c63..0000000 --- a/minetestmeta.py +++ /dev/null @@ -1,35 +0,0 @@ -import os -from expertmm import * - -class MinetestMetadata: - - config = None - config_name = None - config_path = None - worldgen_mod_list = None - - - def __init__(self): - self.config_name = "minetestmeta.yml" - self.config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), self.config_name) - self.config = {} - self.config = get_dict_modified_by_conf_file(self.config, self.config_path, ":") - is_config_changed = False - if not os.path.isfile(self.config_path): - is_config_changed = True - print("Creating '"+self.config_path+"'") - - self.worldgen_mod_list = list() - self.worldgen_mod_list.append("technic_worldgen") - self.worldgen_mod_list.append("mg") # this delays/prevents chunk generation and sometimes crashes in 0.4.13 release (tested on Windows 10) - self.worldgen_mod_list.append("moreores") - self.worldgen_mod_list.append("lapis") - self.worldgen_mod_list.append("sea") - self.worldgen_mod_list.append("moretrees") - self.worldgen_mod_list.append("caverealms") - #self.worldgen_mod_list.append("nature_classic") # NOTE: plantlife_modpack has this and other stuff, but detecting this could help since it is unique to the modpack - self.worldgen_mod_list.append("plantlife_modpack") #ok if installed as modpack instead of putting individual mods in mods folder - - - -mtmeta = MinetestMetadata() diff --git a/web/chunkymap.php b/web/chunkymap.php index b39b7d4..285aa99 100644 --- a/web/chunkymap.php +++ b/web/chunkymap.php @@ -328,7 +328,10 @@ function echo_chunkymap_canvas() { if ($chunkymap_view_zoom_multiplier<$chunkymap_view_min_zoom) $chunkymap_view_zoom_multiplier = $chunkymap_view_min_zoom; if ($chunkymap_view_zoom_multiplier>$chunkymap_view_max_zoom) $chunkymap_view_zoom_multiplier = $chunkymap_view_max_zoom; - $decachunks_per_page = 1.0/$chunkymap_view_zoom_multiplier; + $decachunks_per_page = intval(1.0/$chunkymap_view_zoom_multiplier); + if ($decachunks_per_page<1) { + $decachunks_per_page = 1; + } $view_w = (($decachunks_per_page*160.0)); $view_h = (($decachunks_per_page*160.0)); $view_left = (($chunkymap_view_x)) - (($view_w/2.0)); @@ -362,13 +365,13 @@ function echo_chunkymap_canvas() { echo ''."\r\n"; echo ' '."\r\n"; echo ' '."\r\n"; - echo " '."\r\n"; + echo " '."\r\n"; echo ' '."\r\n"; echo ' '."\r\n"; $cell_perc=intval(round(100.0/$decachunky_count_x)); echo ' '."\r\n"; - echo " '."\r\n"; - echo ' '."\r\n"; + echo ' '."\r\n"; - echo " '."\r\n"; + echo " '."\r\n"; echo ' '."\r\n"; echo ' '."\r\n"; echo ' '."\r\n"; - echo " '."\r\n"; + echo " '."\r\n"; echo ' '."\r\n"; echo ' '."\r\n"; echo '
'."$td_placeholder_content".'".''.'".''.''."$td_placeholder_content".'
".''.''."\r\n"; + echo " ".''.''."\r\n"; echo ' '."\r\n"; while ($decachunky_z>=$decachunky_min_z) { echo ' '."\r\n"; @@ -398,11 +401,11 @@ function echo_chunkymap_canvas() { } echo '
'."\r\n"; echo '
".''.'".''.'
'."$td_placeholder_content".'".''.'".''.''."$td_placeholder_content".'
'."\r\n";