Dreadcast Script Manager

13/11/2023 02:55:01

当前为 2024-09-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Dreadcast Script Manager
  3. // @namespace Violentmonkey Scripts
  4. // @match https://www.dreadcast.net/Main
  5. // @match https://www.dreadcast.net/Forum
  6. // @match https://www.dreadcast.net/Forum/*
  7. // @match https://www.dreadcast.net/EDC
  8. // @match https://www.dreadcast.net/EDC/*
  9. // @version 1.0.1
  10. // @author Pelagia/Isilin
  11. // @description 13/11/2023 02:55:01
  12. // @license http://creativecommons.org/licenses/by-nc-nd/4.0/
  13. // @require https://update.gf.qytechs.cn/scripts/507382/Dreadcast%20Development%20Kit.user.js
  14. // @grant GM_setValue
  15. // @grant GM_getValue
  16. // @grant GM_deleteValue
  17. // @grant GM_listValues
  18. // @grant GM_xmlhttpRequest
  19. // @grant GM_addStyle
  20. // @connect docs.google.com
  21. // @connect googleusercontent.com
  22. // @connect sheets.googleapis.com
  23. // @connect raw.githubusercontent.com
  24. // ==/UserScript==
  25.  
  26. // TODO ajouter dans la liste tous les scripts (en utilisant le lien greasemonkey) et remplacer petit à petit par les versions locales nettoyées.
  27. // TODO add function to export, import settings, and to reset all settings.
  28. // TODO add text to say that disabling a script does not remove settings.
  29.  
  30. const LIST_TAG = 'dcm_list';
  31. const ALL_DISABLED_TAG = 'dcm_all_disabled';
  32.  
  33. let newSettings, newAllDisabled;
  34.  
  35. const initPersistence = () => {
  36. // Init persistent memory if needed.
  37. DC.LocalMemory.init(LIST_TAG, {});
  38. DC.LocalMemory.init(ALL_DISABLED_TAG, false);
  39.  
  40. // Load the current settings.
  41. let settings = DC.LocalMemory.get(LIST_TAG);
  42. let allDisabled = DC.LocalMemory.get(ALL_DISABLED_TAG);
  43.  
  44. return { settings, allDisabled };
  45. };
  46.  
  47. const synchronizeSettings = (settings, scripts) => {
  48. let tmp = settings;
  49.  
  50. scripts.forEach((script) => {
  51. if (!Object.hasOwn(tmp, script.id)) {
  52. // Update the settings, if there is new scripts.
  53. tmp[script.id] = false;
  54. }
  55. });
  56.  
  57. // Remove in settings, scripts that doesn't exist anymore.
  58. tmp = Object.keys(tmp)
  59. .filter((key) => scripts.find((script) => script.id === key) !== undefined)
  60. .reduce((obj, key) => {
  61. obj[key] = tmp[key];
  62. return obj;
  63. }, {});
  64.  
  65. // Save the new settings in persistent memory.
  66. DC.LocalMemory.set(LIST_TAG, tmp);
  67.  
  68. return tmp;
  69. };
  70.  
  71. const createScriptLine = (script, index) => {
  72. const line = $(`
  73. <tr style="border-top: 1px solid white; border-left: 1px solid white; border-right: 1px solid white;">
  74. <td style="padding: 5px 0 0 5px" rowspan="2">${index}</td>
  75. ${
  76. script.icon && script.icon !== ''
  77. ? `<td style="padding: 5px" rowspan="2"><img src="${script.icon}" width="48" height="48" /></td>`
  78. : '<td class="short" style="width: 58px;" rowspan="2" />'
  79. }
  80. <td style="padding: 5px 0; min-width: 120px; text-align: left;">${
  81. script.name || ''
  82. }</td>
  83. <td style="padding: 5px 0; min-width: 120px; text-align: left;"><small>${
  84. script.authors || ''
  85. }</small></td>
  86. <td class="enabled_cell" style="padding: 5px 0; display: flex; justify-content: center;"></td>
  87. <td class="setting_cell" style="padding: 5px 5px 0 0;"></td>
  88. <td class="doc_cell" style="padding: 5px 5px 0 0;"></td>
  89. <td class="rp_cell" style="padding: 5px 5px 0 0;"></td>
  90. <td class="contact_cell" style="padding: 5px 5px 0 0;"></td>
  91. </tr>
  92. <tr style="border-bottom: 1px solid white; border-left: 1px solid white; border-right: 1px solid white;">
  93. <td colspan="7" style="padding: 0 5px 5px 5px; text-align: left;"><small><em class="couleur5">${
  94. script.description || ''
  95. }</em></small></td>
  96. </tr>
  97. `);
  98. $('.enabled_cell', line).append(
  99. DC.UI.Checkbox(
  100. `${script.id}_check`,
  101. newSettings[script.id],
  102. () => (newSettings[script.id] = !newSettings[script.id]),
  103. ),
  104. );
  105. if (script.settings) {
  106. $('.setting_cell', line).append(
  107. DC.UI.Tooltip(
  108. 'Settings',
  109. DC.UI.Button(
  110. `${script.id}_setting`,
  111. '<i class="fas fa-cog"></i>',
  112. () => {},
  113. ),
  114. ),
  115. );
  116. }
  117. if (script.doc && script.doc !== '') {
  118. $('.doc_cell', line).append(
  119. DC.UI.Tooltip(
  120. 'Documentation',
  121. DC.UI.Button(`${script.id}_doc`, '<i class="fas fa-book"></i>', () =>
  122. window.open(script.doc, '_blank'),
  123. ),
  124. ),
  125. );
  126. }
  127. if (script.rp && script.rp !== '') {
  128. $('.rp_cell', line).append(
  129. DC.UI.Tooltip(
  130. 'Topic RP',
  131. DC.UI.Button(
  132. `${script.id}_rp`,
  133. '<div class=""gridCenter>RP</div>',
  134. () => window.open(script.doc, '_blank'),
  135. ),
  136. ),
  137. );
  138. }
  139. if (script.contact && script.contact !== '') {
  140. $('.contact_cell', line).append(
  141. DC.UI.Tooltip(
  142. 'Contact',
  143. DC.UI.Button(`${script.id}_rp`, '<i class="fas fa-envelope"></i>', () =>
  144. nav.getMessagerie().newMessage(script.contact),
  145. ),
  146. ),
  147. );
  148. }
  149.  
  150. return line;
  151. };
  152.  
  153. $(() => {
  154. let { settings, allDisabled } = initPersistence();
  155.  
  156. const createUI = (scripts, settings) => {
  157. DC.UI.addSubMenuTo(
  158. 'Paramètres ▾',
  159. DC.UI.SubMenu(
  160. 'Scripts & Skins',
  161. () => {
  162. // On récupère une config temporaire qu'on appliquera uniquement si sauvegardée.
  163. newSettings = settings;
  164. newAllDisabled = allDisabled;
  165.  
  166. const sections = [
  167. { id: 'all', label: 'Tous' },
  168. { id: 'game', label: 'Jeu' },
  169. { id: 'forum', label: 'Forum' },
  170. { id: 'edc', label: 'EDC' },
  171. ];
  172.  
  173. const categories = [
  174. { id: 'all', label: 'Tous' },
  175. { id: 'mailing', label: 'Messagerie' },
  176. { id: 'chat', label: 'Chat' },
  177. { id: 'silhouette', label: 'Silhouette' },
  178. { id: 'ui', label: 'UI' },
  179. { id: 'mech', label: 'Mécaniques' },
  180. { id: 'fix', label: 'Correctifs' },
  181. { id: 'misc', label: 'Autres' },
  182. ];
  183.  
  184. const content = $(`<div style="color: white;">
  185. <div id="scripts_all_switch" style="display: flex;gap: 1rem;margin-bottom: 1rem;">
  186. <p>Tout désactiver</p>
  187. </div>
  188. <div style="display: flex; gap: 1rem; margin-bottom: 1rem;">
  189. <legend style="margin-right: 1rem; min-width: 60px;">Filtrer :</legend>
  190. <div style="display: flex; gap: 5%; flex-wrap: wrap; width: 100%;">
  191. ${sections
  192. .map(
  193. (section, index) => `
  194. <div>
  195. <input type="radio" id="${
  196. section.id
  197. }_section" name ="section" value ="${section.id}" ${
  198. index === 0 ? 'checked' : ''
  199. } />
  200. <label for="${section.id}_section">${
  201. section.label
  202. }</label>
  203. </div>
  204. `,
  205. )
  206. .join('')}
  207. </div>
  208. </div>
  209. <div style="display: flex; gap: 1rem; margin-bottom: 1rem;">
  210. <legend style="margin-right: 1rem; min-width: 60px;">Filtrer :</legend>
  211. <div style="display: flex; gap: 5%; flex-wrap: wrap; width: 100%;">
  212. ${categories
  213. .map(
  214. (category, index) => `
  215. <div>
  216. <input type="radio" id="${
  217. category.id
  218. }_category" name ="category" value ="${category.id}" ${
  219. index === 0 ? 'checked' : ''
  220. } />
  221. <label for="${category.id}_category">${
  222. category.label
  223. }</label>
  224. </div>
  225. `,
  226. )
  227. .join('')}
  228. </div>
  229. </div>
  230. <table style="border-collapse: collapse; width: 100%; border: 1px solid white; padding: 5px; font-size: 15px; text-align: center;">
  231. <thead>
  232. <th style="padding: 5px 0 5px 5px" scope="col">#</th>
  233. <th class="short" style="width:58px;" />
  234. <th style="padding: 5px 0 5px 0" scope="col">Nom</th>
  235. <th style="padding: 5px 0 5px 0" scope="col">Auteurs</th>
  236. <th style="padding: 5px 0 5px 0" scope="col">Actif</th>
  237. <th class="short" style="width: 40px;" />
  238. <th class="short" style="width: 40px;" />
  239. <th class="short" style="width: 40px;" />
  240. <th class="short" style="width: 40px;" />
  241. </thead>
  242. <tbody></tbody>
  243. </table>
  244. </div>`);
  245.  
  246. $(document).on('change', "input[name='category']", (e) => {
  247. const category = e.target.value;
  248. const section = $("input[name='section']:checked").val();
  249.  
  250. // Empty the table
  251. $('tbody', content).empty();
  252. // Add filtered lines
  253. scripts
  254. .filter(
  255. (script) =>
  256. (script.section.includes(section) || section === 'all') &&
  257. (script.category.includes(category) || category === 'all'),
  258. )
  259. .forEach((script, index) => {
  260. const line = createScriptLine(script, index);
  261. $('tbody', content).append(line);
  262. });
  263. });
  264.  
  265. $(document).on('change', "input[name='section']", (e) => {
  266. const section = e.target.value;
  267. const category = $("input[name='category']:checked").val();
  268.  
  269. // Empty the table
  270. $('tbody', content).empty();
  271. // Add filtered lines
  272. scripts
  273. .filter(
  274. (script) =>
  275. (script.section.includes(section) || section === 'all') &&
  276. (script.category.includes(category) || category === 'all'),
  277. )
  278. .forEach((script, index) => {
  279. const line = createScriptLine(script, index);
  280. $('tbody', content).append(line);
  281. });
  282. });
  283.  
  284. // Sauvegarder les paramètres.
  285. content.append(
  286. DC.UI.TextButton('scripts_refresh', 'Sauvegarder', () => {
  287. settings = newSettings;
  288. allDisabled = newAllDisabled;
  289. DC.LocalMemory.set(LIST_TAG, settings);
  290. DC.LocalMemory.set(ALL_DISABLED_TAG, allDisabled);
  291. location.reload();
  292. }),
  293. );
  294. content.append(
  295. $(
  296. `<p><em class="couleur5">⚠ Sauvegarder votre configuration va raffraichir la page.<br />
  297. Pensez à sauvegarder votre travail en cours avant.</em></p>`,
  298. ),
  299. );
  300.  
  301. // Switch button pour désactiver tous les scripts.
  302. $('#scripts_all_switch', content).append(
  303. DC.UI.Checkbox(
  304. 'scripts_all_check',
  305. newAllDisabled,
  306. () => (newAllDisabled = !newAllDisabled),
  307. ),
  308. );
  309.  
  310. scripts.forEach((script, index) => {
  311. const line = createScriptLine(script, index);
  312. $('tbody', content).append(line);
  313. });
  314.  
  315. return DC.UI.PopUp('scripts_modal', 'Scripts & Skins', content);
  316. },
  317. true,
  318. ),
  319. 5,
  320. );
  321. };
  322.  
  323. // Load list of scripts
  324. DC.Network.loadJson(
  325. 'https://raw.githubusercontent.com/Isilin/dreadcast-scripts/main/data/scripts.json',
  326. )
  327. .then((scripts) => {
  328. settings = synchronizeSettings(settings, scripts);
  329.  
  330. // Create the interface.
  331. if (Util.isGame()) {
  332. createUI(scripts, settings);
  333. }
  334.  
  335. // Load the scripts
  336. if (!allDisabled) {
  337. const context = Util.getContext();
  338.  
  339. scripts
  340. .filter((script) => script.section.includes(context))
  341. .forEach((script) => {
  342. if (settings[script.id]) {
  343. DC.Network.loadScript(script.url)
  344. .then(() => {
  345. console.info(
  346. `DCSM - '${script.name}' script has been loaded successfully.`,
  347. );
  348. })
  349. .catch((err) => {
  350. console.error(
  351. `DCSM - Error loading '${script.name}' script: ` + err,
  352. );
  353. });
  354. }
  355. });
  356. }
  357. })
  358. .catch((err) => {
  359. console.error('DCSM - Error loading the list of scripts :' + err);
  360. });
  361. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址