Release 0.9.0
This commit is contained in:
143
bot/modules/locations/templates/webmap/location_shapes.html
Normal file
143
bot/modules/locations/templates/webmap/location_shapes.html
Normal file
@@ -0,0 +1,143 @@
|
||||
// Helper function to create location shape based on type
|
||||
function createLocationShape(locationId, loc) {
|
||||
const coords = loc.coordinates;
|
||||
const centerLatLng = [coords.x, coords.z]; // 7D2D coordinates (x, z)
|
||||
const dims = loc.dimensions || {};
|
||||
const shape = loc.shape || 'circle';
|
||||
const isEnabled = loc.is_enabled;
|
||||
const is3D = (shape === 'box' || shape === 'spherical');
|
||||
|
||||
// Color scheme
|
||||
const fillColor = isEnabled ? '#ff9900' : '#666666';
|
||||
const strokeColor = isEnabled ? '#ffcc00' : '#999999';
|
||||
const fillOpacity = isEnabled ? 0.3 : 0.15;
|
||||
|
||||
let leafletShape;
|
||||
|
||||
if (shape === 'circle') {
|
||||
const radius = parseFloat(dims.radius || 10);
|
||||
leafletShape = L.circle(centerLatLng, {
|
||||
radius: radius,
|
||||
fillColor: fillColor,
|
||||
color: strokeColor,
|
||||
weight: 2,
|
||||
opacity: 0.8,
|
||||
fillOpacity: fillOpacity
|
||||
});
|
||||
} else if (shape === 'spherical') {
|
||||
const radius = parseFloat(dims.radius || 10);
|
||||
leafletShape = L.circle(centerLatLng, {
|
||||
radius: radius,
|
||||
fillColor: fillColor,
|
||||
color: strokeColor,
|
||||
weight: 2,
|
||||
opacity: 0.8,
|
||||
fillOpacity: fillOpacity,
|
||||
dashArray: '5, 5' // Dashed to indicate 3D
|
||||
});
|
||||
} else if (shape === 'rectangular') {
|
||||
const width = parseFloat(dims.width || 10);
|
||||
const length = parseFloat(dims.length || 10);
|
||||
// Rectangle bounds: from center, extend width/length in both directions
|
||||
const bounds = [
|
||||
[coords.x - width, coords.z - length],
|
||||
[coords.x + width, coords.z + length]
|
||||
];
|
||||
leafletShape = L.rectangle(bounds, {
|
||||
fillColor: fillColor,
|
||||
color: strokeColor,
|
||||
weight: 2,
|
||||
opacity: 0.8,
|
||||
fillOpacity: fillOpacity
|
||||
});
|
||||
} else if (shape === 'box') {
|
||||
const width = parseFloat(dims.width || 10);
|
||||
const length = parseFloat(dims.length || 10);
|
||||
const bounds = [
|
||||
[coords.x - width, coords.z - length],
|
||||
[coords.x + width, coords.z + length]
|
||||
];
|
||||
leafletShape = L.rectangle(bounds, {
|
||||
fillColor: fillColor,
|
||||
color: strokeColor,
|
||||
weight: 2,
|
||||
opacity: 0.8,
|
||||
fillOpacity: fillOpacity,
|
||||
dashArray: '5, 5' // Dashed to indicate 3D
|
||||
});
|
||||
} else {
|
||||
// Fallback to circle
|
||||
leafletShape = L.circle(centerLatLng, {
|
||||
radius: 10,
|
||||
fillColor: fillColor,
|
||||
color: strokeColor,
|
||||
weight: 2,
|
||||
opacity: 0.8,
|
||||
fillOpacity: fillOpacity
|
||||
});
|
||||
}
|
||||
|
||||
// Build popup content
|
||||
const dimensionText = shape === 'circle' || shape === 'spherical'
|
||||
? `Radius: ${dims.radius || 'N/A'}`
|
||||
: `Width: ${dims.width || 'N/A'}, Length: ${dims.length || 'N/A'}${shape === 'box' ? ', Height: ' + (dims.height || 'N/A') : ''}`;
|
||||
|
||||
// Parse locationId to extract components
|
||||
// Format: {dataset}_{owner}_{identifier}
|
||||
const locationIdParts = locationId.split('_');
|
||||
const dataset = locationIdParts.slice(0, -2).join('_'); // Handle datasets with underscores
|
||||
const owner = locationIdParts[locationIdParts.length - 2];
|
||||
const identifier = locationIdParts[locationIdParts.length - 1];
|
||||
|
||||
const teleportEntry = loc.teleport_entry || {};
|
||||
const hasTeleport = teleportEntry.x !== undefined && teleportEntry.y !== undefined && teleportEntry.z !== undefined;
|
||||
const teleportText = hasTeleport
|
||||
? `TP: ${parseFloat(teleportEntry.x || 0).toFixed(0)}, ${parseFloat(teleportEntry.y || 0).toFixed(0)}, ${parseFloat(teleportEntry.z || 0).toFixed(0)}`
|
||||
: 'TP: Not set';
|
||||
|
||||
// Use template literal for clean HTML
|
||||
const popupContent = `
|
||||
<div style="min-width: 250px; font-family: monospace;">
|
||||
<b style="font-size: 1.1em;">${loc.name}</b>
|
||||
<br><span style="font-size: 0.9em; color: #888;">${is3D ? '🎲 3D' : '⬜ 2D'} - ${shape}</span>
|
||||
<br><hr style="margin: 5px 0; border-color: #333;">
|
||||
<b>Type:</b> ${loc.type && loc.type.length > 0 ? loc.type.join(', ') : 'None'}
|
||||
<br><b>Owner:</b> ${loc.owner}
|
||||
<br><b>Status:</b> ${isEnabled ? '✅ Enabled' : '❌ Disabled'}
|
||||
<br><b>Position:</b> ${coords.x.toFixed(0)}, ${coords.y.toFixed(0)}, ${coords.z.toFixed(0)}
|
||||
<br><b>Dimensions:</b> ${dimensionText}
|
||||
<br><b>${teleportText}</b>
|
||||
<br><hr style="margin: 8px 0; border-color: #333;">
|
||||
<div style="display: flex; gap: 5px; justify-content: space-between; align-items: center; margin-bottom: 5px;">
|
||||
<button onclick="editLocationFromMap('${dataset}', '${owner}', '${identifier}')"
|
||||
style="flex: 1; padding: 6px 12px; background: var(--lcars-hopbush); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold;">
|
||||
✏️ Edit</button>
|
||||
<label style="display: flex; align-items: center; gap: 5px; cursor: pointer; white-space: nowrap;">
|
||||
<input type="checkbox"
|
||||
id="enable_${locationId}"
|
||||
${isEnabled ? 'checked' : ''}
|
||||
onchange="toggleLocationEnabled('${dataset}', '${owner}', '${identifier}', this.checked)"
|
||||
style="cursor: pointer; width: 18px; height: 18px;" />
|
||||
<span style="font-weight: bold;">Enabled</span>
|
||||
</label>
|
||||
</div>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<button onclick="moveLocationFromMap('${locationId}')"
|
||||
style="flex: 1; padding: 6px 10px; background: var(--lcars-anakiwa); color: #000; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 0.9em;">
|
||||
📍 Move</button>
|
||||
<button onclick="setTeleportFromMap('${locationId}')"
|
||||
style="flex: 1; padding: 6px 10px; background: var(--lcars-golden-tanoi); color: #000; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 0.9em;">
|
||||
🎯 Set TP</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
leafletShape.bindPopup(popupContent);
|
||||
leafletShape.addTo(map);
|
||||
|
||||
return leafletShape;
|
||||
}
|
||||
|
||||
// Location shapes are now loaded dynamically via Socket.IO
|
||||
// Initial loading is handled by location_update events
|
||||
// See location_update_handler.html for shape creation logic
|
||||
Reference in New Issue
Block a user