Browse Source

player index is now generated

master
poikilos 9 years ago
committed by Jacob Gustafson
parent
commit
81c98cb5d3
  1. 4
      README.md
  2. 152
      chunkymap-regen.py
  3. 11
      minetestinfo.py
  4. 16
      web/chunkymap.php
  5. 4
      web/viewchunkymap.php

4
README.md

@ -47,6 +47,10 @@ 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])
## Developer Notes:
* Player username privacy: check_players in chunkymap-regen.py intentionally makes up an index and uses that as the filename on the destination, so that ajax can update players without knowing either their id (filename of minetest player file) or display name (listed in the player file)
(this way, only usernames can be known if chunkymap.php allows that, or the person is logged in to the server)
Because of the feature, chunkymap-regen.py must prevent duplicates based on value of id in the resulting yml files (minetest player filename as id).
This should be hard to corrupt since id is used as the indexer for the players dict (however, extra files with no matching entry in the dict will still need to be deleted if they exist)
* games_path and mods_path should not be stored in minetestmeta.yml, since otherwise the values may deviate from the parent directories.
To avoid this problem, instead derive the paths from the parent paths using your favorite language such as in the following examples:
games_path = os.path.join(minetestinfo.get_var("shared_minetest_path"), "games")

152
chunkymap-regen.py

