Browse Source

now py file is loopable

use the option: --loop true
then send signals to it with chunkymap-signals.txt (see README and
example)
master
poikilos 9 years ago
committed by Jacob Gustafson
parent
commit
c2b252bef5
  1. 6
      README.md
  2. 10
      chunkymap-genresults/chunk_x-4z5_mapper_result.txt
  3. 575
      chunkymap-regen.py
  4. 11
      chunkymap-signals example.txt
  5. 2
      web/chunkymap.php
  6. 3
      web/example.php
  7. 14
      web/example_chunkymapdataDir_generatedFile.yml

6
README.md

@ -7,6 +7,9 @@ License: (see LICENSE in notepad or your favorite text editor)
This program comes without any warranty, to the extent permitted by applicable law. This program comes without any warranty, to the extent permitted by applicable law.
## Features: ## Features:
* To loop program (reduces disc reads since stores certain info) run like:
chunkymap-regen.py --loop true
* Change program status while looping by placing chunkymap-signals.txt in the same folder as chunkymap-regen.py (see chunkymap-signals example.txt)
* Has static html version of map (echo_chunkymap_table() php function) * Has static html version of map (echo_chunkymap_table() php function)
* Zoom in and out * Zoom in and out
* optionally echo name of world that was detected by the scheduled py file * optionally echo name of world that was detected by the scheduled py file
@ -16,6 +19,9 @@ This program comes without any warranty, to the extent permitted by applicable l
* Has optional script to add crontab entry (to schedule update script every minute that runs the py file unless the py file is not complete [took longer than 1 minute]) * Has optional script to add crontab entry (to schedule update script every minute that runs the py file unless the py file is not complete [took longer than 1 minute])
## Developer Notes:
* the map update function is only able to detect new chunks, and only checks edge chunks if player is present in one
## Requirements: ## Requirements:
* A minetest version compatible with minetestmapper-numpy.py Made by Jogge, modified by celeron55 * A minetest version compatible with minetestmapper-numpy.py Made by Jogge, modified by celeron55
* Python 2.7 (any 2.7.x) * Python 2.7 (any 2.7.x)

10
chunkymap-genresults/chunk_x-4z5_mapper_result.txt

@ -0,0 +1,10 @@
Result image (w=16 h=16) will be written to C:\Users\jgustafson\Documents\GitHub\minetest-chunkymap\chunk_x-4z5.png
Unknown node names: default:grass_1 flowers:mushroom_fertile_brown flowers:mushroom_fertile_red air
Unknown node ids: 0x0 0x1 0x9 0xc 0x7
Drawing image
Saving to: C:\Users\jgustafson\Documents\GitHub\minetest-chunkymap\chunk_x-4z5.png
('PNG Region: ', [-64, -64, 80, 80])
('pngMinX: ', '-64')
('pngMaxZ: ', '80')
('Pixels PerNode: ', 1)
('border: ', 0)

575
chunkymap-regen.py

