Module:GameData/doc: Difference between revisions

Update code: Validate user has all expansion content available and handle ordered objects in Township skill data
(Fix for item names sometimes containing underscores)
(Update code: Validate user has all expansion content available and handle ordered objects in Township skill data)
Line 8: Line 8:


{{SpoilerBox|color=default|title=Code|text=<pre>// TODO:
{{SpoilerBox|color=default|title=Code|text=<pre>// TODO:
// Special attack description generation
// Handle modifications portion of data packages
// Handle modifications portion of data packages
// Use actual descriptions as per language data
class Wiki {
class Wiki {
     constructor() {
     constructor() {
        this.getLocalID = this.getLocalID.bind(this);
         this.namespaces = {
         this.namespaces = {
             melvorD: { displayName: "Demo", url: "https://melvoridle.com/assets/data/melvorDemo.json" },
             melvorD: { displayName: "Demo", url: "https://" + location.hostname + "/assets/data/melvorDemo.json" },
             melvorF: { displayName: "Full Version", url: "https://melvoridle.com/assets/data/melvorFull.json" },
             melvorF: { displayName: "Full Version", url: "https://" + location.hostname + "/assets/data/melvorFull.json" },
             melvorTotH: { displayName: "Throne of the Herald", url: "https://melvoridle.com/assets/data/melvorTotH.json" }
             melvorTotH: { displayName: "Throne of the Herald", url: "https://" + location.hostname + "/assets/data/melvorTotH.json" }
         };
         };
        // Check all required namespaces are registered, as there are still some bits of data extracted from in-game rather than the data packages
        Object.keys(this.namespaces).forEach((nsID) => {
            const nsTest = game.registeredNamespaces.getNamespace(nsID);
            if (nsTest === undefined) {
                throw new Error(`Namespace ${ nsID } (${ this.namespaces[nsID].displayName }) is not registered - Ensure you are signed in and have the expansion.`);
            }
        });
         this.packData = {};
         this.packData = {};
         this.gameData = {};
         this.gameData = {};
Line 446: Line 453:
                     // Elements are inserted at a particular index, controlled by rules
                     // Elements are inserted at a particular index, controlled by rules
                     // specified within the data package
                     // specified within the data package
                    if (this.gameData[categoryName] === undefined) {
this.gameData[categoryName] = this.combineOrderedData(this.gameData[categoryName], categoryData);
                        this.gameData[categoryName] = [];
                    }
                    categoryData.forEach((orderData) => {
                        switch(orderData.insertAt) {
                            case 'Start':
                                this.gameData[categoryName].splice(0, 0, ...orderData.ids);
                                break;
                            case 'End':
                                this.gameData[categoryName].push(...orderData.ids);
                                break;
                            case 'Before':
                                const beforeIdx = this.gameData[categoryName].findIndex((item) => item === orderData.beforeID);
                                if (beforeIdx === -1) {
                                    throw new Error(`Couldn't insert before in category ${ categoryName }: Item ${ orderData.beforeID } is not in the array.`);
                                }
                                this.gameData[categoryName].splice(beforeIndex, 0, ...orderData.ids);
                                break;
                            case 'After':
                                const afterIdx = this.gameData[categoryName].findIndex((item) => item === orderData.afterID);
                                if (afterIdx === -1) {
                                    throw new Error(`Couldn't insert after in category ${ categoryName }: Item ${ orderData.afterID } is not in the array.`);
                                }
                                this.gameData[categoryName].splice(afterIdx + 1, 0, ...orderData.ids);
                                break;
                        }
                    });
                     break;
                     break;
                 case 'golbinRaid':
                 case 'golbinRaid':
Line 496: Line 477:
                     // Contains nested objects
                     // Contains nested objects
                     if (this.gameData[categoryName] === undefined) {
                     if (this.gameData[categoryName] === undefined) {
                         this.gameData[categoryName] = categoryData;
                         this.gameData[categoryName] = [];
                    }
                    else {
                        // Find the appropriate skill object and combine properties with that
                        categoryData.forEach((skillData) => {
                            const skillIdx = this.gameData[categoryName].findIndex((skill) => skill.skillID === skillData.skillID);
                            if (skillIdx === -1) {
                                this.gameData[categoryName].push(skillData);
                            }
                            else {
                                const skillObj = this.gameData[categoryName][skillIdx].data;
                                Object.keys(skillData.data).forEach((dataKey) => {
                                    if ((skillObj[dataKey] === undefined) || !Array.isArray(skillObj[dataKey])) {
                                        // Property is undefined or isn't an array
                                        skillObj[dataKey] = skillData.data[dataKey];
                                    }
                                    else {
                                        // Property is an array
                                        skillObj[dataKey].push(...skillData.data[dataKey]);
                                    }
                                });
                            }
                        });
                     }
                     }
// Find the appropriate skill object and combine properties with that
categoryData.forEach((skillData) => {
var skillIdx = this.gameData[categoryName].findIndex((skill) => skill.skillID === skillData.skillID);
if (skillIdx === -1) {
// Initialize skill
const initData = structuredClone(skillData);
initData.data = {};
this.gameData[categoryName].push(initData);
skillIdx = this.gameData[categoryName].findIndex((skill) => skill.skillID === skillData.skillID);
}
const skillObj = this.gameData[categoryName][skillIdx].data;
Object.keys(skillData.data).forEach((dataKey) => {
if (Array.isArray(skillData.data[dataKey]) && skillData.data[dataKey].length > 0 && skillData.data[dataKey][0].insertAt !== undefined) {
//Data is ordered, special handling applies
skillObj[dataKey] = this.combineOrderedData(skillObj[dataKey], skillData.data[dataKey]);
}
else if ((skillObj[dataKey] === undefined) || !Array.isArray(skillObj[dataKey])) {
// Property is undefined or isn't an array
skillObj[dataKey] = skillData.data[dataKey];
}
else {
// Property is an array
skillObj[dataKey].push(...skillData.data[dataKey]);
}
});
});
                     break;
                     break;
                 default:
                 default:
Line 568: Line 553:
         }
         }
     }
     }
combineOrderedData(existingData, newData) {
// Elements are inserted at a particular index, controlled by rules
// specified within the data package
var resultData = undefined;
if (existingData === undefined) {
resultData = [];
}
else {
resultData = structuredClone(existingData);
}
newData.forEach((orderData) => {
switch(orderData.insertAt) {
case 'Start':
resultData.splice(0, 0, ...orderData.ids);
break;
case 'End':
resultData.push(...orderData.ids);
break;
case 'Before':
const beforeIdx = resultData.findIndex((item) => item === orderData.beforeID);
if (beforeIdx === -1) {
throw new Error(`Couldn't insert before: Item ${ orderData.beforeID } is not in the array.`);
}
resultData.splice(beforeIndex, 0, ...orderData.ids);
break;
case 'After':
const afterIdx = resultData.findIndex((item) => item === orderData.afterID);
if (afterIdx === -1) {
throw new Error(`Couldn't insert after: Item ${ orderData.afterID } is not in the array.`);
}
resultData.splice(afterIdx + 1, 0, ...orderData.ids);
break;
}
});
return resultData;
}
     getNamespacedID(namespace, ID) {
     getNamespacedID(namespace, ID) {
         if (ID.indexOf(':') > 0) {
         if (ID.indexOf(':') > 0) {