@ -207,6 +207,7 @@ class MTChunks:
colors_path = None
python_exe_path = None
chunks = None
players = None # dict with id as subscript, each containing player metadata dict
decachunks = None
rendered_this_session_count = None
#force_rerender_decachunks_enable = None
@ -1132,8 +1133,60 @@ class MTChunks:
self.chunks[chunk_luid].save_yaml(chunk_yaml_path)
print(min_indent+"(saved yaml to '"+chunk_yaml_path+"')")
def get_new_player_index(self):
result = None
if self.players is not None:
result = 0
for this_key in self.players.keys():
this_player = self.players[this_key]
if "index" in this_player:
if this_player["index"]==result:
result = this_player["index"] + 1
return result
def save_player(self, playerid):
if self.players is not None:
if playerid is not None:
if playerid in self.players:
if not os.path.isdir(self.chunkymap_players_path):
os.makedirs(self.chunkymap_players_path)
self.deny_http_access(self.chunkymap_players_path)
this_player = self.players[playerid]
if "index" in this_player:
player_path = os.path.join(self.chunkymap_players_path, this_player["index"])
save_conf_from_dict(player_path, this_player, ":")
else:
print("ERROR: cannot save player since missing 'index' ('index' is used for filename on map)")
else:
print("ERROR: tried to save nonexistant player id '"+str(playerid)+"'")
else:
print("ERROR: save_player(None) was attempted.")
else:
print("ERROR: Tried save_player but the players dict is not ready (self.players is None)")
def check_players(self):
print("PROCESSING PLAYERS")
if self.players is None:
self.players = {}
if os.path.isdir(self.chunkymap_players_path):
folder_path = self.chunkymap_players_path
for sub_name in os.listdir(folder_path):
sub_path = os.path.join(folder_path,sub_name)
if os.path.isfile(sub_path):
if (sub_name[:1]!="."):
if len(sub_name)>4 and sub_name[-4:]==".yml":
player_dict = get_dict_from_conf_file(sub_path,":")
if player_dict is not None:
if "id" in player_dict:
if (player_dict["id"] is not None) and (len(player_dict["id"])>0):
self.players[player_dict["id"]] = player_dict
else:
print("ERROR: no 'id' in chunkymap player entry '"+sub_path+"'")
else:
print("ERROR: could not read any yaml values from '"+sub_path+"'")
else:
os.makedirs(self.chunkymap_players_path)
self.deny_http_access(self.chunkymap_players_path)
players_path = os.path.join(minetestinfo.get_var("primary_world_path"), "players")
player_count = 0
@ -1169,7 +1222,28 @@ class MTChunks:
is_enough_data = True
break
ins.close()
player_dest_path = os.path.join(self.chunkymap_players_path,file_name+".yml")
player_index = None
this_player = None
is_changed = False
if file_name in self.players:
this_player = self.players[file_name]
if "index" in this_player:
player_index = self.players[file_name]["index"]
else:
player_index = self.get_new_player_index()
self.players[file_name]["index"] = player_index
is_changed = True
else:
this_player = {}
player_index = self.get_new_player_index()
this_player["index"] = player_index
self.players[file_name] = this_player
is_changed = True
player_dest_path = None
if player_index is not None:
player_dest_path = os.path.join(self.chunkymap_players_path, player_index+".yml")
else:
print("ERROR: player_index is None for '"+file_name+"' (this should never happen)")
player_x = None
player_y = None
player_z = None
@ -1196,24 +1270,44 @@ class MTChunks:
#if is_enough_data:
#if player_name!="singleplayer":
map_player_dict = get_dict_from_conf_file(player_dest_path,":")
#this_player = get_dict_from_conf_file(player_dest_path,":")
#map_player_position_tuple = None
saved_player_x = None
saved_player_y = None
saved_player_y = None
if map_player_dict is not None:
#map_player_position_tuple = saved_player_x, saved_player_y, saved_player_z
if "x" in map_player_dict.keys():
saved_player_x = float(map_player_dict["x"])
if "y" in map_player_dict.keys():
saved_player_y = float(map_player_dict["y"])
if "z" in map_player_dict.keys():
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 (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)):
#map_player_position_tuple = saved_player_x, saved_player_y, saved_player_z
is_moved = False
if "x" in this_player.keys():
saved_player_x = float(this_player["x"])
if int(saved_player_x) != int(player_x):
is_moved = True
else:
this_player["x"] = player_x
is_moved = True
if "y" in this_player.keys():
saved_player_y = float(this_player["y"])
if int(saved_player_y) != int(player_y):
is_moved = True
else:
this_player["y"] = player_y
is_moved = True
if "z" in this_player.keys():
saved_player_z = float(this_player["z"])
if int(saved_player_z) != int(player_z):
is_moved = True
else:
this_player["z"] = player_z
is_moved = True
if is_moved:
is_changed = True
#if (this_player is None) or not is_same_fvec3( map_player_position_tuple, player_position_tuple):
#if (this_player 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)):
if is_changed:
# 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_y is not None and saved_player_z is not None:
#if this_player is not None and saved_player_x is not None and saved_player_y is not None and saved_player_z is not None:
if is_moved:
#print("PLAYER MOVED: "+str(player_name)+" moved from "+str(map_player_position_tuple)+" to "+str(player_position_tuple))
if self.verbose_enable:
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))
@ -1222,19 +1316,21 @@ class MTChunks:
if self.verbose_enable:
print("SAVING YAML for player '"+str(player_name)+"'")
players_saved_count += 1
outs = open(player_dest_path, 'w')
if player_name is not None:
outs.write("name:"+player_name+"\n") # python automatically uses correct newline for your os when you put "\n"
#if player_position is not None:
# outs.write("position:"+player_position+"\n")
if player_x is not None:
outs.write("x:"+str(player_x)+"\n")
if player_y is not None:
outs.write("y:"+str(player_y)+"\n")
if player_z is not None:
outs.write("z:"+str(player_z)+"\n")
outs.write("is_enough_data:"+str(is_enough_data))
outs.close()
save_conf_from_dict(player_dest_path, this_player, ":", save_nulls_enable=False)
#outs = open(player_dest_path, 'w')
#outs.write("id:"+file_name)
#if player_name is not None:
# outs.write("name:"+player_name+"\n") # python automatically uses correct newline for your os when you put "\n"
##if player_position is not None:
## outs.write("position:"+player_position+"\n")
#if player_x is not None:
# outs.write("x:"+str(player_x)+"\n")
#if player_y is not None:
# outs.write("y:"+str(player_y)+"\n")
#if player_z is not None:
# outs.write("z:"+str(player_z)+"\n")
#outs.write("is_enough_data:"+str(is_enough_data))
#outs.close()
player_written_count += 1
else:
#if self.verbose_enable:
@ -1244,7 +1340,7 @@ class MTChunks:
#if not self.verbose_enable:
print("PLAYERS:")
print(" saved: "+str(player_written_count)+" (moved:"+str(players_moved_count)+"; new:"+str(players_saved_count)+")")
print(" didn't move: "+str(players_didntmove_count))
print(" didn't change: "+str(players_didntmove_count))
def is_chunk_traversed_by_player(self, chunk_luid):
result = False

