Add terrain minimap to dashboard
This commit is contained in:
@@ -8,6 +8,7 @@ import threading
|
||||
import time
|
||||
import traceback
|
||||
import sys
|
||||
from math import floor
|
||||
from pathlib import Path
|
||||
|
||||
import logging
|
||||
@@ -158,6 +159,84 @@ def api_global():
|
||||
return response
|
||||
|
||||
|
||||
def _minimap_surface_cell(chunks, x, z):
|
||||
"""Return the uppermost solid/water block in a loaded world column."""
|
||||
from mosfet.info import blocks
|
||||
|
||||
chunk_x, chunk_z = floor(x / 16), floor(z / 16)
|
||||
chunk = chunks.chunks.get((chunk_x, chunk_z))
|
||||
if chunk is None:
|
||||
return None
|
||||
|
||||
local_x, local_z = x - chunk_x * 16, z - chunk_z * 16
|
||||
min_y = getattr(chunks, 'min_y', -64)
|
||||
for section_y in sorted(chunk.sections, reverse=True):
|
||||
if section_y * 16 + 15 < min_y:
|
||||
continue
|
||||
section = chunk.sections[section_y]
|
||||
if section.get('non_empty_blocks') == 0:
|
||||
continue
|
||||
for y in range(section_y * 16 + 15, max(min_y, section_y * 16) - 1, -1):
|
||||
state_id = chunk.get_block_at(local_x, y, local_z)
|
||||
if state_id is None or state_id == blocks.AIR:
|
||||
continue
|
||||
if (state_id in blocks.NON_SOLID_IDS and
|
||||
state_id not in blocks.WATER_IDS):
|
||||
continue
|
||||
return {'block': blocks.BLOCKS.get(state_id, 'unknown'), 'y': y}
|
||||
return None
|
||||
|
||||
|
||||
@app.route('/api/minimap')
|
||||
def api_minimap():
|
||||
position = g.get('pos') or g.get('player_position')
|
||||
chunks = g.get('chunks')
|
||||
if (not g.get('connected') or position is None or position is False or
|
||||
chunks is None or not hasattr(chunks, 'chunks')):
|
||||
return jsonify(ready=False, cells=[])
|
||||
|
||||
try:
|
||||
radius = int(request.args.get('radius', 12))
|
||||
except (TypeError, ValueError):
|
||||
radius = 12
|
||||
radius = max(4, min(32, radius))
|
||||
try:
|
||||
radius_x = int(request.args.get('radius_x', radius))
|
||||
except (TypeError, ValueError):
|
||||
radius_x = radius
|
||||
try:
|
||||
radius_z = int(request.args.get('radius_z', radius))
|
||||
except (TypeError, ValueError):
|
||||
radius_z = radius
|
||||
radius_x = max(4, min(48, radius_x))
|
||||
radius_z = max(4, min(32, radius_z))
|
||||
center_x, center_z = floor(position.x), floor(position.z)
|
||||
center_y = floor(position.y)
|
||||
lock = getattr(chunks, 'lock', None)
|
||||
if lock is not None:
|
||||
lock.acquire()
|
||||
try:
|
||||
cells = [
|
||||
[_minimap_surface_cell(chunks, center_x + dx, center_z + dz)
|
||||
for dx in range(-radius_x, radius_x + 1)]
|
||||
for dz in range(-radius_z, radius_z + 1)
|
||||
]
|
||||
finally:
|
||||
if lock is not None:
|
||||
lock.release()
|
||||
|
||||
ready = any(cell is not None for row in cells for cell in row)
|
||||
return jsonify(
|
||||
ready=ready,
|
||||
center={'x': center_x, 'y': center_y, 'z': center_z},
|
||||
yaw=float(g.get('yaw', 0.0) or 0.0),
|
||||
radius=radius,
|
||||
radius_x=radius_x,
|
||||
radius_z=radius_z,
|
||||
cells=cells if ready else [],
|
||||
)
|
||||
|
||||
|
||||
@app.route('/api/items')
|
||||
def api_items():
|
||||
from mosfet.info.items import ITEM_NAMES
|
||||
|
||||
Reference in New Issue
Block a user