Greasy Fork镜像 还支持 简体中文。

Dreadcast Script Manager

Centralize all dreadcast scripts in one single source, integrated to the game.

目前為 2024-09-12 提交的版本,檢視 最新版本

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

QingJ © 2025

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