What a mess

This commit is contained in:
Joan
2025-11-07 15:27:13 +01:00
parent 0b79b3ae59
commit 33cc9586c2
130 changed files with 29819 additions and 1175 deletions

View File

@@ -252,7 +252,7 @@ function populateForm(location) {
renderInteractablesList(location.interactables || {});
// Render connections
renderConnectionsList(location.id, location.exits);
renderConnectionsList(location.id);
}
function updateImagePreview(imagePath) {
@@ -282,26 +282,63 @@ function renderSpawnList(spawns) {
});
}
function renderConnectionsList(locationId, exits) {
const list = document.getElementById('connectionsList');
if (!list) return;
function renderConnectionsList(locationId) {
const list = document.getElementById('connectionList');
if (!list) {
console.error('connectionList element not found!');
return;
}
list.innerHTML = '';
for (const [direction, destId] of Object.entries(exits)) {
const destLocation = currentLocations.find(l => l.id === destId);
// Get connections from the global connections array
const locationConnections = connections.filter(conn => conn.from === locationId);
if (!locationConnections || locationConnections.length === 0) {
list.innerHTML = '<div style="padding: 10px; text-align: center; opacity: 0.5;">No connections</div>';
return;
}
locationConnections.forEach(conn => {
const destLocation = currentLocations.find(l => l.id === conn.to);
if (destLocation) {
const item = document.createElement('div');
item.className = 'connection-item';
item.innerHTML = `
<div class="connection-info">
<div class="connection-direction">${direction}${destLocation.name}</div>
<div class="connection-direction" style="font-weight: 500; color: #ffa726;">
${getDirectionEmoji(conn.direction)} ${conn.direction}
</div>
<div style="font-size: 0.85em; opacity: 0.7; margin-top: 4px;">
${destLocation.name}
</div>
</div>
<button class="btn btn-remove" onclick="deleteConnection('${locationId}', '${destId}')">×</button>
<button class="btn btn-remove" onclick="deleteConnection('${locationId}', '${conn.to}')"
style="width: 32px; height: 32px; padding: 0; font-size: 20px; line-height: 1;">×</button>
`;
list.appendChild(item);
}
}
});
}
function getDirectionEmoji(direction) {
const emojiMap = {
'north': '⬆️',
'south': '⬇️',
'east': '➡️',
'west': '⬅️',
'northeast': '↗️',
'northwest': '↖️',
'southeast': '↘️',
'southwest': '↙️',
'up': '⬆️',
'down': '⬇️',
'inside': '🚪',
'outside': '🚪'
};
return emojiMap[direction.toLowerCase()] || '🔀';
}
// ==================== CANVAS DRAWING ====================
@@ -837,11 +874,103 @@ function filterNPCList() {
});
}
async function promptAddConnection(fromId, toId) {
const direction = prompt('Enter direction (north, south, east, west, northeast, etc.):');
if (!direction) return;
// Store connection data temporarily
let pendingConnection = null;
function promptAddConnection(fromId, toId) {
// Store the connection data
pendingConnection = { fromId, toId };
// Get location names
const fromLocation = currentLocations.find(loc => loc.id === fromId);
const toLocation = currentLocations.find(loc => loc.id === toId);
// Update modal
document.getElementById('fromLocationName').textContent = fromLocation ? fromLocation.name : fromId;
document.getElementById('toLocationName').textContent = toLocation ? toLocation.name : toId;
// Reset selection
document.getElementById('directionSelect').value = '';
document.getElementById('autoReverseConnection').checked = true;
// Close location list modal and open direction modal
closeAddConnectionModal();
document.getElementById('selectDirectionModal').style.display = 'flex';
// Update reverse connection text based on selection
updateReverseConnectionText();
}
function updateReverseConnectionText() {
const directionSelect = document.getElementById('directionSelect');
const reverseText = document.getElementById('reverseConnectionText');
const checkbox = document.getElementById('autoReverseConnection');
if (!directionSelect || !reverseText || !checkbox) return;
const direction = directionSelect.value;
if (!direction) {
reverseText.textContent = 'Will also create a connection back from destination to source';
return;
}
const reverseDirection = getReverseDirection(direction);
const fromLocation = currentLocations.find(loc => loc.id === pendingConnection.fromId);
const toLocation = currentLocations.find(loc => loc.id === pendingConnection.toId);
if (checkbox.checked) {
reverseText.innerHTML = `Will create: <strong>${toLocation?.name || 'destination'}</strong> → ${reverseDirection} → <strong>${fromLocation?.name || 'source'}</strong>`;
} else {
reverseText.textContent = 'Only one-way connection will be created';
}
}
// Listen to direction changes
if (document.getElementById('directionSelect')) {
document.getElementById('directionSelect').addEventListener('change', updateReverseConnectionText);
document.getElementById('autoReverseConnection').addEventListener('change', updateReverseConnectionText);
}
function getReverseDirection(direction) {
const reverseMap = {
'north': 'south',
'south': 'north',
'east': 'west',
'west': 'east',
'northeast': 'southwest',
'northwest': 'southeast',
'southeast': 'northwest',
'southwest': 'northeast',
'up': 'down',
'down': 'up',
'inside': 'outside',
'outside': 'inside'
};
return reverseMap[direction] || direction;
}
function closeSelectDirectionModal() {
document.getElementById('selectDirectionModal').style.display = 'none';
pendingConnection = null;
}
async function confirmAddConnection() {
if (!pendingConnection) return;
const direction = document.getElementById('directionSelect').value;
const autoReverse = document.getElementById('autoReverseConnection').checked;
if (!direction) {
alert('Please select a direction');
return;
}
const { fromId, toId } = pendingConnection;
try {
// Add the main connection
const response = await fetch('/api/editor/connection', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
@@ -850,24 +979,99 @@ async function promptAddConnection(fromId, toId) {
const data = await response.json();
if (data.success) {
showSuccess('Connection added!');
await loadConnections();
await selectLocation(fromId); // Refresh form
drawMap();
closeAddConnectionModal();
} else {
if (!data.success) {
alert('Failed to add connection: ' + data.error);
return;
}
// Add reverse connection if enabled
if (autoReverse) {
const reverseDirection = getReverseDirection(direction);
const reverseResponse = await fetch('/api/editor/connection', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({from: toId, to: fromId, direction: reverseDirection})
});
const reverseData = await reverseResponse.json();
if (reverseData.success) {
showSuccess(`Connection added! (bidirectional: ${direction}${reverseDirection})`);
} else {
showSuccess(`Connection added (${direction}), but reverse failed: ${reverseData.error}`);
}
} else {
showSuccess(`Connection added! (one-way: ${direction})`);
}
// Refresh the view
await loadConnections();
await selectLocation(fromId); // Refresh form
drawMap();
closeSelectDirectionModal();
} catch (error) {
alert('Failed to add connection: ' + error.message);
}
}
async function deleteConnection(fromId, toId) {
if (!confirm('Delete this connection?')) return;
// Store pending deletion data
let pendingDeletion = null;
function deleteConnection(fromId, toId) {
// Get location information
const fromLocation = currentLocations.find(loc => loc.id === fromId);
const toLocation = currentLocations.find(loc => loc.id === toId);
if (!fromLocation || !toLocation) {
alert('Location not found');
return;
}
// Find the direction of this connection
const direction = Object.entries(fromLocation.exits || {}).find(([dir, dest]) => dest === toId)?.[0];
// Check if reverse connection exists
const reverseDirection = getReverseDirection(direction);
const hasReverseConnection = toLocation.exits && toLocation.exits[reverseDirection] === fromId;
// Store deletion data
pendingDeletion = { fromId, toId, direction, hasReverseConnection, reverseDirection };
// Update modal content
document.getElementById('deleteFromLocationName').textContent = fromLocation.name;
document.getElementById('deleteToLocationName').textContent = toLocation.name;
document.getElementById('deleteDirectionText').textContent = direction || 'unknown';
// Show/hide reverse connection option
const reverseOption = document.getElementById('deleteReverseOption');
if (hasReverseConnection) {
reverseOption.style.display = 'block';
document.getElementById('deleteReverseText').innerHTML =
`Also delete: <strong>${toLocation.name}</strong> → ${reverseDirection} → <strong>${fromLocation.name}</strong>`;
document.getElementById('deleteBothConnections').checked = true;
} else {
reverseOption.style.display = 'none';
document.getElementById('deleteBothConnections').checked = false;
}
// Show modal
document.getElementById('deleteConnectionModal').style.display = 'flex';
}
function closeDeleteConnectionModal() {
document.getElementById('deleteConnectionModal').style.display = 'none';
pendingDeletion = null;
}
async function confirmDeleteConnection() {
if (!pendingDeletion) return;
const { fromId, toId, hasReverseConnection, reverseDirection } = pendingDeletion;
const deleteBoth = document.getElementById('deleteBothConnections').checked;
try {
// Delete the main connection
const response = await fetch('/api/editor/connection', {
method: 'DELETE',
headers: {'Content-Type': 'application/json'},
@@ -876,14 +1080,36 @@ async function deleteConnection(fromId, toId) {
const data = await response.json();
if (data.success) {
showSuccess('Connection deleted!');
await loadConnections();
await selectLocation(fromId); // Refresh form
drawMap();
} else {
if (!data.success) {
alert('Failed to delete connection: ' + data.error);
return;
}
// Delete reverse connection if requested and exists
if (deleteBoth && hasReverseConnection) {
const reverseResponse = await fetch('/api/editor/connection', {
method: 'DELETE',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({from: toId, to: fromId})
});
const reverseData = await reverseResponse.json();
if (reverseData.success) {
showSuccess('Both connections deleted!');
} else {
showSuccess(`Connection deleted, but reverse failed: ${reverseData.error}`);
}
} else {
showSuccess('Connection deleted!');
}
// Refresh the view
await loadConnections();
await selectLocation(fromId); // Refresh form
drawMap();
closeDeleteConnectionModal();
} catch (error) {
alert('Failed to delete connection: ' + error.message);
}