second alpha (v0.2)
This commit is contained in:
parent
7a343254e2
commit
7a1094c733
22 changed files with 2343 additions and 1511 deletions
202
site_generator/templates/world_detail_radar.template
Normal file
202
site_generator/templates/world_detail_radar.template
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
<h3 id='weltradar' class="section-header-flex">
|
||||
<span>Weltradar</span>
|
||||
<div class="map-toggle-controls">
|
||||
<button id="toggle-live-btn-%%current_world_key%%" class="map-toggle-button active">Live</button>
|
||||
<button id="toggle-archive-btn-%%current_world_key%%" class="map-toggle-button">Archiv</button>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<div id="live-map-container-%%current_world_key%%">
|
||||
<div id="ol-map-container-%%current_world_key%%" class="map-view-container"></div>
|
||||
|
||||
<div id="popup-%%current_world_key%%" class="ol-popup">
|
||||
<a href="#" id="popup-closer-%%current_world_key%%" class="ol-popup-closer"></a>
|
||||
<div id="popup-content-%%current_world_key%%" class="ol-popup-content"></div>
|
||||
</div>
|
||||
<div class='map-sub-info'>
|
||||
%%map_sub_info_link%%
|
||||
<span class='map-last-update'>Letzte Kartenaktualisierung: <span id='map-last-update-text-%%current_world_key%%'><em>wird geladen...</em></span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="archive-view-container-%%current_world_key%%" style="display: none;">
|
||||
%%ARCHIVE_HTML%%
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Globale Referenzen
|
||||
window.olMap_%%current_world_key%% = null;
|
||||
window.playerMarkerSource_%%current_world_key%% = new ol.source.Vector();
|
||||
window.mapData_%%current_world_key%% = {};
|
||||
|
||||
// Konvertiert Minetest-Koordinaten in OpenLayers-Pixel-Koordinaten
|
||||
function convertMinetestToOpenLayers_%%current_world_key%%(posX, posZ) {
|
||||
const mapData = window.mapData_%%current_world_key%%;
|
||||
if (!mapData || !mapData.mapWidth) return null;
|
||||
|
||||
const percentX = (posX - mapData.minX) / mapData.extentWidth;
|
||||
const percentZ = (posZ - mapData.minZ) / mapData.extentHeight;
|
||||
|
||||
const pixelX = percentX * mapData.mapWidth;
|
||||
const pixelY = - (mapData.mapHeight - (percentZ * mapData.mapHeight));
|
||||
|
||||
return [pixelX, pixelY];
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const mapContainer = document.getElementById('ol-map-container-%%current_world_key%%');
|
||||
const mapInfoPath = '/%%web_map_info_rel_path%%?v=' + new Date().getTime();
|
||||
|
||||
fetch(mapInfoPath)
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error('map_info.txt nicht gefunden (Status: ' + response.status + ')');
|
||||
return response.text();
|
||||
})
|
||||
.then(mapInfoText => {
|
||||
const mapInfo = (text => {
|
||||
const data = {};
|
||||
text.split('\n').forEach(line => {
|
||||
const parts = line.split('=');
|
||||
if (parts.length === 2 && parts[0] && parts[1]) data[parts[0].trim()] = parts[1].trim();
|
||||
});
|
||||
return data;
|
||||
})(mapInfoText);
|
||||
|
||||
if (!mapInfo.map_dimension || !mapInfo.map_extent) throw new Error('map_info.txt ist unvollständig.');
|
||||
|
||||
const mapData = window.mapData_%%current_world_key%%;
|
||||
const mapDim = mapInfo.map_dimension.split('x');
|
||||
mapData.mapWidth = parseInt(mapDim[0], 10);
|
||||
mapData.mapHeight = parseInt(mapDim[1], 10);
|
||||
|
||||
const mapExt = mapInfo.map_extent.split(/[+:]/);
|
||||
mapData.minX = parseInt(mapExt[0], 10);
|
||||
mapData.minZ = parseInt(mapExt[1], 10);
|
||||
mapData.extentWidth = parseInt(mapExt[2], 10);
|
||||
mapData.extentHeight = parseInt(mapExt[3], 10);
|
||||
|
||||
if (mapContainer && typeof ol !== 'undefined' && mapData.mapWidth > 0) {
|
||||
mapContainer.innerHTML = '';
|
||||
|
||||
const extent = [0, -mapData.mapHeight, mapData.mapWidth, 0];
|
||||
const resolutions = %%RESOLUTIONS_JS_ARRAY%%;
|
||||
|
||||
const projection = new ol.proj.Projection({
|
||||
code: 'pixel-map-%%current_world_key%%',
|
||||
units: 'pixels',
|
||||
extent: extent
|
||||
});
|
||||
|
||||
const tileGrid = new ol.tilegrid.TileGrid({
|
||||
origin: ol.extent.getTopLeft(extent),
|
||||
resolutions: resolutions,
|
||||
});
|
||||
|
||||
const tileSource = new ol.source.TileImage({
|
||||
projection: projection,
|
||||
tileGrid: tileGrid,
|
||||
tileUrlFunction: function(tileCoord) {
|
||||
if (!tileCoord) return '';
|
||||
return ('/%%web_tiles_rel_path%%/' + tileCoord[0] + '/' + tileCoord[1] + '/' + tileCoord[2] + '.png?v=%%CACHE_BUSTER%%');
|
||||
}
|
||||
});
|
||||
|
||||
const tileLayer = new ol.layer.Tile({ source: tileSource });
|
||||
|
||||
const playerLayer = new ol.layer.Vector({ source: window.playerMarkerSource_%%current_world_key%%, style: f => f.get('style') });
|
||||
|
||||
const view = new ol.View({
|
||||
projection: projection,
|
||||
center: ol.extent.getCenter(extent),
|
||||
resolutions: resolutions,
|
||||
maxZoom: resolutions.length - 1
|
||||
});
|
||||
|
||||
const popupContainer = document.getElementById('popup-%%current_world_key%%');
|
||||
const popupContent = document.getElementById('popup-content-%%current_world_key%%');
|
||||
const popupCloser = document.getElementById('popup-closer-%%current_world_key%%');
|
||||
|
||||
const overlay = new ol.Overlay({ element: popupContainer, autoPan: { animation: { duration: 250 } } });
|
||||
popupCloser.onclick = () => { overlay.setPosition(undefined); popupCloser.blur(); return false; };
|
||||
|
||||
const mapControls = [ new ol.control.Zoom(), new ol.control.Rotate(), new ol.control.Attribution({ collapsible: false }), new ol.control.FullScreen() ];
|
||||
|
||||
window.olMap_%%current_world_key%% = new ol.Map({
|
||||
controls: mapControls,
|
||||
layers: [tileLayer, playerLayer],
|
||||
overlays: [overlay],
|
||||
target: mapContainer,
|
||||
view: view
|
||||
});
|
||||
|
||||
const map = window.olMap_%%current_world_key%%;
|
||||
|
||||
// KORREKTUR: Hintergrundfarbe wird hier per JavaScript gesetzt
|
||||
map.getViewport().style.backgroundColor = '%%map_background_color%%';
|
||||
|
||||
map.getView().fit(extent, { size: map.getSize() });
|
||||
|
||||
map.on('click', function(evt) {
|
||||
const feature = map.forEachFeatureAtPixel(evt.pixel, f => f);
|
||||
|
||||
overlay.setPosition(undefined);
|
||||
popupCloser.blur();
|
||||
|
||||
if (feature) {
|
||||
const playerData = feature.get('playerData');
|
||||
if (playerData) {
|
||||
const statusDotClass = feature.get('statusDotClass');
|
||||
const lastLoginFormatted = feature.get('lastLoginFormatted');
|
||||
const popupHTML = `
|
||||
<div class='popup-player-box'>
|
||||
<div class="player-header">
|
||||
<div class="player-identity">
|
||||
<img src="/images/players/${encodeURIComponent(playerData.name)}.png?v=%%CACHE_BUSTER%%" class="player-icon" onerror="this.onerror=null;this.src='/%%DEFAULT_PLAYER_SKIN_URL%%?v=%%CACHE_BUSTER%%';">
|
||||
<span class="player-name-status">
|
||||
<span class="status-dot ${statusDotClass}" title="Letzter Login: ${lastLoginFormatted}"></span>
|
||||
<strong class="player-name">${playerData.name}</strong>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="privilege-separator">
|
||||
<div class="popup-player-vitals">
|
||||
<span class="vital"><span class="icon">❤️</span> ${playerData.hp ?? '?'}</span>
|
||||
<span class="vital"><span class="icon">💨</span> ${playerData.breath ?? '?'}</span>
|
||||
<span class="vital"><span class="icon">🍖</span> ${playerData.stamina ?? '?'}</span>
|
||||
</div>
|
||||
</div>`;
|
||||
popupContent.innerHTML = popupHTML;
|
||||
overlay.setPosition(feature.getGeometry().getCoordinates());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (window.playerListLogic_%%current_world_key%% && window.playerListLogic_%%current_world_key%%.masterPlayerData) {
|
||||
window.playerListLogic_%%current_world_key%%.updatePlayerMarkers(window.playerListLogic_%%current_world_key%%.masterPlayerData);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Fehler beim Initialisieren der Karte:", error);
|
||||
mapContainer.innerHTML = "<p><em>Karte konnte nicht initialisiert werden: " + error.message + "</em></p>";
|
||||
});
|
||||
|
||||
const liveBtn = document.getElementById('toggle-live-btn-%%current_world_key%%');
|
||||
const archiveBtn = document.getElementById('toggle-archive-btn-%%current_world_key%%');
|
||||
const liveContainer = document.getElementById('live-map-container-%%current_world_key%%');
|
||||
const archiveContainer = document.getElementById('archive-view-container-%%current_world_key%%');
|
||||
|
||||
if (liveBtn && archiveBtn && liveContainer && archiveContainer) {
|
||||
liveBtn.addEventListener('click', () => {
|
||||
liveBtn.classList.add('active'); archiveBtn.classList.remove('active');
|
||||
liveContainer.style.display = 'block'; archiveContainer.style.display = 'none';
|
||||
if (window.olMap_%%current_world_key%%) {
|
||||
setTimeout(() => window.olMap_%%current_world_key%%.updateSize(), 10);
|
||||
}
|
||||
});
|
||||
archiveBtn.addEventListener('click', () => {
|
||||
archiveBtn.classList.add('active'); liveBtn.classList.remove('active');
|
||||
archiveContainer.style.display = 'block'; liveContainer.style.display = 'none';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue