feat: json format, et al.

This commit is contained in:
Subarashimo
2025-12-03 14:55:30 +01:00
parent 56349f30e6
commit 0f7fdfcef1
28 changed files with 5692 additions and 237 deletions
+79 -13
View File
@@ -10,6 +10,7 @@ import { buildUserStatsText } from '../rendering/userStats.js';
import { renderInventory, getLocationId } from '../rendering/inventory.js';
import { parseItems, serializeItems } from '../../utils/itemParser.js';
import { sanitizeLocationName, sanitizeItemName } from '../../utils/security.js';
import { handleItemRemoved, navigateToLinkedSkills } from '../rendering/skills.js';
// Type imports
/** @typedef {import('../../types/inventory.js').InventoryV2} InventoryV2 */
@@ -134,15 +135,20 @@ export function hideAddItemForm(field, location) {
export function saveAddItem(field, location) {
const inventory = extensionSettings.userStats.inventory;
let inputId;
let descInputId;
if (field === 'stored') {
inputId = `.rpg-location-item-input[data-location="${location}"]`;
descInputId = `.rpg-location-item-desc-input[data-location="${location}"]`;
} else {
inputId = `#rpg-new-item-${field}`;
descInputId = `#rpg-new-item-desc-${field}`;
}
const input = $(inputId);
const descInput = $(descInputId);
const rawItemName = input.val().trim();
const itemDescription = descInput?.val()?.trim() || '';
if (!rawItemName) {
hideAddItemForm(field, location);
@@ -157,10 +163,39 @@ export function saveAddItem(field, location) {
return;
}
// Get current items, add new one, serialize back
// Update structured inventory (inventoryV3) if it exists
if (extensionSettings.inventoryV3) {
const newItem = { name: itemName, description: itemDescription };
if (field === 'simplified') {
if (!extensionSettings.inventoryV3.simplified) {
extensionSettings.inventoryV3.simplified = [];
}
extensionSettings.inventoryV3.simplified.push(newItem);
} else if (field === 'stored') {
if (!extensionSettings.inventoryV3.stored) {
extensionSettings.inventoryV3.stored = {};
}
if (!extensionSettings.inventoryV3.stored[location]) {
extensionSettings.inventoryV3.stored[location] = [];
}
extensionSettings.inventoryV3.stored[location].push(newItem);
} else if (field === 'onPerson') {
if (!extensionSettings.inventoryV3.onPerson) {
extensionSettings.inventoryV3.onPerson = [];
}
extensionSettings.inventoryV3.onPerson.push(newItem);
} else if (field === 'assets') {
if (!extensionSettings.inventoryV3.assets) {
extensionSettings.inventoryV3.assets = [];
}
extensionSettings.inventoryV3.assets.push(newItem);
}
}
// Also update legacy inventory format for backwards compatibility
let currentString;
if (field === 'simplified') {
// For simplified inventory, use items field or fall back to onPerson
currentString = inventory.items || inventory.onPerson || 'None';
} else if (field === 'stored') {
currentString = inventory.stored[location] || 'None';
@@ -174,7 +209,6 @@ export function saveAddItem(field, location) {
// Save back to inventory
if (field === 'simplified') {
// Update both items and onPerson for simplified mode
inventory.items = newString;
inventory.onPerson = newString;
} else if (field === 'stored') {
@@ -201,13 +235,31 @@ export function saveAddItem(field, location) {
*/
export function removeItem(field, itemIndex, location) {
const inventory = extensionSettings.userStats.inventory;
let removedItemName = null;
// console.log('[RPG Companion] DEBUG removeItem called:', { field, itemIndex, location });
// Remove from structured inventory (inventoryV3) if it exists
if (extensionSettings.inventoryV3) {
let structuredArray = null;
if (field === 'simplified' && extensionSettings.inventoryV3.simplified) {
structuredArray = extensionSettings.inventoryV3.simplified;
} else if (field === 'stored' && extensionSettings.inventoryV3.stored?.[location]) {
structuredArray = extensionSettings.inventoryV3.stored[location];
} else if (field === 'onPerson' && extensionSettings.inventoryV3.onPerson) {
structuredArray = extensionSettings.inventoryV3.onPerson;
} else if (field === 'assets' && extensionSettings.inventoryV3.assets) {
structuredArray = extensionSettings.inventoryV3.assets;
}
if (structuredArray && structuredArray[itemIndex]) {
removedItemName = structuredArray[itemIndex].name;
structuredArray.splice(itemIndex, 1);
}
}
// Get current items, remove the one at index, serialize back
// Get current items from legacy format
let currentString;
if (field === 'simplified') {
// For simplified inventory, use items field or fall back to onPerson
currentString = inventory.items || inventory.onPerson || 'None';
} else if (field === 'stored') {
currentString = inventory.stored[location] || 'None';
@@ -215,20 +267,24 @@ export function removeItem(field, itemIndex, location) {
currentString = inventory[field] || 'None';
}
// console.log('[RPG Companion] DEBUG currentString before removal:', currentString);
const items = parseItems(currentString);
// console.log('[RPG Companion] DEBUG items array before removal:', items);
// Get the item name before removing (for item-skill link check) - use structured name if available
if (!removedItemName) {
removedItemName = items[itemIndex];
}
items.splice(itemIndex, 1); // Remove item at index
// console.log('[RPG Companion] DEBUG items array after removal:', items);
// Check if this item was linked to a skill and handle removal
if (removedItemName && extensionSettings.enableItemSkillLinks) {
handleItemRemoved(removedItemName);
}
const newString = serializeItems(items);
// console.log('[RPG Companion] DEBUG newString after removal:', newString);
// Save back to inventory
// Save back to legacy inventory
if (field === 'simplified') {
// Update both items and onPerson for simplified mode
inventory.items = newString;
inventory.onPerson = newString;
} else if (field === 'stored') {
@@ -487,6 +543,16 @@ export function initInventoryEventListeners() {
removeItem(field, itemIndex, location);
});
// Go to linked skills button (on inventory items)
$(document).on('click', '.rpg-item-skill-link[data-action="goto-linked-skills"]', function(e) {
e.preventDefault();
e.stopPropagation();
const itemName = $(this).data('item');
if (itemName) {
navigateToLinkedSkills(itemName);
}
});
// Add location button - shows inline form
$(document).on('click', '.rpg-inventory-add-btn[data-action="add-location"]', function(e) {
e.preventDefault();
+63 -4
View File
@@ -31,10 +31,36 @@ export function updateInventoryItem(field, index, newName, location) {
return;
}
// Get current items for the field
// Get the OLD item name before updating (for skill link updates)
let oldItemName = null;
if (extensionSettings.inventoryV3) {
let structuredArray = null;
if (field === 'simplified' && extensionSettings.inventoryV3.simplified) {
structuredArray = extensionSettings.inventoryV3.simplified;
} else if (field === 'stored' && extensionSettings.inventoryV3.stored?.[location]) {
structuredArray = extensionSettings.inventoryV3.stored[location];
} else if (field === 'onPerson' && extensionSettings.inventoryV3.onPerson) {
structuredArray = extensionSettings.inventoryV3.onPerson;
} else if (field === 'assets' && extensionSettings.inventoryV3.assets) {
structuredArray = extensionSettings.inventoryV3.assets;
}
if (structuredArray && structuredArray[index]) {
const item = structuredArray[index];
oldItemName = typeof item === 'string' ? item : item.name;
// Update the structured item
if (typeof item === 'object') {
item.name = sanitizedName;
} else {
structuredArray[index] = sanitizedName;
}
}
}
// Get current items for the legacy format
let currentString;
if (field === 'simplified') {
// For simplified inventory, use items field or fall back to onPerson
currentString = inventory.items || inventory.onPerson || 'None';
} else if (field === 'stored') {
if (!location) {
@@ -55,15 +81,19 @@ export function updateInventoryItem(field, index, newName, location) {
return;
}
// Get old name from legacy format if not found in structured format
if (!oldItemName) {
oldItemName = items[index];
}
// Update the item at this index
items[index] = sanitizedName;
// Serialize back to string
const newItemString = serializeItems(items);
// Update the inventory
// Update the legacy inventory
if (field === 'simplified') {
// Update both items and onPerson for simplified mode
inventory.items = newItemString;
inventory.onPerson = newItemString;
} else if (field === 'stored') {
@@ -72,6 +102,11 @@ export function updateInventoryItem(field, index, newName, location) {
inventory[field] = newItemString;
}
// Update skill links if the item name changed
if (oldItemName && oldItemName !== sanitizedName && extensionSettings.skillAbilityLinks) {
updateSkillLinksForRenamedItem(oldItemName, sanitizedName);
}
// Update lastGeneratedData and committedTrackerData with new inventory
updateLastGeneratedDataInventory();
@@ -84,6 +119,30 @@ export function updateInventoryItem(field, index, newName, location) {
renderInventory();
}
/**
* Updates skill-ability links when an inventory item is renamed
* @param {string} oldName - The old item name
* @param {string} newName - The new item name
*/
function updateSkillLinksForRenamedItem(oldName, newName) {
if (!extensionSettings.skillAbilityLinks) return;
const oldNameLower = oldName.toLowerCase().trim();
let updated = false;
for (const [key, linkedItem] of Object.entries(extensionSettings.skillAbilityLinks)) {
// Case-insensitive comparison to match the linking logic
if (linkedItem && linkedItem.toLowerCase().trim() === oldNameLower) {
extensionSettings.skillAbilityLinks[key] = newName;
updated = true;
}
}
if (updated) {
console.log(`[RPG Companion] Updated skill links: "${oldName}" -> "${newName}"`);
}
}
/**
* Updates lastGeneratedData.userStats AND committedTrackerData.userStats to include
* current inventory in text format.