11
minetestinfo.py

@ -33,6 +33,8 @@ prepackaged_game_mod_list = list()
prepackaged_gameid = "minetest_game"
new_mod_list = list()
user_excluded_mod_count = 0
minetestinfo = ConfigManager(os.path.join(os.path.dirname(os.path.abspath(__file__)), "minetestmeta.yml"), ":")
os_name="linux"
@ -305,7 +307,7 @@ def load_world_and_mod_data():
print("")
if len(prepackaged_game_mod_list)<1:
prepackaged_game_mod_list = get_modified_mod_list_from_game_path(prepackaged_game_mod_list, prepackaged_game_path)
print(prepackaged_gameid+" has the following mod(s): "+','.join(prepackaged_game_mod_list))
print(prepackaged_gameid+" has "+str(len(prepackaged_game_mod_list))+" mod(s): "+','.join(prepackaged_game_mod_list))
if minetestinfo.contains("game_path") and os.path.isdir(minetestinfo.get_var("game_path")):
loaded_mod_list = get_modified_mod_list_from_game_path(loaded_mod_list, minetestinfo.get_var("game_path"))
@ -318,11 +320,15 @@ def load_world_and_mod_data():
if len(new_mod_list)>0:
new_mod_list_msg = ": "+','.join(new_mod_list)
gameid = os.path.basename(minetestinfo.get_var("game_path"))
print("")
print(gameid+" has "+str(len(new_mod_list))+" mod(s) beyond "+prepackaged_gameid+new_mod_list_msg+")")
if (user_excluded_mod_count>0):
print(" (not including "+str(user_excluded_mod_count)+" mods(s) excluded by world.mt)")
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.")
def get_modified_mod_list_from_game_path(mod_list, game_path):
global user_excluded_mod_count
if mod_list is None:
mod_list = list()
if game_path is not None and os.path.isdir(game_path):
@ -330,6 +336,7 @@ def get_modified_mod_list_from_game_path(mod_list, game_path):
folder_path = mods_path
missing_load_mod_setting_count = 0
check_world_mt()
user_excluded_mod_count = 0
for sub_name in os.listdir(folder_path):
sub_path = os.path.join(folder_path,sub_name)
if os.path.isdir(sub_path):
@ -338,6 +345,8 @@ def get_modified_mod_list_from_game_path(mod_list, game_path):
load_mod_variable_name = "load_mod_"+sub_name
if (world_mt_mapvars is not None) and (load_mod_variable_name in world_mt_mapvars):
load_this_mod = get_world_var(load_mod_variable_name)
if load_this_mod != True:
user_excluded_mod_count += 1
if load_this_mod == True:
if sub_name not in mod_list:
mod_list.append(sub_name)

16
web/chunkymap.php

