diff --git a/actions/canvas_create_primitive_MOD.js b/actions/canvas_create_primitive_MOD.js index ebb0db46..eee55c92 100644 --- a/actions/canvas_create_primitive_MOD.js +++ b/actions/canvas_create_primitive_MOD.js @@ -11,13 +11,24 @@ module.exports = { subtitle(data) { const info = parseInt(data.info, 10); - if (info === 0) { - return data.color ? `Create Circle with Color ${data.color}` : 'No color circle has been created'; - } - if (info === 1) { - return data.color ? `Create Rectangle with Color ${data.color}` : 'No color rectangle has been created'; + switch (info) { + case 0: + return data.color ? `Create Circle with Color ${data.color}` : 'No color circle has been created'; + case 1: + return data.color ? `Create Rectangle with Color ${data.color}` : 'No color rectangle has been created'; + case 2: + return data.color ? `Create Triangle with Color ${data.color}` : 'No color triangle has been created'; + case 3: + return data.color ? `Create Hexagon with Color ${data.color}` : 'No color hexagon has been created'; + case 4: + return data.color ? `Create Pentagon with Color ${data.color}` : 'No color pentagon has been created'; + case 5: + return data.color ? `Create Ellipse with Color ${data.color}` : 'No color ellipse has been created'; + case 6: + return data.color ? `Create Star with Color ${data.color}` : 'No color star has been created'; + default: + return ''; } - // Add more cases for different shapes as needed }, variableStorage(data, varType) { @@ -35,12 +46,15 @@ module.exports = {

-
Width (px) @@ -52,7 +66,6 @@ module.exports = {


-
Color @@ -60,7 +73,6 @@ module.exports = {


- `; }, @@ -75,18 +87,93 @@ module.exports = { const ctx = canvas.getContext('2d'); const color = this.evalMessage(data.color, cache); + let sideLength; + let xCenter; + let yCenter; + let angle; + let x; + let y; + let angleStep; + let radius; + let centerX; + let centerY; + let numPoints; + let outerRadius; + let innerRadius; + switch (shapeType) { - case 0: // Circle + case 0: ctx.beginPath(); ctx.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI); ctx.fillStyle = color; ctx.fill(); break; - case 1: // Rectangle + case 1: ctx.fillStyle = color; ctx.fillRect(0, 0, width, height); break; - // Add more cases for different shapes + case 2: + ctx.beginPath(); + ctx.moveTo(width / 2, 0); + ctx.lineTo(width, height); + ctx.lineTo(0, height); + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); + break; + case 3: + ctx.beginPath(); + sideLength = Math.min(width, height) / 2; + xCenter = width / 2; + yCenter = height / 2; + for (let i = 0; i < 6; i++) { + angle = (Math.PI / 3) * i; + x = xCenter + sideLength * Math.cos(angle); + y = yCenter + sideLength * Math.sin(angle); + if (i === 0) { + ctx.moveTo(x, y); + } else { + ctx.lineTo(x, y); + } + } + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); + break; + case 4: + ctx.beginPath(); + angleStep = (2 * Math.PI) / 5; + radius = Math.min(width, height) / 2; + centerX = width / 2; + centerY = height / 2; + ctx.moveTo(centerX + radius * Math.cos(0), centerY + radius * Math.sin(0)); + for (let i = 1; i <= 5; i++) { + ctx.lineTo(centerX + radius * Math.cos(angleStep * i), centerY + radius * Math.sin(angleStep * i)); + } + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); + break; + case 5: + ctx.beginPath(); + ctx.ellipse(width / 2, height / 2, width / 2, height / 2, 0, 0, 2 * Math.PI); + ctx.fillStyle = color; + ctx.fill(); + break; + case 6: + numPoints = 5; + outerRadius = Math.min(width, height) / 2; + innerRadius = outerRadius * 0.5; + ctx.beginPath(); + for (let i = 0; i < numPoints * 2; i++) { + const radius = i % 2 === 0 ? outerRadius : innerRadius; + const angle = (i * Math.PI) / numPoints - Math.PI / 2; + ctx.lineTo(width / 2 + radius * Math.cos(angle), height / 2 + radius * Math.sin(angle)); + } + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); + break; default: break; } diff --git a/actions/json_random_MOD.js b/actions/json_random_MOD.js new file mode 100644 index 00000000..38587f8e --- /dev/null +++ b/actions/json_random_MOD.js @@ -0,0 +1,99 @@ +const fs = require('fs'); +const path = require('path'); + +module.exports = { + name: 'Pick Random JSON Item', + section: 'File Stuff', + fields: ['filepath', 'title', 'storage', 'varName'], + + subtitle(data) { + return `Pick random item from JSON file "${data.filepath}"`; + }, + + variableStorage(data, varType) { + if (parseInt(data.storage, 10) !== varType) return; + return [data.varName, 'Text']; + }, + + html() { + return ` +
+
+ File Path + +
+
+ Title + +
+
+ +
+
+ `; + }, + + init() {}, + + async action(cache) { + const data = cache.actions[cache.index]; + let filepath = this.evalMessage(data.filepath, cache); + const title = this.evalMessage(data.title, cache); + const storage = parseInt(data.storage, 10); + const varName = this.evalMessage(data.varName, cache); + + if (filepath.startsWith('./')) { + filepath = path.join(__dirname, '..', filepath.substring(2)); + } + + let jsonData; + + try { + if (fs.existsSync(filepath)) { + const fileData = fs.readFileSync(filepath); + if (fileData.length === 0) { + console.warn('JSON file is empty.'); + this.storeValue(undefined, storage, varName, cache); + return this.callNextAction(cache); + } + jsonData = JSON.parse(fileData); + } else { + throw new Error('File does not exist'); + } + } catch (error) { + console.error(`Error reading JSON file: ${error}`); + this.storeValue(undefined, storage, varName, cache); + return this.callNextAction(cache); + } + + let result; + + try { + if (title) { + const titleData = jsonData.find((item) => item.Title === title); + if (!titleData) throw new Error('Title not found'); + + const keys = Object.keys(titleData).filter((key) => key !== 'Title'); + if (keys.length === 0) throw new Error('No items found under specified title'); + + const randomKey = keys[Math.floor(Math.random() * keys.length)]; + result = randomKey; + } else { + const items = jsonData.flatMap((item) => Object.keys(item).filter((key) => key !== 'Title')); + if (items.length === 0) throw new Error('No items found in JSON'); + + const randomItem = items[Math.floor(Math.random() * items.length)]; + result = randomItem; + } + } catch (error) { + console.error(`Error accessing data: ${error}`); + this.storeValue(undefined, storage, varName, cache); + return this.callNextAction(cache); + } + + this.storeValue(result, storage, varName, cache); + this.callNextAction(cache); + }, + + mod() {}, +}; diff --git a/actions/json_read_MOD.js b/actions/json_read_MOD.js new file mode 100644 index 00000000..dd85f0f0 --- /dev/null +++ b/actions/json_read_MOD.js @@ -0,0 +1,102 @@ +const fs = require('fs'); +const path = require('path'); + +module.exports = { + name: 'Read JSON File', + section: 'File Stuff', + fields: ['filepath', 'title', 'contentTitle', 'storage', 'varName'], + + subtitle(data) { + return `Read JSON file "${data.filepath}"`; + }, + + variableStorage(data, varType) { + if (parseInt(data.storage, 10) !== varType) return; + return [data.varName, 'Unknown']; + }, + + html() { + return ` +
+
+ File Path + +
+
+ Title + +
+
+ Content Title + +
+
+ +
+
+ `; + }, + + init() {}, + + async action(cache) { + const data = cache.actions[cache.index]; + let filepath = this.evalMessage(data.filepath, cache); + const title = this.evalMessage(data.title, cache); + const contentTitle = this.evalMessage(data.contentTitle, cache); + const storage = parseInt(data.storage, 10); + const varName = this.evalMessage(data.varName, cache); + + if (filepath.startsWith('./')) { + filepath = path.join(__dirname, '..', filepath.substring(2)); + } + + let jsonData; + + try { + if (fs.existsSync(filepath)) { + const fileData = fs.readFileSync(filepath); + if (fileData.length === 0) { + console.warn('JSON file is empty.'); + this.storeValue(undefined, storage, varName, cache); + return this.callNextAction(cache); + } + jsonData = JSON.parse(fileData); + } else { + throw new Error('File does not exist'); + } + } catch (error) { + console.error(`Error reading JSON file: ${error}`); + this.storeValue(undefined, storage, varName, cache); + return this.callNextAction(cache); + } + + let result; + try { + const titleData = jsonData.find((item) => item.Title === title); + if (!titleData) throw new Error('Title not found'); + + if (contentTitle.includes('/')) { + const contentKeys = contentTitle.split('/'); + result = {}; + for (const key of contentKeys) { + if (titleData[key] !== undefined) { + result[key] = titleData[key]; + } + } + } else { + if (titleData[contentTitle] === undefined) throw new Error('Content Title not found'); + result = titleData[contentTitle]; + } + } catch (error) { + console.error(`Error accessing data: ${error}`); + this.storeValue(undefined, storage, varName, cache); + return this.callNextAction(cache); + } + + this.storeValue(result, storage, varName, cache); + this.callNextAction(cache); + }, + + mod() {}, +}; diff --git a/actions/json_write_MOD.js b/actions/json_write_MOD.js new file mode 100644 index 00000000..682462b5 --- /dev/null +++ b/actions/json_write_MOD.js @@ -0,0 +1,187 @@ +const fs = require('fs'); +const path = require('path'); + +module.exports = { + name: 'JSON File Control', + section: 'File Stuff', + fields: ['filepath', 'action', 'title', 'contentTitle', 'contentText', 'newTitle', 'oldTitle', 'deleteContentTitle'], + meta: { + version: '2.1.7', + preciseCheck: false, + author: 'DBM Mods', + authorUrl: 'https://github.com/dbm-network/mods', + }, + + subtitle(data) { + return `Perform JSON operations on ${data.filepath}`; + }, + + html() { + return ` +
+
+ File Path + +
+
+ Action + +
+
+ Title + +
+ + + +
+ `; + }, + + init() { + const { glob, document } = this; + + glob.onChangeAction = function onChangeAction(event) { + const value = event.value; + document.getElementById('titleSection').style.display = + value === 'addTitle' || value === 'addContent' || value === 'renameContent' ? 'block' : 'none'; + document.getElementById('contentSection').style.display = value === 'addContent' ? 'block' : 'none'; + document.getElementById('renameSection').style.display = + value === 'renameContent' || value === 'renameTitle' ? 'block' : 'none'; + document.getElementById('deleteSection').style.display = value === 'deleteContent' ? 'block' : 'none'; + }; + + glob.onChangeAction(document.getElementById('action')); + }, + + async action(cache) { + const data = cache.actions[cache.index]; + let filepath = this.evalMessage(data.filepath, cache); + + if (filepath.startsWith('./')) { + filepath = path.join(__dirname, '..', filepath.substring(2)); + } + + const action = data.action; + const title = this.evalMessage(data.title, cache); + const contentTitle = this.evalMessage(data.contentTitle, cache); + const contentText = this.evalMessage(data.contentText, cache); + const oldTitle = this.evalMessage(data.oldTitle, cache); + const newTitle = this.evalMessage(data.newTitle, cache); + const deleteContentTitle = this.evalMessage(data.deleteContentTitle, cache); + + // Load JSON file + let jsonData; + try { + if (fs.existsSync(filepath)) { + const fileData = fs.readFileSync(filepath); + jsonData = JSON.parse(fileData); + } else { + jsonData = []; + } + } catch (error) { + console.error(`Error reading JSON file: ${error}`); + jsonData = []; + } + + let target; + + switch (action) { + case 'addTitle': + if (title) { + jsonData.push({ Title: title }); + } + break; + case 'addContent': + target = jsonData.find((item) => item.Title === title); + if (!target) { + target = { Title: title }; + jsonData.push(target); + } + if (contentTitle.includes('/')) { + const keys = contentTitle.split('/'); + keys.reduce(function addNestedContent(obj, key, index) { + if (index === keys.length - 1) { + obj[key] = isNaN(contentText) ? contentText : parseFloat(contentText); + } else { + obj[key] = obj[key] || {}; + } + return obj[key]; + }, target); + } else { + target[contentTitle] = isNaN(contentText) ? contentText : parseFloat(contentText); + } + break; + case 'renameContent': + jsonData.forEach((item) => { + if (item.Title === title && item[contentTitle]) { + item[newTitle] = item[contentTitle]; + delete item[contentTitle]; + } + }); + break; + case 'renameTitle': + jsonData.forEach((item) => { + if (item.Title === oldTitle) { + item.Title = newTitle; + } + }); + break; + case 'deleteContent': + jsonData.forEach((item) => { + if (item.Title === title) { + if (deleteContentTitle.includes('/')) { + const keys = deleteContentTitle.split('/'); + keys.reduce(function deleteNestedContent(obj, key, index) { + if (index === keys.length - 1) { + delete obj[key]; + } else { + return obj[key]; + } + return obj; + }, item); + } else { + delete item[deleteContentTitle]; + } + } + }); + break; + case 'deleteTitle': + jsonData = jsonData.filter((item) => item.Title !== title); + break; + } + + // Save JSON file + try { + fs.writeFileSync(filepath, JSON.stringify(jsonData, null, 2)); + } catch (error) { + console.error(`Error writing JSON file: ${error}`); + } + + this.callNextAction(cache); + }, + + mod() {}, +};