1042 lines
42 KiB
Python
1042 lines
42 KiB
Python
from bot import loaded_modules_dict
|
|
from os import path, pardir
|
|
import json
|
|
|
|
module_name = path.basename(path.normpath(path.join(path.abspath(__file__), pardir, pardir)))
|
|
widget_name = path.basename(path.abspath(__file__))[:-3]
|
|
|
|
# View Registry - defines all available views and their navigation labels
|
|
# This eliminates the need for separate template files for each button
|
|
VIEW_REGISTRY = {
|
|
'frontend': {
|
|
'label_active': 'back',
|
|
'label_inactive': 'main',
|
|
'action': 'show_frontend',
|
|
'include_in_menu': False
|
|
},
|
|
'options': {
|
|
'label_active': 'back',
|
|
'label_inactive': 'options',
|
|
'action': 'show_options',
|
|
'include_in_menu': True
|
|
},
|
|
'map': {
|
|
'label_active': 'hide map',
|
|
'label_inactive': 'show map',
|
|
'action': 'show_map',
|
|
'include_in_menu': True
|
|
},
|
|
'create_new': {
|
|
'label_active': 'back',
|
|
'label_inactive': 'create new',
|
|
'action': 'show_create_new',
|
|
'include_in_menu': True
|
|
},
|
|
'special_locations': {
|
|
'label_active': 'back',
|
|
'label_inactive': 'special',
|
|
'action': 'show_special_locations',
|
|
'include_in_menu': True
|
|
}
|
|
}
|
|
|
|
|
|
def get_table_row_css_class(location_dict):
|
|
is_enabled = location_dict.get("is_enabled", False)
|
|
|
|
if is_enabled:
|
|
css_class = "is_enabled"
|
|
else:
|
|
css_class = ""
|
|
|
|
return css_class
|
|
|
|
|
|
def select_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get('dispatchers_steamid', None)
|
|
|
|
current_view = module.get_current_view(dispatchers_steamid)
|
|
if current_view == "options":
|
|
options_view(module, dispatchers_steamid=dispatchers_steamid, current_view=current_view)
|
|
elif current_view == "map":
|
|
map_view(module, dispatchers_steamid=dispatchers_steamid, current_view=current_view)
|
|
elif current_view == "special_locations":
|
|
frontend_view(module, dispatchers_steamid=dispatchers_steamid, current_view=current_view)
|
|
elif current_view == "delete-modal":
|
|
frontend_view(module, dispatchers_steamid=dispatchers_steamid)
|
|
delete_modal_view(module, dispatchers_steamid=dispatchers_steamid)
|
|
elif current_view == "create_new":
|
|
edit_view(module, dispatchers_steamid=dispatchers_steamid, current_view=current_view)
|
|
elif current_view == "edit_location_entry":
|
|
location_owner = (
|
|
module.dom.data
|
|
.get(module.get_module_identifier(), {})
|
|
.get("visibility", {})
|
|
.get(dispatchers_steamid, {})
|
|
.get("location_owner", None)
|
|
)
|
|
location_identifier = (
|
|
module.dom.data
|
|
.get(module.get_module_identifier(), {})
|
|
.get("visibility", {})
|
|
.get(dispatchers_steamid, {})
|
|
.get("location_identifier", None)
|
|
)
|
|
location_origin = (
|
|
module.dom.data
|
|
.get(module.get_module_identifier(), {})
|
|
.get("visibility", {})
|
|
.get(dispatchers_steamid, {})
|
|
.get("location_origin", None)
|
|
)
|
|
|
|
edit_view(
|
|
module,
|
|
dispatchers_steamid=dispatchers_steamid,
|
|
location_owner=location_owner,
|
|
location_identifier=location_identifier,
|
|
location_origin=location_origin,
|
|
current_view=current_view
|
|
)
|
|
else:
|
|
frontend_view(module, dispatchers_steamid=dispatchers_steamid)
|
|
|
|
|
|
def delete_modal_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get('dispatchers_steamid', None)
|
|
|
|
all_available_locations = module.dom.data.get(module.get_module_identifier(), {}).get("elements", {})
|
|
all_selected_elements_count = 0
|
|
active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None)
|
|
for map_identifier, location_owner in all_available_locations.items():
|
|
if active_dataset == map_identifier:
|
|
for player_steamid, player_locations in location_owner.items():
|
|
for identifier, location_dict in player_locations.items():
|
|
location_is_selected_by = location_dict.get("selected_by", [])
|
|
if dispatchers_steamid in location_is_selected_by:
|
|
all_selected_elements_count += 1
|
|
|
|
modal_confirm_delete = module.dom_management.get_delete_confirm_modal(
|
|
module,
|
|
count=all_selected_elements_count,
|
|
target_module="module_locations",
|
|
dom_element_id="location_table_modal_action_delete_button",
|
|
dom_action="delete_selected_dom_elements",
|
|
dom_element_root=module.dom_element_root,
|
|
dom_element_select_root=module.dom_element_select_root,
|
|
confirmed="True"
|
|
)
|
|
|
|
data_to_emit = modal_confirm_delete
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="modal_content",
|
|
clients=[dispatchers_steamid],
|
|
target_element={
|
|
"id": "manage_locations_widget_modal",
|
|
"type": "div",
|
|
"selector": "body > main > div"
|
|
}
|
|
)
|
|
|
|
|
|
def frontend_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get("dispatchers_steamid", None)
|
|
current_view = kwargs.get("current_view", None)
|
|
|
|
# Load templates
|
|
template_frontend = module.templates.get_template('manage_locations_widget/view_frontend.html')
|
|
template_view_menu = module.templates.get_template('manage_locations_widget/control_view_menu.html')
|
|
control_player_location_view_template = module.templates.get_template(
|
|
'manage_locations_widget/control_player_location.html'
|
|
)
|
|
control_edit_link = module.templates.get_template('manage_locations_widget/control_edit_link.html')
|
|
control_enabled_link = module.templates.get_template('manage_locations_widget/control_enabled_link.html')
|
|
|
|
template_table_header = module.templates.get_template('manage_locations_widget/table_header.html')
|
|
template_table_rows = module.templates.get_template('manage_locations_widget/table_row.html')
|
|
template_table_footer = module.templates.get_template('manage_locations_widget/table_footer.html')
|
|
|
|
# Build table rows efficiently using list + join (avoids O(n²) with string +=)
|
|
table_rows_list = []
|
|
all_available_locations = module.dom.data.get(module.get_module_identifier(), {}).get("elements", {})
|
|
all_selected_elements_count = 0
|
|
active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None)
|
|
for map_identifier, location_owner in all_available_locations.items():
|
|
if active_dataset == map_identifier:
|
|
for player_steamid, player_locations in location_owner.items():
|
|
player_dict = (
|
|
module.dom.data
|
|
.get("module_players", {})
|
|
.get("elements", {})
|
|
.get(active_dataset, {})
|
|
.get(player_steamid, {})
|
|
)
|
|
for identifier, location_dict in player_locations.items():
|
|
location_has_special_properties = len(location_dict.get("type", [])) >= 1
|
|
if not location_has_special_properties and current_view == "special_locations":
|
|
continue
|
|
|
|
location_is_selected_by = location_dict.get("selected_by", [])
|
|
|
|
location_entry_selected = False
|
|
if dispatchers_steamid in location_is_selected_by:
|
|
location_entry_selected = True
|
|
all_selected_elements_count += 1
|
|
|
|
# Sanitize dataset for HTML ID (replace spaces with underscores, lowercase)
|
|
location_dict_for_template = location_dict.copy()
|
|
location_dict_for_template["dataset"] = module.dom_management.sanitize_for_html_id(location_dict.get("dataset", ""))
|
|
location_dict_for_template["dataset_original"] = location_dict.get("dataset", "")
|
|
|
|
control_select_link = module.dom_management.get_selection_dom_element(
|
|
module,
|
|
target_module="module_locations",
|
|
dom_element_select_root=[identifier, "selected_by"],
|
|
dom_element=location_dict_for_template,
|
|
dom_element_entry_selected=location_entry_selected,
|
|
dom_action_inactive="select_dom_element",
|
|
dom_action_active="deselect_dom_element"
|
|
)
|
|
|
|
table_rows_list.append(module.template_render_hook(
|
|
module,
|
|
template=template_table_rows,
|
|
location=location_dict_for_template,
|
|
player_dict=player_dict,
|
|
control_select_link=control_select_link,
|
|
control_enabled_link=module.template_render_hook(
|
|
module,
|
|
template=control_enabled_link,
|
|
location=location_dict_for_template,
|
|
),
|
|
control_edit_link=module.template_render_hook(
|
|
module,
|
|
template=control_edit_link,
|
|
dispatchers_steamid=dispatchers_steamid,
|
|
location=location_dict_for_template,
|
|
)
|
|
))
|
|
|
|
table_rows = ''.join(table_rows_list)
|
|
|
|
dom_element_delete_button = module.dom_management.get_delete_button_dom_element(
|
|
module,
|
|
count=all_selected_elements_count,
|
|
target_module="module_locations",
|
|
dom_element_root=module.dom_element_root,
|
|
dom_element_select_root=module.dom_element_select_root,
|
|
dom_element_id="manage_locations_control_action_delete_link",
|
|
dom_action="delete_selected_dom_elements"
|
|
)
|
|
|
|
# Get current view and player coordinates
|
|
current_view = module.get_current_view(dispatchers_steamid)
|
|
player_coordinates = module.dom.data.get("module_players", {}).get("players", {}).get(dispatchers_steamid, {}).get(
|
|
"pos", {"x": 0, "y": 0, "z": 0}
|
|
)
|
|
|
|
# Render navigation menu using view registry
|
|
options_toggle = module.template_render_hook(
|
|
module,
|
|
template=template_view_menu,
|
|
views=VIEW_REGISTRY,
|
|
current_view=current_view,
|
|
steamid=dispatchers_steamid,
|
|
control_player_location_view=module.template_render_hook(
|
|
module,
|
|
template=control_player_location_view_template,
|
|
pos_x=player_coordinates["x"],
|
|
pos_y=player_coordinates["y"],
|
|
pos_z=player_coordinates["z"]
|
|
)
|
|
)
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=template_frontend,
|
|
options_toggle=options_toggle,
|
|
table_header=module.template_render_hook(
|
|
module,
|
|
template=template_table_header
|
|
),
|
|
table_rows=table_rows,
|
|
table_footer=module.template_render_hook(
|
|
module,
|
|
template=template_table_footer,
|
|
action_delete_button=dom_element_delete_button
|
|
)
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="widget_content",
|
|
clients=[dispatchers_steamid],
|
|
target_element={
|
|
"id": "manage_locations_widget",
|
|
"type": "table",
|
|
"selector": "body > main > div"
|
|
}
|
|
)
|
|
|
|
|
|
def map_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get("dispatchers_steamid", None)
|
|
current_view = kwargs.get("current_view", None)
|
|
|
|
# Load templates
|
|
template_map = module.templates.get_template('manage_locations_widget/view_map.html')
|
|
template_view_menu = module.templates.get_template('manage_locations_widget/control_view_menu.html')
|
|
control_player_location_view_template = module.templates.get_template(
|
|
'manage_locations_widget/control_player_location.html'
|
|
)
|
|
|
|
# Get current view and player coordinates
|
|
current_view = module.get_current_view(dispatchers_steamid)
|
|
player_coordinates = module.dom.data.get("module_players", {}).get("players", {}).get(dispatchers_steamid, {}).get(
|
|
"pos", {"x": 0, "y": 0, "z": 0}
|
|
)
|
|
|
|
# Collect all locations for the map
|
|
all_locations = module.dom.data.get(module.get_module_identifier(), {}).get("elements", {})
|
|
locations_for_map = {}
|
|
active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None)
|
|
|
|
for map_identifier, location_owners in all_locations.items():
|
|
if active_dataset and map_identifier != active_dataset:
|
|
continue
|
|
for owner_steamid, player_locations in location_owners.items():
|
|
for identifier, location_dict in player_locations.items():
|
|
location_id = f"{map_identifier}_{owner_steamid}_{identifier}"
|
|
coordinates = location_dict.get("coordinates", {})
|
|
dimensions = location_dict.get("dimensions", {})
|
|
shape = location_dict.get("shape", "circle")
|
|
|
|
locations_for_map[location_id] = {
|
|
"name": location_dict.get("name", "Unknown"),
|
|
"identifier": identifier,
|
|
"owner": owner_steamid,
|
|
"shape": shape,
|
|
"coordinates": {
|
|
"x": float(coordinates.get("x", 0)),
|
|
"y": float(coordinates.get("y", 0)),
|
|
"z": float(coordinates.get("z", 0))
|
|
},
|
|
"dimensions": dimensions,
|
|
"teleport_entry": location_dict.get("teleport_entry", {}),
|
|
"type": location_dict.get("type", []),
|
|
"is_enabled": location_dict.get("is_enabled", False)
|
|
}
|
|
|
|
# Collect all online players for the map
|
|
players_module = loaded_modules_dict.get("module_players")
|
|
players_for_map = {}
|
|
|
|
if players_module:
|
|
active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None)
|
|
all_players = players_module.dom.data.get("module_players", {}).get("elements", {})
|
|
|
|
if active_dataset and active_dataset in all_players:
|
|
for steamid, player_dict in all_players[active_dataset].items():
|
|
if player_dict.get("is_online", False):
|
|
players_for_map[steamid] = {
|
|
"name": player_dict.get("name", "Player"),
|
|
"level": player_dict.get("level", 0),
|
|
"health": player_dict.get("health", 0),
|
|
"zombies": player_dict.get("zombies", 0),
|
|
"players": player_dict.get("players", 0),
|
|
"deaths": player_dict.get("deaths", 0),
|
|
"score": player_dict.get("score", 0),
|
|
"ping": player_dict.get("ping", 0),
|
|
"is_authenticated": player_dict.get("is_authenticated", False),
|
|
"is_muted": player_dict.get("is_muted", False),
|
|
"is_initialized": player_dict.get("is_initialized", False),
|
|
"in_limbo": player_dict.get("in_limbo", False),
|
|
"permission_level": player_dict.get("permission_level", None),
|
|
"dataset": active_dataset,
|
|
"pos": {
|
|
"x": player_dict.get("pos", {}).get("x", 0),
|
|
"y": player_dict.get("pos", {}).get("y", 0),
|
|
"z": player_dict.get("pos", {}).get("z", 0)
|
|
}
|
|
}
|
|
|
|
# Get gameprefs for map legend
|
|
gameprefs = {}
|
|
if active_dataset:
|
|
gameprefs = (
|
|
module.dom.data
|
|
.get("module_game_environment", {})
|
|
.get(active_dataset, {})
|
|
.get("gameprefs", {})
|
|
)
|
|
|
|
# Load webmap templates from players and locations modules
|
|
webmap_templates = {}
|
|
|
|
# Load player webmap templates
|
|
if players_module:
|
|
try:
|
|
webmap_templates['player_popup'] = players_module.templates.get_template('webmap/player_popup.html').render()
|
|
webmap_templates['player_markers'] = players_module.templates.get_template('webmap/player_markers.html').render()
|
|
webmap_templates['player_update_handler'] = players_module.templates.get_template('webmap/player_update_handler.html').render()
|
|
webmap_templates['player_actions'] = players_module.templates.get_template('webmap/player_actions.html').render()
|
|
except Exception as e:
|
|
module.logger.error(f"Error loading player webmap templates: {e}")
|
|
|
|
# Load location webmap templates
|
|
try:
|
|
webmap_templates['location_shapes'] = module.templates.get_template('webmap/location_shapes.html').render()
|
|
webmap_templates['location_update_handler'] = module.templates.get_template('webmap/location_update_handler.html').render()
|
|
webmap_templates['location_actions'] = module.templates.get_template('webmap/location_actions.html').render()
|
|
except Exception as e:
|
|
module.logger.error(f"Error loading location webmap templates: {e}")
|
|
|
|
# Render navigation menu using view registry
|
|
control_switch_view = module.template_render_hook(
|
|
module,
|
|
template=template_view_menu,
|
|
views=VIEW_REGISTRY,
|
|
current_view=current_view,
|
|
steamid=dispatchers_steamid,
|
|
control_player_location_view=module.template_render_hook(
|
|
module,
|
|
template=control_player_location_view_template,
|
|
pos_x=player_coordinates["x"],
|
|
pos_y=player_coordinates["y"],
|
|
pos_z=player_coordinates["z"]
|
|
)
|
|
)
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=template_map,
|
|
control_switch_view=control_switch_view,
|
|
webmap_templates=webmap_templates
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="widget_content",
|
|
clients=[dispatchers_steamid],
|
|
target_element={
|
|
"id": "manage_locations_widget",
|
|
"type": "table",
|
|
"selector": "body > main > div"
|
|
}
|
|
)
|
|
|
|
# Send map metadata via Socket.IO
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload={
|
|
"gameprefs": gameprefs,
|
|
"active_dataset": active_dataset or "Unknown"
|
|
},
|
|
data_type="map_metadata",
|
|
clients=[dispatchers_steamid]
|
|
)
|
|
|
|
# Send initial player data via Socket.IO
|
|
for steamid, player_data in players_for_map.items():
|
|
player_update_data = {
|
|
"steamid": steamid,
|
|
"name": player_data.get("name", "Player"),
|
|
"level": player_data.get("level", 0),
|
|
"health": player_data.get("health", 0),
|
|
"zombies": player_data.get("zombies", 0),
|
|
"deaths": player_data.get("deaths", 0),
|
|
"players": player_data.get("players", 0),
|
|
"score": player_data.get("score", 0),
|
|
"ping": player_data.get("ping", 0),
|
|
"is_muted": player_data.get("is_muted", False),
|
|
"is_authenticated": player_data.get("is_authenticated", False),
|
|
"in_limbo": player_data.get("in_limbo", False),
|
|
"is_initialized": player_data.get("is_initialized", False),
|
|
"permission_level": player_data.get("permission_level", None),
|
|
"dataset": player_data.get("dataset", ""),
|
|
"position": {
|
|
"x": float(player_data.get("pos", {}).get("x", 0)),
|
|
"y": float(player_data.get("pos", {}).get("y", 0)),
|
|
"z": float(player_data.get("pos", {}).get("z", 0))
|
|
}
|
|
}
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=player_update_data,
|
|
data_type="player_position_update",
|
|
clients=[dispatchers_steamid]
|
|
)
|
|
|
|
# Send initial location data via Socket.IO
|
|
for location_id, location_data in locations_for_map.items():
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload={
|
|
"location_id": location_id,
|
|
"location": location_data
|
|
},
|
|
data_type="location_update",
|
|
clients=[dispatchers_steamid]
|
|
)
|
|
|
|
|
|
def options_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get("dispatchers_steamid", None)
|
|
|
|
# Load templates
|
|
template_frontend = module.templates.get_template('manage_locations_widget/view_options.html')
|
|
template_view_menu = module.templates.get_template('manage_locations_widget/control_view_menu.html')
|
|
|
|
# Get current view
|
|
current_view = module.get_current_view(dispatchers_steamid)
|
|
|
|
# Render navigation menu using view registry
|
|
options_toggle = module.template_render_hook(
|
|
module,
|
|
template=template_view_menu,
|
|
views=VIEW_REGISTRY,
|
|
current_view=current_view,
|
|
steamid=dispatchers_steamid,
|
|
control_player_location_view='' # No player location in options view
|
|
)
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=template_frontend,
|
|
options_toggle=options_toggle,
|
|
widget_options=module.options,
|
|
available_actions=module.available_actions_dict,
|
|
available_triggers=module.available_triggers_dict,
|
|
available_widgets=module.available_widgets_dict
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="widget_content",
|
|
clients=[dispatchers_steamid],
|
|
target_element={
|
|
"id": "manage_locations_widget",
|
|
"type": "table",
|
|
"selector": "body > main > div"
|
|
}
|
|
)
|
|
|
|
|
|
def special_locations_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get("dispatchers_steamid", None)
|
|
|
|
# Load templates
|
|
template_frontend = module.templates.get_template('manage_locations_widget/view_special_locations.html')
|
|
template_view_menu = module.templates.get_template('manage_locations_widget/control_view_menu.html')
|
|
|
|
# Get current view
|
|
current_view = module.get_current_view(dispatchers_steamid)
|
|
|
|
# Render navigation menu using view registry
|
|
options_toggle = module.template_render_hook(
|
|
module,
|
|
template=template_view_menu,
|
|
views=VIEW_REGISTRY,
|
|
current_view=current_view,
|
|
steamid=dispatchers_steamid,
|
|
control_player_location_view=''
|
|
)
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=template_frontend,
|
|
options_toggle=options_toggle
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="widget_content",
|
|
clients=[dispatchers_steamid],
|
|
target_element={
|
|
"id": "manage_locations_widget",
|
|
"type": "table",
|
|
"selector": "body > main > div"
|
|
}
|
|
)
|
|
|
|
|
|
def edit_view(*args, **kwargs):
|
|
module = args[0]
|
|
dispatchers_steamid = kwargs.get("dispatchers_steamid", None)
|
|
edit_mode = kwargs.get("current_view", None)
|
|
|
|
location_to_edit_dict = {}
|
|
if edit_mode == "edit_location_entry":
|
|
location_owner = kwargs.get("location_owner", None)
|
|
location_identifier = kwargs.get("location_identifier", None)
|
|
location_origin = kwargs.get("location_origin", None)
|
|
if all([
|
|
location_owner is not None,
|
|
location_identifier is not None,
|
|
location_origin is not None
|
|
]):
|
|
location_to_edit_dict = (
|
|
module.dom.data
|
|
.get(module.get_module_identifier(), {})
|
|
.get("elements", {})
|
|
.get(location_origin)
|
|
.get(location_owner)
|
|
.get(location_identifier)
|
|
)
|
|
if edit_mode == "create_new":
|
|
location_to_edit_dict = {
|
|
"owner": str(dispatchers_steamid),
|
|
"is_enabled": False
|
|
}
|
|
|
|
# Check for prefilled coordinates from map
|
|
prefill_coords = (
|
|
module.dom.data
|
|
.get(module.get_module_identifier(), {})
|
|
.get("visibility", {})
|
|
.get(dispatchers_steamid, {})
|
|
.get("prefill_coordinates", None)
|
|
)
|
|
|
|
if prefill_coords:
|
|
location_to_edit_dict["coordinates"] = {
|
|
"x": float(prefill_coords.get("x", 0)),
|
|
"y": float(prefill_coords.get("y", 0)),
|
|
"z": float(prefill_coords.get("z", 0))
|
|
}
|
|
# Also prefill teleport_entry with same coordinates
|
|
location_to_edit_dict["teleport_entry"] = {
|
|
"x": float(prefill_coords.get("x", 0)),
|
|
"y": float(prefill_coords.get("y", 0)),
|
|
"z": float(prefill_coords.get("z", 0))
|
|
}
|
|
|
|
# Load templates
|
|
template_frontend = module.templates.get_template('manage_locations_widget/view_create_new.html')
|
|
template_view_menu = module.templates.get_template('manage_locations_widget/control_view_menu.html')
|
|
control_player_location_view_template = module.templates.get_template(
|
|
'manage_locations_widget/control_player_location.html'
|
|
)
|
|
|
|
# Get current view and player coordinates
|
|
current_view = module.get_current_view(dispatchers_steamid)
|
|
player_coordinates = module.dom.data.get("module_players", {}).get("players", {}).get(dispatchers_steamid, {}).get(
|
|
"pos", {"x": 0, "y": 0, "z": 0}
|
|
)
|
|
|
|
# Render navigation menu using view registry
|
|
options_toggle = module.template_render_hook(
|
|
module,
|
|
template=template_view_menu,
|
|
views=VIEW_REGISTRY,
|
|
current_view=current_view,
|
|
steamid=dispatchers_steamid,
|
|
control_player_location_view=module.template_render_hook(
|
|
module,
|
|
template=control_player_location_view_template,
|
|
pos_x=player_coordinates["x"],
|
|
pos_y=player_coordinates["y"],
|
|
pos_z=player_coordinates["z"]
|
|
)
|
|
)
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=template_frontend,
|
|
options_toggle=options_toggle,
|
|
widget_options=module.options,
|
|
location_to_edit_dict=location_to_edit_dict
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="widget_content",
|
|
clients=[dispatchers_steamid],
|
|
target_element={
|
|
"id": "manage_locations_widget",
|
|
"type": "table",
|
|
"selector": "body > main > div"
|
|
}
|
|
)
|
|
|
|
|
|
def table_row(*args, **kwargs):
|
|
module = args[0]
|
|
method = kwargs.get("method", None)
|
|
updated_values_dict = kwargs.get("updated_values_dict", None)
|
|
|
|
template_table_rows = module.templates.get_template('manage_locations_widget/table_row.html')
|
|
|
|
control_edit_link = module.templates.get_template('manage_locations_widget/control_edit_link.html')
|
|
control_enabled_link = module.templates.get_template('manage_locations_widget/control_enabled_link.html')
|
|
|
|
if updated_values_dict is not None:
|
|
if method in ["upsert", "update", "edit"]:
|
|
active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None)
|
|
for clientid in module.webserver.connected_clients.keys():
|
|
current_view = module.get_current_view(clientid)
|
|
visibility_conditions = [
|
|
current_view == "frontend"
|
|
]
|
|
if any(visibility_conditions): # only relevant if the table is shown
|
|
for player_steamid, locations in updated_values_dict.items():
|
|
player_dict = (
|
|
module.dom.data
|
|
.get("module_players", {})
|
|
.get("elements", {})
|
|
.get(active_dataset, {})
|
|
.get(player_steamid, {})
|
|
)
|
|
for identifier, location_dict in locations.items():
|
|
location_is_selected_by = location_dict.get("selected_by", [])
|
|
|
|
location_entry_selected = False
|
|
if clientid in location_is_selected_by:
|
|
location_entry_selected = True
|
|
|
|
try:
|
|
# Sanitize dataset for HTML ID (replace spaces with underscores, lowercase)
|
|
sanitized_dataset = module.dom_management.sanitize_for_html_id(updated_values_dict[player_steamid][identifier]["dataset"])
|
|
table_row_id = "location_table_row_{}_{}_{}".format(
|
|
sanitized_dataset,
|
|
str(player_steamid),
|
|
str(identifier)
|
|
)
|
|
# Update location_dict with sanitized dataset for template
|
|
location_dict = location_dict.copy()
|
|
location_dict["dataset"] = sanitized_dataset
|
|
location_dict["dataset_original"] = updated_values_dict[player_steamid][identifier].get("dataset", "")
|
|
except KeyError:
|
|
table_row_id = "manage_locations_widget"
|
|
|
|
control_select_link = module.dom_management.get_selection_dom_element(
|
|
module,
|
|
target_module="module_locations",
|
|
dom_element_select_root=[identifier, "selected_by"],
|
|
dom_element=location_dict,
|
|
dom_element_entry_selected=location_entry_selected,
|
|
dom_action_inactive="select_dom_element",
|
|
dom_action_active="deselect_dom_element"
|
|
)
|
|
rendered_table_row = module.template_render_hook(
|
|
module,
|
|
template=template_table_rows,
|
|
location=location_dict,
|
|
player_dict=player_dict,
|
|
control_select_link=control_select_link,
|
|
control_enabled_link=module.template_render_hook(
|
|
module,
|
|
template=control_enabled_link,
|
|
location=location_dict,
|
|
),
|
|
control_edit_link=module.template_render_hook(
|
|
module,
|
|
template=control_edit_link,
|
|
location=location_dict,
|
|
),
|
|
css_class=get_table_row_css_class(location_dict)
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=rendered_table_row,
|
|
data_type="table_row",
|
|
clients=[clientid],
|
|
target_element={
|
|
"id": table_row_id,
|
|
"type": "tr",
|
|
"class": get_table_row_css_class(location_dict),
|
|
"selector": "body > main > div > div#manage_locations_widget > main > table > tbody"
|
|
}
|
|
)
|
|
else: # table is not visible or current user, skip it!
|
|
continue
|
|
elif method in ["remove"]: # callback_dict sent us here with a removal notification!
|
|
location_origin = updated_values_dict[2]
|
|
player_steamid = updated_values_dict[3]
|
|
location_identifier = updated_values_dict[-1]
|
|
|
|
# Sanitize dataset for HTML ID (replace spaces with underscores, lowercase)
|
|
sanitized_origin = module.dom_management.sanitize_for_html_id(location_origin)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
data_type="remove_table_row",
|
|
clients="all",
|
|
target_element={
|
|
"id": "location_table_row_{}_{}_{}".format(
|
|
sanitized_origin,
|
|
str(player_steamid),
|
|
str(location_identifier)
|
|
),
|
|
}
|
|
)
|
|
|
|
update_delete_button_status(module, *args, **kwargs)
|
|
|
|
|
|
def update_player_location(*args, **kwargs):
|
|
module = args[0]
|
|
updated_values_dict = kwargs.get("updated_values_dict", None)
|
|
webserver_logged_in_users = module.dom.data.get("module_webserver", {}).get(
|
|
"webserver_logged_in_users", []
|
|
)
|
|
|
|
dispatchers_steamid = updated_values_dict.get("steamid")
|
|
if dispatchers_steamid not in webserver_logged_in_users:
|
|
return
|
|
|
|
control_player_location_view = module.templates.get_template(
|
|
'manage_locations_widget/control_player_location.html'
|
|
)
|
|
|
|
player_coordinates = updated_values_dict.get("pos", {})
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=control_player_location_view,
|
|
pos_x=player_coordinates["x"],
|
|
pos_y=player_coordinates["y"],
|
|
pos_z=player_coordinates["z"]
|
|
)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="element_content",
|
|
method="replace",
|
|
clients=dispatchers_steamid,
|
|
target_element={
|
|
"id": "current_player_pos"
|
|
}
|
|
)
|
|
|
|
|
|
def update_selection_status(*args, **kwargs):
|
|
module = args[0]
|
|
updated_values_dict = kwargs.get("updated_values_dict", None)
|
|
location_identifier = updated_values_dict["identifier"]
|
|
|
|
# Sanitize dataset for HTML ID (replace spaces with underscores, lowercase)
|
|
sanitized_dataset = module.dom_management.sanitize_for_html_id(updated_values_dict["dataset"])
|
|
|
|
module.dom_management.update_selection_status(
|
|
*args, **kwargs,
|
|
target_module=module,
|
|
dom_element_root=[location_identifier],
|
|
dom_element_select_root=[location_identifier, "selected_by"],
|
|
dom_action_active="deselect_dom_element",
|
|
dom_action_inactive="select_dom_element",
|
|
dom_element_id={
|
|
"id": "location_table_row_{}_{}_{}_control_select_link".format(
|
|
sanitized_dataset,
|
|
updated_values_dict["owner"],
|
|
updated_values_dict["identifier"]
|
|
)
|
|
}
|
|
)
|
|
|
|
update_delete_button_status(module, *args, **kwargs)
|
|
|
|
|
|
def update_enabled_flag(*args, **kwargs):
|
|
module = args[0]
|
|
original_values_dict = kwargs.get("original_values_dict", None)
|
|
|
|
control_enable_link = module.templates.get_template('manage_locations_widget/control_enabled_link.html')
|
|
|
|
location_origin = original_values_dict.get("dataset", None)
|
|
location_owner = original_values_dict.get("owner", None)
|
|
location_identifier = original_values_dict.get("identifier", None)
|
|
|
|
location_dict = (
|
|
module.dom.data.get("module_locations", {})
|
|
.get("elements", {})
|
|
.get(location_origin, {})
|
|
.get(location_owner, {})
|
|
.get(location_identifier, None)
|
|
)
|
|
|
|
# Sanitize dataset for HTML ID (replace spaces with underscores, lowercase)
|
|
location_dict_sanitized = location_dict.copy()
|
|
location_dict_sanitized["dataset"] = module.dom_management.sanitize_for_html_id(location_origin)
|
|
location_dict_sanitized["dataset_original"] = location_origin
|
|
|
|
data_to_emit = module.template_render_hook(
|
|
module,
|
|
template=control_enable_link,
|
|
location=location_dict_sanitized,
|
|
)
|
|
|
|
# Sanitize dataset for HTML ID (replace spaces with underscores, lowercase)
|
|
sanitized_origin = module.dom_management.sanitize_for_html_id(location_origin)
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload=data_to_emit,
|
|
data_type="element_content",
|
|
clients="all",
|
|
method="update",
|
|
target_element={
|
|
"id": "location_table_row_{}_{}_{}_control_enabled_link".format(
|
|
sanitized_origin,
|
|
location_owner,
|
|
location_identifier
|
|
),
|
|
}
|
|
)
|
|
|
|
|
|
def update_delete_button_status(*args, **kwargs):
|
|
module = args[0]
|
|
|
|
module.dom_management.update_delete_button_status(
|
|
*args, **kwargs,
|
|
target_module=module,
|
|
dom_element_root=module.dom_element_root,
|
|
dom_element_select_root=module.dom_element_select_root,
|
|
dom_action="delete_selected_dom_elements",
|
|
dom_element_id={
|
|
"id": "manage_locations_control_action_delete_link"
|
|
}
|
|
)
|
|
|
|
|
|
def update_location_on_map(*args, **kwargs):
|
|
"""Send location updates to map view via socket.io"""
|
|
module = args[0]
|
|
method = kwargs.get("method", None)
|
|
updated_values_dict = kwargs.get("updated_values_dict", None)
|
|
|
|
if updated_values_dict is None:
|
|
return
|
|
|
|
# Check which clients are viewing the map
|
|
for clientid in module.webserver.connected_clients.keys():
|
|
current_view = module.get_current_view(clientid)
|
|
if current_view != "map":
|
|
continue
|
|
|
|
if method in ["upsert", "update", "edit"]:
|
|
# Send location update for each changed location
|
|
active_dataset = module.dom.data.get("module_game_environment", {}).get("active_dataset", None)
|
|
|
|
# updated_values_dict structure at callback depth 4:
|
|
# {location_identifier: {location_data}}
|
|
# location_data includes "owner" field
|
|
|
|
for identifier, location_dict in updated_values_dict.items():
|
|
if not isinstance(location_dict, dict):
|
|
continue
|
|
|
|
# Get owner directly from location_dict
|
|
owner_steamid = location_dict.get("owner")
|
|
if owner_steamid is None:
|
|
continue
|
|
|
|
location_id = f"{active_dataset}_{owner_steamid}_{identifier}"
|
|
|
|
# Get full location data from DOM if fields are missing in updated_values_dict
|
|
# (e.g., when only is_enabled is updated)
|
|
full_location_dict = (
|
|
module.dom.data
|
|
.get("module_locations", {})
|
|
.get("elements", {})
|
|
.get(active_dataset, {})
|
|
.get(owner_steamid, {})
|
|
.get(identifier, {})
|
|
)
|
|
|
|
coordinates = location_dict.get("coordinates")
|
|
if coordinates is None:
|
|
coordinates = full_location_dict.get("coordinates", {})
|
|
|
|
dimensions = location_dict.get("dimensions")
|
|
if dimensions is None:
|
|
dimensions = full_location_dict.get("dimensions", {})
|
|
|
|
location_data = {
|
|
"name": location_dict.get("name", full_location_dict.get("name", "Unknown")),
|
|
"identifier": identifier,
|
|
"owner": owner_steamid,
|
|
"shape": location_dict.get("shape", full_location_dict.get("shape", "circle")),
|
|
"coordinates": {
|
|
"x": float(coordinates.get("x", 0)),
|
|
"y": float(coordinates.get("y", 0)),
|
|
"z": float(coordinates.get("z", 0))
|
|
},
|
|
"dimensions": dimensions,
|
|
"teleport_entry": location_dict.get("teleport_entry", full_location_dict.get("teleport_entry", {})),
|
|
"type": location_dict.get("type", full_location_dict.get("type", [])),
|
|
"is_enabled": location_dict.get("is_enabled", full_location_dict.get("is_enabled", False))
|
|
}
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload={
|
|
"location_id": location_id,
|
|
"location": location_data
|
|
},
|
|
data_type="location_update",
|
|
clients=[clientid]
|
|
)
|
|
|
|
elif method in ["remove"]:
|
|
# Send location removal
|
|
location_origin = updated_values_dict[2]
|
|
owner_steamid = updated_values_dict[3]
|
|
location_identifier = updated_values_dict[-1]
|
|
location_id = f"{location_origin}_{owner_steamid}_{location_identifier}"
|
|
|
|
module.webserver.send_data_to_client_hook(
|
|
module,
|
|
payload={
|
|
"location_id": location_id
|
|
},
|
|
data_type="location_remove",
|
|
clients=[clientid]
|
|
)
|
|
|
|
|
|
widget_meta = {
|
|
"description": "shows locations and stuff",
|
|
"main_widget": select_view,
|
|
"handlers": {
|
|
# the %abc% placeholders can contain any text at all, it has no effect on anything but code-readability
|
|
# the third line could just as well read
|
|
# "module_locations/elements/%x%/%x%/%x%/selected_by": update_selection_status
|
|
# and would still function the same as
|
|
# "module_locations/elements/%map_identifier%/%steamid%/%element_identifier%/selected_by":
|
|
# update_selection_status
|
|
"module_locations/visibility/%steamid%/current_view":
|
|
select_view,
|
|
"module_locations/elements/%map_identifier%/%steamid%":
|
|
table_row,
|
|
"module_locations/elements/%map_identifier%/%owner_steamid%/%element_identifier%":
|
|
update_location_on_map,
|
|
"module_locations/elements/%map_identifier%/%steamid%/%element_identifier%/selected_by":
|
|
update_selection_status,
|
|
"module_locations/elements/%map_identifier%/%steamid%/%element_identifier%/is_enabled":
|
|
update_enabled_flag,
|
|
"module_players/elements/%map_identifier%/%steamid%/pos":
|
|
update_player_location
|
|
},
|
|
"enabled": True
|
|
}
|
|
|
|
loaded_modules_dict["module_" + module_name].register_widget(widget_name, widget_meta)
|