@ -3,7 +3,18 @@ import os
import subprocess import subprocess
import traceback import traceback
import argparse import argparse
import time
import sys
import timeit
from timeit import default_timer as best_timer
#best_timer = timeit.default_timer
#if sys.platform == "win32":
# on Windows, the best timer is time.clock()
# best_timer = time.clock
#else:
# on most other platforms, the best timer is time.time()
# best_timer = time.time
# REQUIRES: see README.md # REQUIRES: see README.md
# The way to do a full render is deleting all files from the folder self.chunkymap_data_path such as /var/www/html/minetest/chunkymapdata (or chunkymap in current directory on Windows) # The way to do a full render is deleting all files from the folder self.chunkymap_data_path such as /var/www/html/minetest/chunkymapdata (or chunkymap in current directory on Windows)
@ -15,9 +26,30 @@ import argparse
#region server-specific options #region server-specific options
def get_dict_from_conf_file(path,assignment_operator="="): def get_dict_from_conf_file(path,assignment_operator="="):
results = None
results = get_dict_modified_by_conf_file(results, path, assignment_operator)
return results
def RepresentsInt(s):
try:
int(s)
return True
except ValueError:
return False
def RepresentsFloat(s):
try:
float(s)
return True
except ValueError:
return False
def get_dict_modified_by_conf_file(this_dict, path,assignment_operator="="):
results = None results = None
#print ("Checking "+str(path)+" for settings...") #print ("Checking "+str(path)+" for settings...")
if os.path.isfile(path): if os.path.isfile(path):
results = this_dict
if (results is None) or (type(results) is not dict):
results = {} results = {}
ins = open(path, 'r') ins = open(path, 'r')
line = True line = True
@ -32,11 +64,35 @@ def get_dict_from_conf_file(path,assignment_operator="="):
if ao_index<len(line_strip)-1: # skip yaml implicit nulls or yaml objects if ao_index<len(line_strip)-1: # skip yaml implicit nulls or yaml objects
result_name = line_strip[:ao_index].strip() result_name = line_strip[:ao_index].strip()
result_value = line_strip[ao_index+1:].strip() result_value = line_strip[ao_index+1:].strip()
result_lower = result_value.lower()
if result_value=="None" or result_value=="null" or result_value=="~" or result_value=="NULL":
result_value = None
elif result_lower=="true":
result_value = True
elif result_lower=="false":
result_value = False
elif RepresentsInt(result_value):
result_value = int(result_value)
elif RepresentsFloat(result_value):
result_value = float(result_value)
#print (" CHECKING... "+result_name+":"+result_value) #print (" CHECKING... "+result_name+":"+result_value)
results[result_name]=result_value results[result_name]=result_value
ins.close() ins.close()
return results return results
def save_conf_from_dict(path, this_dict, assignment_operator="=", save_nulls_enable=True):
try:
outs = open(path, 'w')
for this_key in this_dict.keys():
if save_nulls_enable or (this_dict[this_key] is not None):
if this_dict[this_key] is None:
outs.write(this_key+assignment_operator+"null\n")
else:
outs.write(this_key+assignment_operator+str(this_dict[this_key])+"\n")
outs.close()
except:
print("Could not finish saving chunk metadata to '"+str(yml_path)+"': "+str(traceback.format_exc()))
def get_tuple_from_notation(line, debug_src_name="<unknown object>"): def get_tuple_from_notation(line, debug_src_name="<unknown object>"):
result = None result = None
if line is not None: if line is not None:
@ -69,49 +125,138 @@ def is_same_fvec3(list_a, list_b):
class MTChunk: class MTChunk:
x = None x = None
z = None z = None
chunk_dict = None
is_player_in_this_chunk = None is_player_in_this_chunk = None
is_fresh = None is_fresh = None
width = None #width = None
height = None #height = None
is_marked = None #is_marked = None
is_marked_empty = None #is_marked_empty = None
image_w = None #image_w = None
image_h = None #image_h = None
image_left = None #image_left = None
image_top = None #image_top = None
image_right = None #image_right = None
image_bottom = None #image_bottom = None
def __init__(self): def __init__(self):
# NOTE: variables that need to be saved (and only they) should be stored in dict
self.chunk_dict = {}
self.is_player_in_this_chunk = False self.is_player_in_this_chunk = False
self.is_fresh = False self.is_fresh = False
self.is_marked = False
self.is_marked_empty = False self.chunk_dict["is_marked_empty"] = False
self.chunk_dict["is_marked"] = False
self.chunk_dict["width"] = None
self.chunk_dict["height"] = None
self.chunk_dict["image_w"] = None
self.chunk_dict["image_h"] = None
self.chunk_dict["image_left"] = None
self.chunk_dict["image_top"] = None
self.chunk_dict["image_right"] = None
self.chunk_dict["image_bottom"] = None
def load_yaml(self, yml_path):
self.chunk_dict = get_dict_modified_by_conf_file(self.chunk_dict,yml_path,":")
def save_yaml(self, yml_path): def save_yaml(self, yml_path):
save_conf_from_dict(yml_path, self.chunk_dict, assignment_operator=":", save_nulls_enable=False)
#try:
#outs = open(yml_path, 'w')
#outs.write("is_marked_empty:"+str(self.is_marked_empty)+"\n")
#outs.write("is_marked:"+str(self.is_marked)+"\n")
#if self.width is not None:
#outs.write("width:"+str(self.width)+"\n")
#if self.height is not None:
#outs.write("height:"+str(self.height)+"\n")
#if self.image_w is not None:
#outs.write("image_w:"+str(self.image_w)+"\n")
#if self.image_h is not None:
#outs.write("image_h:"+str(self.image_h)+"\n")
#if self.image_left is not None:
#outs.write("image_left:"+str(self.image_left)+"\n")
#if self.image_top is not None:
#outs.write("image_top:"+str(self.image_top)+"\n")
#if self.image_right is not None:
#outs.write("image_right:"+str(self.image_right)+"\n")
#if self.image_bottom is not None:
#outs.write("image_bottom:"+str(self.image_bottom)+"\n")
#outs.close()
#except:
#print("Could not finish saving chunk metadata to '"+str(yml_path)+"': "+str(traceback.format_exc()))
#requires output such as from minetestmapper-numpy.py
def set_from_genresult(self, this_genresult_path):
#this_genresult_path = mtchunks.get_chunk_genresult_path(chunk_luid)
result = False
if os.path.isfile(this_genresult_path):
#may have data such as:
#Result image (w=16 h=16) will be written to chunk_x0z0.png
#Unknown node names: meze:meze default:stone_with_iron air default:dirt_with_snow default:stone_with_copper default:snow
#Unknown node ids: 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
#Drawing image
#Saving to: chunk_x0z0.png
#('PNG Region: ', [0, 64, 0, 64])
#('Pixels PerNode: ', 1)
#('border: ', 0)
self.chunk_dict["is_marked"] = True
ins = open(this_genresult_path, 'r')
line = True
while line:
line = ins.readline()
if line:
line_strip = line.strip()
if "data does not exist" in line_strip:
self.chunk_dict["is_marked_empty"] = True
break
elif "Result image" in line_strip:
oparen_index = line_strip.find("(")
if (oparen_index>-1):
cparen_index = line_strip.find(")", oparen_index+1)
if (cparen_index>-1):
operations_string = line_strip[oparen_index+1:cparen_index]
operation_list = operations_string.split(" ")
#if len(operation_list)==2:
for operation_string in operation_list:
if "=" in operation_string:
chunks = operation_string.split("=")
if len(chunks)==2:
if chunks[0].strip()=="w":
try: try:
outs = open(yml_path, 'w') self.chunk_dict["image_w"]=int(chunks[1].strip())
outs.write("is_marked_empty:"+str(self.is_marked_empty)+"\n")
outs.write("is_marked:"+str(self.is_marked)+"\n")
if self.width is not None:
outs.write("width:"+str(self.width)+"\n")
if self.height is not None:
outs.write("height:"+str(self.height)+"\n")
if self.image_w is not None:
outs.write("image_w:"+str(self.image_w)+"\n")
if self.image_h is not None:
outs.write("image_h:"+str(self.image_h)+"\n")
if self.image_left is not None:
outs.write("image_left:"+str(self.image_left)+"\n")
if self.image_top is not None:
outs.write("image_top:"+str(self.image_top)+"\n")
if self.image_right is not None:
outs.write("image_right:"+str(self.image_right)+"\n")
if self.image_bottom is not None:
outs.write("image_bottom:"+str(self.image_bottom)+"\n")
outs.close()
except: except:
print("Could not finish saving chunk metadata to '"+str(yml_path)+"': "+str(traceback.format_exc())) print("Bad value for image w:"+str(chunks[1]))
elif chunks[0].strip()=="h":
try:
self.chunk_dict["image_h"]=int(chunks[1].strip())
except:
print("Bad value for image h:"+str(chunks[1]))
else:
print("Bad name for image variable so ignoring variable named '"+str(chunks[0])+"'")
else:
print("Bad assignment (not 2 sides) so ignoring command '"+operation_string+"'")
else:
print("Bad assignment (operator) so ignoring command '"+operation_string+"'")
#else:
# print("Bad assignment count so ignoring operations string '"+operations_string+"'")
elif "PNG Region" in line_strip:
obracket_index = line_strip.find("[")
if obracket_index>-1:
cbracket_index = line_strip.find("]", obracket_index+1)
if cbracket_index>-1:
rect_values_string = line_strip[obracket_index+1:cbracket_index]
rect_values_list = rect_values_string.split(",")
if len(rect_values_list)==4:
#pngregion=[pngminx, pngmaxx, pngminz, pngmaxz] #from minetestmapper-numpy.py
self.chunk_dict["image_left"]=int(rect_values_list[0].strip())
self.chunk_dict["image_right"]=int(rect_values_list[1].strip())
self.chunk_dict["image_top"]=int(rect_values_list[2].strip())
self.chunk_dict["image_bottom"]=int(rect_values_list[3].strip())
else:
print("Bad map rect, so ignoring: "+rect_values_string)
ins.close()
class MTChunks: class MTChunks:
@ -142,24 +287,35 @@ class MTChunks:
pixelspernode = 1 pixelspernode = 1
refresh_map_enable = None refresh_map_enable = None
refresh_players_enable = None refresh_players_enable = None
refresh_map_seconds = None
refresh_players_seconds = None
last_players_refresh_second = None
last_map_refresh_second = None
#ALSO save to YAML: #ALSO save to YAML:
#total_generated_count = 0 #total_generated_count = 0
#endregion values to save to YAML #endregion values to save to YAML
loop_enable = None
is_verbose = None
world_blacklist = None world_blacklist = None
def __init__(self): #formerly checkpaths() in global scope def __init__(self): #formerly checkpaths() in global scope
self.is_verbose = True
self.loop_enable = True
self.refresh_map_enable = True self.refresh_map_enable = True
self.refresh_players_enable = True self.refresh_players_enable = True
self.chunks = {} self.chunks = {}
self.username = "owner" self.username = "owner"
self.website_root="/var/www/html/minetest" self.website_root="/var/www/html/minetest"
self.world_name = "FCAGameAWorld" self.world_name = "FCAGameAWorld"
os_name="linux" self.os_name="linux"
self.refresh_map_seconds = 10
self.refresh_players_seconds = 3
input_string = "" input_string = ""
if (os.path.sep!="/"): if (os.path.sep!="/"):
os_name="windows" self.os_name="windows"
#input_string = input("Which self.username contains minetest/util/minetestmapper-numpy.py (minetest not .minetest) ["+self.username+"]?") #input_string = input("Which self.username contains minetest/util/minetestmapper-numpy.py (minetest not .minetest) ["+self.username+"]?")
if (len(input_string)>0): if (len(input_string)>0):
self.username = input_string self.username = input_string
@ -174,13 +330,13 @@ class MTChunks:
self.world_name = input_string self.world_name = input_string
#region server-specific options #region server-specific options
self.profiles_path = "/home" self.profiles_path = "/home"
if os_name=="windows": if self.os_name=="windows":
self.profiles_path = "C:\\Users" self.profiles_path = "C:\\Users"
self.profile_path = os.path.join(self.profiles_path, self.username) self.profile_path = os.path.join(self.profiles_path, self.username)
#if (not os.path.isdir(self.profile_path)): #if (not os.path.isdir(self.profile_path)):
# self.profile_path = os.path.join(self.profiles_path, "jgustafson") # self.profile_path = os.path.join(self.profiles_path, "jgustafson")
self.dotminetest_path = os.path.join(self.profile_path,".minetest") self.dotminetest_path = os.path.join(self.profile_path,".minetest")
if (os_name=="windows"): self.dotminetest_path = "C:\\games\\Minetest" if (self.os_name=="windows"): self.dotminetest_path = "C:\\games\\Minetest"
self.worlds_path = os.path.join(self.dotminetest_path,"worlds") self.worlds_path = os.path.join(self.dotminetest_path,"worlds")
self.world_path = os.path.join(self.worlds_path, self.world_name) self.world_path = os.path.join(self.worlds_path, self.world_name)
auto_chosen_world = False auto_chosen_world = False
@ -211,22 +367,23 @@ class MTChunks:
break break
self.python_exe_path = "python" self.python_exe_path = "python"
self.is_save_output_ok = True # this is probably required to avoid minutely writes self.is_save_output_ok = True # Keeping output after analyzing it is no longer necessary since results are saved to YAML, but keeping output provides debug info since is the output of minetestmapper-numpy.py
try: try:
alt_path = "C:\\python27\python.exe" alt_path = "C:\\python27\python.exe"
if os.path.isfile(alt_path): if os.path.isfile(alt_path):
self.python_exe_path = alt_path self.python_exe_path = alt_path
#else may be in path--assume installer worked
except: except:
pass # do nothing, probably linux pass # do nothing, probably linux
self.mtmn_path = os.path.join( self.profile_path, "minetest/util/minetestmapper-numpy.py" ) self.mtmn_path = os.path.join( self.profile_path, "minetest/util/minetestmapper-numpy.py" )
self.colors_path = os.path.join( self.profile_path, "minetest/util/colors.txt" ) self.colors_path = os.path.join( self.profile_path, "minetest/util/colors.txt" )
if os_name=="windows": if self.os_name=="windows":
self.mtmn_path = os.path.join(os.path.dirname(__file__), "minetestmapper-numpy.py") self.mtmn_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "minetestmapper-numpy.py")
self.colors_path = os.path.join(os.path.dirname(__file__), "colors.txt") self.colors_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "colors.txt")
self.website_root = os.path.dirname(__file__) self.website_root = os.path.dirname(os.path.abspath(__file__))
self.chunkx_min = 0 self.chunkx_min = 0
self.chunkz_min = 0 self.chunkz_min = 0
@ -238,76 +395,6 @@ class MTChunks:
self.minheight = -32 self.minheight = -32
self.pixelspernode = 1 self.pixelspernode = 1
def set_from_genresult(self, mtchunk, chunk_luid):
dest_genresult_path = self.get_chunk_genresult_path(chunk_luid)
result = False
if os.path.isfile(dest_genresult_path):
#may have data such as:
#Result image (w=16 h=16) will be written to chunk_x0z0.png
#Unknown node names: meze:meze default:stone_with_iron air default:dirt_with_snow default:stone_with_copper default:snow
#Unknown node ids: 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
#Drawing image
#Saving to: chunk_x0z0.png
#('PNG Region: ', [0, 64, 0, 64])
#('Pixels PerNode: ', 1)
#('border: ', 0)
mtchunk.is_marked = True
ins = open(dest_genresult_path, 'r')
line = True
while line:
line = ins.readline()
if line:
line_strip = line.strip()
if "data does not exist" in line_strip:
mtchunk.is_marked_empty = True
break
elif "Result image" in line_strip:
oparen_index = line_strip.find("(")
if (oparen_index>-1):
cparen_index = line_strip.find(")", oparen_index+1)
if (cparen_index>-1):
operations_string = line_strip[oparen_index+1:cparen_index]
operation_list = operations_string.split(" ")
#if len(operation_list)==2:
for operation_string in operation_list:
if "=" in operation_string:
chunks = operation_string.split("=")
if len(chunks)==2:
if chunks[0].strip()=="w":
try:
mtchunk.image_w=int(chunks[1].strip())
except:
print("Bad value for image w:"+str(chunks[1]))
elif chunks[0].strip()=="h":
try:
mtchunk.image_h=int(chunks[1].strip())
except:
print("Bad value for image h:"+str(chunks[1]))
else:
print("Bad name for image variable so ignoring variable named '"+str(chunks[0])+"'")
else:
print("Bad assignment (not 2 sides) so ignoring command '"+operation_string+"'")
else:
print("Bad assignment (operator) so ignoring command '"+operation_string+"'")
#else:
# print("Bad assignment count so ignoring operations string '"+operations_string+"'")
elif "PNG Region" in line_strip:
obracket_index = line_strip.find("[")
if obracket_index>-1:
cbracket_index = line_strip.find("]", obracket_index+1)
if cbracket_index>-1:
rect_values_string = line_strip[obracket_index+1:cbracket_index]
rect_values_list = rect_values_string.split(",")
if len(rect_values_list)==4:
#pngregion=[pngminx, pngmaxx, pngminz, pngmaxz] #from minetestmapper-numpy.py
mtchunk.image_left=int(rect_values_list[0].strip())
mtchunk.image_right=int(rect_values_list[1].strip())
mtchunk.image_top=int(rect_values_list[2].strip())
mtchunk.image_bottom=int(rect_values_list[3].strip())
else:
print("Bad map rect, so ignoring: "+rect_values_string)
ins.close()
@ -335,7 +422,13 @@ class MTChunks:
return "chunk_"+chunk_luid+".png" return "chunk_"+chunk_luid+".png"
def get_chunk_image_tmp_path(self, chunk_luid): def get_chunk_image_tmp_path(self, chunk_luid):
return os.path.join(os.path.dirname(__file__), self.get_chunk_image_name(chunk_luid)) return os.path.join(os.path.dirname(os.path.abspath(__file__)), self.get_chunk_image_name(chunk_luid))
def get_signal_name(self):
return "chunkymap-signals.txt"
def get_signal_path(self):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), self.get_signal_name())
def get_chunk_image_path(self, chunk_luid): def get_chunk_image_path(self, chunk_luid):
return os.path.join(self.chunkymap_data_path, self.get_chunk_image_name(chunk_luid)) return os.path.join(self.chunkymap_data_path, self.get_chunk_image_name(chunk_luid))
@ -343,8 +436,11 @@ class MTChunks:
def get_chunk_genresult_name(self, chunk_luid): def get_chunk_genresult_name(self, chunk_luid):
return "chunk_"+chunk_luid+"_mapper_result.txt" return "chunk_"+chunk_luid+"_mapper_result.txt"
def get_chunk_genresults_tmp_folder(self, chunk_luid):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), "chunkymap-genresults")
def get_chunk_genresult_tmp_path(self, chunk_luid): def get_chunk_genresult_tmp_path(self, chunk_luid):
return os.path.join(os.path.dirname(__file__), self.get_chunk_genresult_name(chunk_luid)) return os.path.join(self.get_chunk_genresults_tmp_folder(chunk_luid), self.get_chunk_genresult_name(chunk_luid))
def get_chunk_yaml_name(self, chunk_luid): def get_chunk_yaml_name(self, chunk_luid):
return "chunk_"+chunk_luid+".yml" return "chunk_"+chunk_luid+".yml"
@ -389,43 +485,6 @@ class MTChunks:
ins.close() ins.close()
return result return result
def get_chunk_genresult_path(self, chunk_luid):
return os.path.join(self.chunkymap_data_path, self.get_chunk_genresult_name(chunk_luid))
#deprecated
def is_genresult_marked(self, chunk_luid):
result = False
dest_genresult_path = self.get_chunk_genresult_path(chunk_luid)
if os.path.isfile(dest_genresult_path):
result = True
return result
#deprecated
def is_genresult_marked_empty(self, chunk_luid):
dest_genresult_path = self.get_chunk_genresult_path(chunk_luid)
result = False
if os.path.isfile(dest_genresult_path):
ins = open(dest_genresult_path, 'r')
line = True
while line:
line = ins.readline()
if line:
line_strip = line.strip()
if "data does not exist" in line_strip:
result = True
break
ins.close()
return result
def remove_genresult(self, chunk_luid):
result = False
dest_genresult_path = self.get_chunk_genresult_path(chunk_luid)
if os.path.isfile(dest_genresult_path):
result = True
os.remove(dest_genresult_path)
return result
def remove_chunk_image(self, chunk_luid): def remove_chunk_image(self, chunk_luid):
result = False result = False
tmp_png_path = self.get_chunk_image_path(chunk_luid) tmp_png_path = self.get_chunk_image_path(chunk_luid)
@ -436,49 +495,54 @@ class MTChunks:
def remove_chunk(self, chunk_luid): def remove_chunk(self, chunk_luid):
result = False result = False
out_path = self.get_chunk_genresult_path(chunk_luid) out_path = self.get_chunk_genresult_tmp_path(chunk_luid)
tmp_png_path = self.get_chunk_image_path(chunk_luid) tmp_png_path = self.get_chunk_image_path(chunk_luid)
if os.path.isfile(out_path): yml_path = self.get_chunk_yaml_path(chunk_luid)
os.remove(out_path)
result = True
if os.path.isfile(tmp_png_path): if os.path.isfile(tmp_png_path):
os.remove(tmp_png_path) os.remove(tmp_png_path)
result = True result = True
if os.path.isfile(yml_path):
os.remove(yml_path)
result = True
if os.path.isfile(out_path):
os.remove(out_path)
result = True
return result return result
def is_chunk_rendered_on_dest(self, chunk_luid): #formerly is_chunk_empty_on_dest (reversed) def is_chunk_rendered_on_dest(self, chunk_luid): #formerly is_chunk_empty_on_dest (reversed)
is_rendered = False is_rendered = False
#is_chunk_out_empty = self.is_chunk_yaml_marked_empty(chunk_luid)
#dest_genresult_path = self.get_chunk_genresult_path(chunk_luid)
dest_png_path = self.get_chunk_image_path(chunk_luid) dest_png_path = self.get_chunk_image_path(chunk_luid)
if os.path.isfile(dest_png_path): if os.path.isfile(dest_png_path):
#os.remove(dest_genresult_path)
is_rendered = True is_rendered = True
return is_rendered return is_rendered
def prepare_chunk_meta(self, chunk_luid): def prepare_chunk_meta(self, chunk_luid):
if chunk_luid not in self.chunks.keys(): if chunk_luid not in self.chunks.keys():
self.chunks[chunk_luid] = MTChunk() self.chunks[chunk_luid] = MTChunk()
yaml_path = self.get_chunk_yaml_path(chunk_luid)
if os.path.isfile(yaml_path):
self.chunks[chunk_luid].load_yaml(yaml_path)
def render_chunk(self, x, z): def render_chunk(self, x, z):
result = False result = False
chunk_luid = self.get_chunk_luid(x,z) chunk_luid = self.get_chunk_luid(x,z)
png_name = self.get_chunk_image_name(chunk_luid) png_name = self.get_chunk_image_name(chunk_luid)
tmp_png_path = self.get_chunk_image_tmp_path(chunk_luid) tmp_png_path = self.get_chunk_image_tmp_path(chunk_luid)
cmd_suffix = ""
genresult_name = self.get_chunk_genresult_name(chunk_luid) genresult_name = self.get_chunk_genresult_name(chunk_luid)
genresult_tmp_folder_path = self.get_chunk_genresults_tmp_folder(chunk_luid)
if not os.path.isdir(genresult_tmp_folder_path):
os.makedirs(genresult_tmp_folder_path)
genresult_path = self.get_chunk_genresult_tmp_path(chunk_luid) genresult_path = self.get_chunk_genresult_tmp_path(chunk_luid)
if self.is_save_output_ok:
cmd_suffix = " > \""+genresult_path+"\""
x_min = x * self.chunk_size x_min = x * self.chunk_size
x_max = x * self.chunk_size + self.chunk_size - 1 x_max = x * self.chunk_size + self.chunk_size - 1
z_min = z * self.chunk_size z_min = z * self.chunk_size
z_max = z * self.chunk_size + self.chunk_size - 1 z_max = z * self.chunk_size + self.chunk_size - 1
#print ("generating x = " + str(x_min) + " to " + str(x_max) + " , z = " + str(z_min) + " to " + str(z_max)) #print ("generating x = " + str(x_min) + " to " + str(x_max) + " , z = " + str(z_min) + " to " + str(z_max))
cmd_suffix = ""
cmd_suffix = " > \""+genresult_path+"\""
cmd_string = self.python_exe_path + " \""+self.mtmn_path + "\" --region " + str(x_min) + " " + str(x_max) + " " + str(z_min) + " " + str(z_max) + " --maxheight "+str(self.maxheight)+" --minheight "+str(self.minheight)+" --pixelspernode "+str(self.pixelspernode)+" \""+self.world_path+"\" \""+tmp_png_path+"\"" + cmd_suffix cmd_string = self.python_exe_path + " \""+self.mtmn_path + "\" --region " + str(x_min) + " " + str(x_max) + " " + str(z_min) + " " + str(z_max) + " --maxheight "+str(self.maxheight)+" --minheight "+str(self.minheight)+" --pixelspernode "+str(self.pixelspernode)+" \""+self.world_path+"\" \""+tmp_png_path+"\"" + cmd_suffix
dest_png_path = self.get_chunk_image_path(chunk_luid) dest_png_path = self.get_chunk_image_path(chunk_luid)
dest_genresult_path = self.get_chunk_genresult_path(chunk_luid)
#is_empty_chunk = is_chunk_yaml_marked(chunk_luid) and is_chunk_yaml_marked_empty(chunk_luid) #is_empty_chunk = is_chunk_yaml_marked(chunk_luid) and is_chunk_yaml_marked_empty(chunk_luid)
print (cmd_string) print (cmd_string)
subprocess.call(cmd_string, shell=True) # TODO: remember not to allow arbitrary command execution, which could happen if input contains ';' when using shell=True subprocess.call(cmd_string, shell=True) # TODO: remember not to allow arbitrary command execution, which could happen if input contains ';' when using shell=True
@ -492,27 +556,23 @@ class MTChunks:
try: try:
os.rename(tmp_png_path, dest_png_path) os.rename(tmp_png_path, dest_png_path)
print("(moved to '"+dest_png_path+"')") print("(moved to '"+dest_png_path+"')")
self.prepare_chunk_meta(chunk_luid) self.prepare_chunk_meta(chunk_luid) # DOES load existing yml if exists
self.chunks[chunk_luid].is_fresh = True self.chunks[chunk_luid].is_fresh = True
except: except:
print ("Could not finish moving '"+tmp_png_path+"' to '"+dest_png_path+"'") print ("Could not finish moving '"+tmp_png_path+"' to '"+dest_png_path+"'")
try: try:
if (os.path.isfile(dest_genresult_path)): self.prepare_chunk_meta(chunk_luid) # DOES load existing yml if exists
os.remove(dest_genresult_path) this_chunk = self.chunks[chunk_luid]
if self.is_save_output_ok: #this_chunk = MTChunk()
this_chunk.set_from_genresult(genresult_path)
#os.rename(genresult_path, dest_genresult_path)
#print("(moved to '"+dest_genresult_path+"')")
tmp_chunk = MTChunk()
self.set_from_genresult(tmp_chunk,chunk_luid)
chunk_yaml_path = self.get_chunk_yaml_path(chunk_luid) chunk_yaml_path = self.get_chunk_yaml_path(chunk_luid)
tmp_chunk.save_yaml(chunk_yaml_path) this_chunk.save_yaml(chunk_yaml_path)
this_chunk.save_yaml(chunk_yaml_path)
print("(saved yaml to '"+chunk_yaml_path+"')") print("(saved yaml to '"+chunk_yaml_path+"')")
os.remove(genresult_path) if not self.is_save_output_ok:
else:
if os.path.isfile(genresult_path): if os.path.isfile(genresult_path):
os.remove(genresult_path) os.remove(genresult_path)
except: except:
print ("Could not finish deleting/moving output") print ("Could not finish deleting/moving output")
@ -523,6 +583,7 @@ class MTChunks:
def check_players(self): def check_players(self):
# NOT NEEDED: if os.path.isfile(self.mtmn_path) and os.path.isfile(self.colors_path): # NOT NEEDED: if os.path.isfile(self.mtmn_path) and os.path.isfile(self.colors_path):
print("PROCESSING PLAYERS")
self.chunkymap_data_path=os.path.join(self.website_root,"chunkymapdata") self.chunkymap_data_path=os.path.join(self.website_root,"chunkymapdata")
chunkymap_players_name = "players" chunkymap_players_name = "players"
chunkymap_players_path = os.path.join(self.chunkymap_data_path, chunkymap_players_name) chunkymap_players_path = os.path.join(self.chunkymap_data_path, chunkymap_players_name)
@ -535,6 +596,9 @@ class MTChunks:
players_path = os.path.join(self.world_path, "players") players_path = os.path.join(self.world_path, "players")
player_count = 0 player_count = 0
player_written_count = 0 player_written_count = 0
players_moved_count = 0
players_didntmove_count = 0
players_saved_count = 0
for dirname, dirnames, filenames in os.walk(players_path): for dirname, dirnames, filenames in os.walk(players_path):
for filename in filenames: for filename in filenames:
file_fullname = os.path.join(players_path,filename) file_fullname = os.path.join(players_path,filename)
@ -582,7 +646,7 @@ class MTChunks:
chunk_y = int((float(player_y)/self.chunk_size)) chunk_y = int((float(player_y)/self.chunk_size))
chunk_z = int((float(player_z)/self.chunk_size)) chunk_z = int((float(player_z)/self.chunk_size))
chunk_luid = self.get_chunk_luid(chunk_x, chunk_z) chunk_luid = self.get_chunk_luid(chunk_x, chunk_z)
self.prepare_chunk_meta(chunk_luid) self.prepare_chunk_meta(chunk_luid) # DOES load existing yml if exists
self.chunks[chunk_luid].is_player_in_this_chunk = True self.chunks[chunk_luid].is_player_in_this_chunk = True
#if is_enough_data: #if is_enough_data:
@ -601,15 +665,18 @@ class MTChunks:
if "z" in map_player_dict.keys(): if "z" in map_player_dict.keys():
saved_player_z = float(map_player_dict["z"]) saved_player_z = float(map_player_dict["z"])
#if (map_player_dict is None) or not is_same_fvec3( map_player_position_tuple, player_position_tuple): #if (map_player_dict is None) or not is_same_fvec3( map_player_position_tuple, player_position_tuple):
if (map_player_dict is None) or (saved_player_x is None) or (saved_player_z is None) or (int(saved_player_x)!=int(player_x)) or (int(saved_player_z)!=int(player_z)): if (map_player_dict is None) or (saved_player_x is None) or (saved_player_z is None) or (int(saved_player_x)!=int(player_x)) or (int(saved_player_y)!=int(player_y)) or (int(saved_player_z)!=int(player_z)):
# don't check y since y is elevation in minetest, don't use float since subblock position doesn't matter to map # don't check y since y is elevation in minetest, don't use float since subblock position doesn't matter to map
if map_player_dict is not None and saved_player_x is not None and saved_player_z is not None: if map_player_dict is not None and saved_player_x is not None and saved_player_y is not None and saved_player_z is not None:
#print("PLAYER MOVED: "+str(player_name)+" moved from "+str(map_player_position_tuple)+" to "+str(player_position_tuple)) #print("PLAYER MOVED: "+str(player_name)+" moved from "+str(map_player_position_tuple)+" to "+str(player_position_tuple))
if self.is_verbose:
print("PLAYER MOVED: "+str(player_name)+" moved from "+str(saved_player_x)+","+str(saved_player_y)+","+str(saved_player_z)+" to "+str(player_x)+","+str(player_y)+","+str(player_z)) print("PLAYER MOVED: "+str(player_name)+" moved from "+str(saved_player_x)+","+str(saved_player_y)+","+str(saved_player_z)+" to "+str(player_x)+","+str(player_y)+","+str(player_z))
players_moved_count += 1
else: else:
if self.is_verbose:
print("SAVING YAML for player '"+str(player_name)+"'") print("SAVING YAML for player '"+str(player_name)+"'")
players_saved_count += 1
outs = open(player_dest_path, 'w') outs = open(player_dest_path, 'w')
if player_name is not None: if player_name is not None:
outs.write("name:"+player_name+"\n") # python automatically uses correct newline for your os when you put "\n" outs.write("name:"+player_name+"\n") # python automatically uses correct newline for your os when you put "\n"
@ -625,9 +692,14 @@ class MTChunks:
outs.close() outs.close()
player_written_count += 1 player_written_count += 1
else: else:
if self.is_verbose:
print("DIDN'T MOVE: "+str(player_name)) print("DIDN'T MOVE: "+str(player_name))
players_didntmove_count += 1
player_count += 1 player_count += 1
if not self.is_verbose:
print("PLAYERS:")
print(" saved: "+str(player_written_count)+" (moved:"+str(players_moved_count)+"; new:"+str(players_saved_count)+")")
print(" didn't move: "+str(player_name))
def is_player_at_luid(self, chunk_luid): def is_player_at_luid(self, chunk_luid):
result = False result = False
@ -643,7 +715,7 @@ class MTChunks:
def check_map(self): def check_map(self):
if os.path.isfile(self.mtmn_path) and os.path.isfile(self.colors_path): if os.path.isfile(self.mtmn_path) and os.path.isfile(self.colors_path):
rendered_count = 0
self.chunkymap_data_path=os.path.join(self.website_root,"chunkymapdata") self.chunkymap_data_path=os.path.join(self.website_root,"chunkymapdata")
yaml_name = "generated.yml" yaml_name = "generated.yml"
world_yaml_path = os.path.join(self.chunkymap_data_path, yaml_name) world_yaml_path = os.path.join(self.chunkymap_data_path, yaml_name)
@ -657,12 +729,13 @@ class MTChunks:
self.deny_http_access(self.chunkymap_data_path) self.deny_http_access(self.chunkymap_data_path)
mapvars = get_dict_from_conf_file(world_yaml_path,":") mapvars = get_dict_from_conf_file(world_yaml_path,":")
#is_testonly == (os_name=="windows") #is_testonly == (self.os_name=="windows")
if mapvars is not None and set(['world_name']).issubset(mapvars): if mapvars is not None and set(['world_name']).issubset(mapvars):
#if self.is_verbose:
# print (" (FOUND self.world_name)") # print (" (FOUND self.world_name)")
if mapvars["world_name"] != self.world_name: if mapvars["world_name"] != self.world_name:
print ("REMOVING data since from different world (map '"+str(mapvars["world_name"])+"' is not '"+str(self.world_name)+"')...") print ("Removing ALL map data since from WORLD NAME is different (map '"+str(mapvars["world_name"])+"' is not '"+str(self.world_name)+"')...")
for dirname, dirnames, filenames in os.walk(self.chunkymap_data_path): for dirname, dirnames, filenames in os.walk(self.chunkymap_data_path):
#index = 0 #index = 0
#for j in range(0,len(filenames)): #for j in range(0,len(filenames)):
@ -673,6 +746,7 @@ class MTChunks:
for filename in filenames: for filename in filenames:
if filename[0] != ".": if filename[0] != ".":
file_fullname = os.path.join(self.chunkymap_data_path,filename) file_fullname = os.path.join(self.chunkymap_data_path,filename)
if self.is_verbose:
print (" EXAMINING "+filename) print (" EXAMINING "+filename)
badstart_string = "chunk" badstart_string = "chunk"
if (len(filename) >= len(badstart_string)) and (filename[:len(badstart_string)]==badstart_string): if (len(filename) >= len(badstart_string)) and (filename[:len(badstart_string)]==badstart_string):
@ -683,11 +757,13 @@ class MTChunks:
#for j in range(0,len(filenames)): #for j in range(0,len(filenames)):
# i = len(filenames) - 0 - 1 # i = len(filenames) - 0 - 1
# if filenames[i][0] == ".": # if filenames[i][0] == ".":
# if self.is_verbose:
# print (" SKIPPING "+filenames[i]) # print (" SKIPPING "+filenames[i])
# filenames.remove_at(i) # filenames.remove_at(i)
for filename in filenames: for filename in filenames:
if filename[0] != ".": if filename[0] != ".":
file_fullname = os.path.join(self.chunkymap_data_path,filename) file_fullname = os.path.join(self.chunkymap_data_path,filename)
if self.is_verbose:
print (" EXAMINING "+filename) print (" EXAMINING "+filename)
badend_string = ".yml" badend_string = ".yml"
if (len(filename) >= len(badend_string)) and (filename[len(filename)-len(badend_string):]==badend_string): if (len(filename) >= len(badend_string)) and (filename[len(filename)-len(badend_string):]==badend_string):
@ -705,7 +781,7 @@ class MTChunks:
#if str(self.world_name) != str(mapvars["world_name"]): #if str(self.world_name) != str(mapvars["world_name"]):
# is_different_world = True # is_different_world = True
# print("FULL RENDER since chosen world name '"+self.world_name+"' does not match previously rendered world name '"+mapvars["world_name"]+"'") # print("FULL RENDER since chosen world name '"+self.world_name+"' does not match previously rendered world name '"+mapvars["world_name"]+"'")
print("PROCESSING MAP DATA")
while outline_generates_count > 0: while outline_generates_count > 0:
outline_generates_count = 0 outline_generates_count = 0
for z in range (self.chunkz_min,self.chunkz_max+1): for z in range (self.chunkz_min,self.chunkz_max+1):
@ -730,19 +806,33 @@ class MTChunks:
if self.is_chunk_yaml_marked(chunk_luid): if self.is_chunk_yaml_marked(chunk_luid):
if self.is_chunk_yaml_marked_empty(chunk_luid): if self.is_chunk_yaml_marked_empty(chunk_luid):
is_render_needed = True is_render_needed = True
if self.is_verbose:
print (chunk_luid+": RENDERING nonfresh previously marked empty (player in it)") print (chunk_luid+": RENDERING nonfresh previously marked empty (player in it)")
else: else:
sys.stdout.write('.')
else:
if self.is_verbose:
print (chunk_luid+": SKIPPING nonfresh previously marked (player in it)") print (chunk_luid+": SKIPPING nonfresh previously marked (player in it)")
#else:
#sys.stdout.write('.')
else: else:
is_render_needed = True is_render_needed = True
if self.is_verbose:
print (chunk_luid+": RENDERING nonfresh unmarked (player in it)") print (chunk_luid+": RENDERING nonfresh unmarked (player in it)")
else:
sys.stdout.write('.')
else: else:
if (not self.is_chunk_yaml_marked(chunk_luid)): if (not self.is_chunk_yaml_marked(chunk_luid)):
is_render_needed = True is_render_needed = True
if self.is_verbose:
print (chunk_luid+": RENDERING nonfresh unmarked (simple check since has no player)") print (chunk_luid+": RENDERING nonfresh unmarked (simple check since has no player)")
else: else:
sys.stdout.write('.')
else:
if self.is_verbose:
print (chunk_luid+": SKIPPING nonfresh previously marked (simple check since has no player)") print (chunk_luid+": SKIPPING nonfresh previously marked (simple check since has no player)")
else: else:
if self.is_verbose:
print (chunk_luid+": SKIPPING fresh chunk") print (chunk_luid+": SKIPPING fresh chunk")
#if (not self.is_chunk_yaml_marked(chunk_luid)): #if (not self.is_chunk_yaml_marked(chunk_luid)):
#is_render_needed = True #is_render_needed = True
@ -750,13 +840,15 @@ class MTChunks:
# This should never happen since keeping the output of minetestmapper-numpy.py (after analyzing that output) is deprecated: # This should never happen since keeping the output of minetestmapper-numpy.py (after analyzing that output) is deprecated:
#if self.is_genresult_marked(chunk_luid) and not self.is_chunk_yaml_present(chunk_luid): #if self.is_genresult_marked(chunk_luid) and not self.is_chunk_yaml_present(chunk_luid):
# tmp_chunk = MTChunk() # tmp_chunk = MTChunk()
# self.set_from_genresult(tmp_chunk,chunk_luid) # genresult_path = self.get_chunk_genresult_tmp_path(chunk_luid)
# tmp_chunk.set_from_genresult(genresult_path)
# chunk_yaml_path = self.get_chunk_yaml_path(chunk_luid) # chunk_yaml_path = self.get_chunk_yaml_path(chunk_luid)
# tmp_chunk.save_yaml(chunk_yaml_path) # tmp_chunk.save_yaml(chunk_yaml_path)
# print("(saved yaml to '"+chunk_yaml_path+"')") # print("(saved yaml to '"+chunk_yaml_path+"')")
if is_render_needed: if is_render_needed:
rendered_count += 1
if (self.render_chunk(x,z)): if (self.render_chunk(x,z)):
total_generated_count += 1 total_generated_count += 1
outline_generates_count += 1 outline_generates_count += 1
@ -765,11 +857,13 @@ class MTChunks:
total_generated_count += 1 total_generated_count += 1
outline_generates_count += 1 outline_generates_count += 1
tmp_png_path = self.get_chunk_image_path(chunk_luid) tmp_png_path = self.get_chunk_image_path(chunk_luid)
if self.is_verbose:
print(chunk_luid+": Skipping existing map tile file " + tmp_png_path + " (delete it to re-render)") print(chunk_luid+": Skipping existing map tile file " + tmp_png_path + " (delete it to re-render)")
#elif is_empty_chunk: #elif is_empty_chunk:
#print("Skipping empty chunk " + chunk_luid) #print("Skipping empty chunk " + chunk_luid)
#else: #else:
#print(chunk_luid+": Not rendered on dest.") #print(chunk_luid+": Not rendered on dest.")
if self.is_verbose:
print ("") # blank line before next z so output is more readable print ("") # blank line before next z so output is more readable
self.chunkx_min -= 1 self.chunkx_min -= 1
self.chunkz_min -= 1 self.chunkz_min -= 1
@ -820,9 +914,96 @@ class MTChunks:
outs.write("total_generated_count:"+str(total_generated_count) + "\n") outs.write("total_generated_count:"+str(total_generated_count) + "\n")
outs.close() outs.close()
else: else:
if self.is_verbose:
print (" (Not saving '"+world_yaml_path+"' since same value of each current variable is already in file as loaded)") print (" (Not saving '"+world_yaml_path+"' since same value of each current variable is already in file as loaded)")
if not self.is_verbose:
print(" rendered: "+str(rendered_count)+" (only checks for new chunks)")
else:
print ("MAP ERROR: failed since this folder must contain colors.txt and minetestmapper-numpy.py")
def read_then_remove_signals(self):
signal_path = self.get_signal_path()
if os.path.isfile(signal_path):
signals = get_dict_from_conf_file(signal_path)
if signals is not None:
for this_key in signals.keys:
if this_key=="loop_enable":
if not signals[this_key]:
self.loop_enable = False
else:
print("WARNING: Got signal to change loop_enable to True, so doing nothing")
elif this_key=="refresh_players_enable":
if type(signals[this_key]) is bool:
self.refresh_players_enable = signals[this_key]
else:
print("ERROR: expected bool for "+this_key)
elif this_key=="refresh_map_seconds":
if (type(signals[this_key]) is float) or (type(signals[this_key]) is int):
if float(signals[this_key])>=1.0:
self.refresh_map_seconds = float(signals[this_key])
else:
print("ERROR: expected >=1 seconds for refresh_map_seconds (int or float)")
else:
print("ERROR: expected int for "+this_key)
elif this_key=="refresh_players_seconds":
if (type(signals[this_key]) is float) or (type(signals[this_key]) is int):
if float(signals[this_key])>=1.0:
self.refresh_players_seconds = float(signals[this_key])
else: else:
print ("failed since this folder must contain colors.txt and minetestmapper-numpy.py") print("ERROR: expected >=1 seconds for refresh_players_seconds (int or float)")
else:
print("ERROR: expected int for "+this_key)
elif this_key=="refresh_map_enable":
if type(signals[this_key]) is bool:
self.refresh_map_enable = signals[this_key]
else:
print("ERROR: expected bool for "+this_key)
else:
print("ERROR: unknown signal '"+this_key+"'")
else:
print("WARNING: blank '"+signal_path+"'")
try:
os.remove()
except:
print("FATAL ERROR: "+__file__+" must have permission to remove '"+signal_path+"' so exiting to avoid inability to avoid repeating commands at next launch.")
self.loop_enable = False
def run_loop(self):
#self.last_run_second = best_timer()
self.loop_enable = True
self.is_verbose = False
while self.loop_enable:
before_second = best_timer()
run_wait_seconds = self.refresh_map_seconds
if self.refresh_players_seconds < run_wait_seconds:
run_wait_seconds = self.refresh_players_seconds
print("")
self.read_then_remove_signals()
if self.loop_enable:
if self.refresh_players_enable:
if self.last_players_refresh_second is None or (best_timer()-self.last_players_refresh_second > self.refresh_players_seconds ):
last_players_refresh_second = best_timer()
self.check_players()
else:
print("waiting before doing player update")
else:
print("player update is not enabled")
if self.refresh_map_enable:
if self.last_map_refresh_second is None or (best_timer()-self.last_map_refresh_second > self.refresh_map_seconds):
last_map_refresh_second = best_timer()
self.check_map()
else:
print("waiting before doing map update")
else:
print("map update is not enabled")
else:
self.is_verbose = True
run_wait_seconds -= (best_timer()-before_second)
if (int(float(run_wait_seconds)+.5)>0.0):
time.sleep(run_wait_seconds)
def run(self): def run(self):
if self.refresh_players_enable: if self.refresh_players_enable:
@ -831,17 +1012,17 @@ class MTChunks:
self.check_map() self.check_map()
if __name__ == '__main__': if __name__ == '__main__':
mtchunks = MTChunks()
signal_path = mtchunks.get_signal_path()
stop_line = "loop_enable:False"
parser = argparse.ArgumentParser(description='A mapper for minetest') parser = argparse.ArgumentParser(description='A mapper for minetest')
parser.add_argument('--skip-map', type = bool, metavar = ('skip_map'), default = False, help = 'draw map tiles and save YAML files for chunkymap.php to use') parser.add_argument('--skip-map', type = bool, metavar = ('skip_map'), default = False, help = 'draw map tiles and save YAML files for chunkymap.php to use')
#parser.add_argument('--skip-map',action='store_const', const = True, default = False, help = 'Do not draw map tiles (which would save PNG and YAML files for chunkymap.php to use)')
parser.add_argument('--skip-players', type = bool, metavar = ('skip_players'), default = False, help = 'update player YAML files for chunkymap.php to use') parser.add_argument('--skip-players', type = bool, metavar = ('skip_players'), default = False, help = 'update player YAML files for chunkymap.php to use')
#parser.add_argument('--skip-players',action='store_const', const = True, default = False, help = 'Do not update players (which would save YAML files for chunkymap.php to use)') parser.add_argument('--loop', type = bool, metavar = ('loop'), default = False, help = 'keep running until "'+signal_path+'" contains the line '+stop_line)
#parser = argparse.ArgumentParser(description='Process some integers.')
args = parser.parse_args() args = parser.parse_args()
mtchunks = MTChunks()
if not args.skip_players: if not args.skip_players:
if not args.skip_map: if not args.skip_map:
mtchunks.refresh_players_enable = False
print("Drawing players and map") print("Drawing players and map")
else: else:
mtchunks.refresh_map_enable = False mtchunks.refresh_map_enable = False
@ -851,10 +1032,12 @@ if __name__ == '__main__':
mtchunks.refresh_players_enable = False mtchunks.refresh_players_enable = False
print("Drawing map only") print("Drawing map only")
else: else:
mtchunks.refresh_players_enable = False
mtchunks.refresh_map_enable = False mtchunks.refresh_map_enable = False
print("Nothing to do since "+str(args)) print("Nothing to do since "+str(args))
if mtchunks.refresh_players_enable or mtchunks.refresh_map_enable:
#input("press enter to exit...") if args.loop:
print("To stop chunkymap-regen loop, save a line '"+stop_line+"' to '"+signal_path+"'")
mtchunks.run_loop()
else:
mtchunks.run() mtchunks.run()