@ -252,8 +252,8 @@ function get_javascript_bool_value($this_bool) {
}
//chunk_mode_enable: shows chunk png images instead of decachunk jpg images (slower)
//debug_mode_enable: draws colored rectangles based on yml files instead of drawing images
function echo_chunkymap_canvas($chunk_mode_enable, $debug_mode_enable, $html4_mode_enable) {
//visual_debug_enable: draws colored rectangles based on yml files instead of drawing images
function echo_chunkymap_canvas($chunk_mode_enable, $visual_debug_enable, $html4_mode_enable) {
global $chunkymap_view_x;
global $chunkymap_view_z;
global $chunkymap_view_zoom;
@ -346,7 +346,7 @@ function echo_chunkymap_canvas($chunk_mode_enable, $debug_mode_enable, $html4_mo
var chunkymap_view_min_zoom='.$chunkymap_view_min_zoom.';
var chunkymap_zoom_delta='.$chunkymap_change_zoom_multiplier.';
var chunk_mode_enable='.get_javascript_bool_value($chunk_mode_enable).';
var debug_mode_enable='.get_javascript_bool_value($debug_mode_enable).';
var visual_debug_enable='.get_javascript_bool_value($visual_debug_enable).';
var chunks_per_tile_x_count='.$chunks_per_tile_x_count.';
var chunks_per_tile_z_count='.$chunks_per_tile_z_count.';
var tile_w='.$tile_w.';
@ -529,8 +529,6 @@ function echo_chunkymap_canvas($chunk_mode_enable, $debug_mode_enable, $html4_mo
//size_1pt_pixel_count = ctx.canvas.height/600.0;
var bw_index = 0;
for (i=0; i<bawidgets.length; i++) {
this_widget = bawidgets[i];
this_img = this_widget["image"]
@ -572,11 +570,11 @@ function echo_chunkymap_canvas($chunk_mode_enable, $debug_mode_enable, $html4_mo
pen_y += size_1em_pixel_count + padding_h;
//COMPASS ROSE (no click):
var compass_rose_img = document.getElementById("compass-rose");
var compass_rose_img = document.getElementById("compass_rose");
var this_h_ratio = compass_rose_img.height/compass_rose_img.width;
tmp_w = compass_rose_w;
tmp_h = tmp_w*this_h_ratio;
bw_index = add_bawidget(pen_x-padding_w, pen_y, tmp_w, tmp_h, null, "compass-rose");
bw_index = add_bawidget(pen_x-padding_w, pen_y, tmp_w, tmp_h, null, "compass_rose");
last_bawidget["image"] = compass_rose_img;
compass_rose_img.style.visibility="hidden";
pen_y += last_bawidget.height+padding_h;
@ -630,13 +628,13 @@ function echo_chunkymap_canvas($chunk_mode_enable, $debug_mode_enable, $html4_mo
else {
$td_tile_placeholder_content = $td_decachunk_placeholder_content
}
echo '<img id="compass-rose" src="chunkymapdata/images/compass_rose.png"/>';
echo '<img id="compass_rose" src="chunkymapdata/images/compass_rose.png"/>';
echo '<img id="zoom_in" src="chunkymapdata/images/zoom_in.png"/>';
echo '<img id="zoom_in_disabled" src="chunkymapdata/images/zoom_in_disabled.png"/>';
echo '<img id="zoom_out" src="chunkymapdata/images/zoom_out.png"/>';
echo '<img id="zoom_out_disabled" src="chunkymapdata/images/zoom_out_disabled.png"/>';
$this_tiley_z=$max_tiley_z; //start at max since screen is inverted cartesian
if ($debug_mode_enable!==true) {
if ($visual_debug_enable!==true) {
//this table loads the images then is hidden when javascript runs successfully, but it is also a map though not very functional
echo '<table id="chunkymap_table" cellspacing="0" cellpadding="0" style="width:100%">'."\r\n";
echo ' <tr>'."\r\n";

4
web/viewchunkymap.php

@ -27,9 +27,9 @@ if (is_file('chunkymap.php')) {
set_chunkymap_view($chunkymap_view_x,$chunkymap_view_z,$chunkymap_view_zoom);
//echo "<table><tr><td style=\"text-align:left\">";
$chunk_mode_enable=true; //(this should normally be false) if true, uses 16x16 png files instead of the 160x160 decachunks; it is slower but may have more of the map during times when new chunks are explored but before the render queue is done and the decachunk images are created from the chunk images.);
$debug_mode_enable=false; //if true, this renders colors based on yml files instead of drawing images (and does not echo images at all)
$visual_debug_enable=false; //if true, this renders colors based on yml files instead of drawing images (and does not echo images at all)
$html4_mode_enable=false; //if true, does not echo canvas nor client-side scripting
echo_chunkymap_canvas($chunk_mode_enable,$debug_mode_enable,$html4_mode_enable);
echo_chunkymap_canvas($chunk_mode_enable,$visual_debug_enable,$html4_mode_enable);
//echo_chunkymap_as_chunk_table(false);
//echo_decachunk_table();
//echo "</td></tr></table>";

Loading…
Cancel
Save