11
chunkymap-signals example.txt

@ -0,0 +1,11 @@
#to stop program:
loop_enable:False
#to stop checking for player movements (players will timeout and the php will stop showing the players due to old file modified times)
refresh_players_enable:False
#to stop checking for map updates (NOTE: the map update function is only able to detect new chunks, and only checks edge chunks if player is present in one)
refresh_map_enable:False
#other options:
refresh_players_seconds:60
refresh_map_seconds:300

2
web/chunkymap.php

@ -552,7 +552,7 @@ function echo_chunkymap_table() {
$text_style="color:white;"; $text_style="color:white;";
if ($is_expired==false) { if ($is_expired==false) {
if ($is_idle==true) { if ($is_idle==true) {
$img_border_style="border: 1px solid gray;"; $img_border_style="border: 1px solid rgba(128,128,128,.5);";
$img_style.="opacity: 0.4; filter: alpha(opacity=40);"; //filter is for IE8 and below $img_style.="opacity: 0.4; filter: alpha(opacity=40);"; //filter is for IE8 and below
$text_style="color:white; opacity: 0.4; filter: alpha(opacity=40);"; //filter is for IE8 and below $text_style="color:white; opacity: 0.4; filter: alpha(opacity=40);"; //filter is for IE8 and below
} }

3
web/example.php

@ -1,5 +1,8 @@
<html> <html>
<head>
<title>Chunkymap Example Page</title> <title>Chunkymap Example Page</title>
<meta http-equiv="refresh" content="30">
</head>
<body style="font-family:calibri,sans"> <body style="font-family:calibri,sans">
<?php <?php
ini_set('display_errors', 1); ini_set('display_errors', 1);

14
web/generated_example.yml → web/example_chunkymapdataDir_generatedFile.yml

@ -1,13 +1,13 @@
#to generate this, run chunkymap-regen.py with permission to create and write to /var/www/html/minetest/chunkymapdata (or use shell script) #to generate this, run chunkymap-regen.py with permission to create and write to /var/www/html/minetest/chunkymapdata (or use shell script)
world_name:FCAGameAWorld world_name:FCAGameAWorld
chunk_size:80 chunk_size:16
pixelspernode:1 pixelspernode:1
chunkx_min:-22 chunkx_min:-16
chunkz_min:-22 chunkz_min:-16
chunkx_max:22 chunkx_max:16
chunkz_max:22 chunkz_max:16
maxheight:50 maxheight:32
minheight:-25 minheight:-16
world_path:/home/owner/.minetest/worlds/FCAGameAWorld world_path:/home/owner/.minetest/worlds/FCAGameAWorld
chunkymap_data_path:/var/www/html/minetest/chunkymapdata chunkymap_data_path:/var/www/html/minetest/chunkymapdata
total_generated_count:288 total_generated_count:288
Loading…
Cancel
Save