diff --git a/README.md b/README.md deleted file mode 100644 index af5626b..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -Hello, world! diff --git a/index.html b/index.html new file mode 100644 index 0000000..89eec2c --- /dev/null +++ b/index.html @@ -0,0 +1,123 @@ + + + + + + + Architectury Template Generator + + + + +

Architectury Template Generator

+ +
+
+ Mod properties + +

Mod name

+ + + +

Mod ID (optional)

+ + + +

Package name

+ + + +

+ + +

Mappings

+ The set of names used for Minecraft code. +
+ + +
+
+ + +
+
+ +
+
+ Mod loaders + +

Project type

+
+ +
+ +
+

Subprojects

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+

Additional subprojects

+
+ + +
+
+
+ +

Dependencies

+
+ + +
+
+
+ +
+ Generate + + + +
+
+
+ + + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..50b5dcd --- /dev/null +++ b/script.js @@ -0,0 +1,182 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import init, { create_state, generate, is_valid_mod_id, list_all_minecraft_versions, supports_neoforge, to_mod_id, validate_mod_id } from "./templateer.js"; +await init(); + +const state = create_state(); + +// Set up Minecraft version dropdown with contents +const mcSelect = document.getElementById("minecraft-version-select"); +mcSelect.onchange = refreshAvailablePlatforms; + +for (const version of list_all_minecraft_versions().reverse()) { + const option = document.createElement("option"); + option.textContent = version; + mcSelect.appendChild(option); +} + +// Hide multiplatform settings when deselected +const projectTypeToggles = document.getElementById("project-type-toggles").getElementsByTagName("input"); +const multiplatformInput = document.getElementById("multiplatform-input"); +const multiplatformSettings = document.getElementById("multiplatform-settings"); + +for (const input of projectTypeToggles) { + input.onchange = refreshDisplayedProjectType; +}; + +// Add listeners to Fabric and Quilt checkboxes for controlling the Fabric-like checkbox, +// and refresh the Fabric-like status according to the default state. +document.getElementById("fabric-loader-input").onchange = refreshFabricLikeCheckbox; +document.getElementById("quilt-loader-input").onchange = refreshFabricLikeCheckbox; +refreshFabricLikeCheckbox(); + +// Add generated mod id placeholder when not specified manually +const modNameInput = document.getElementById("mod-name-input"); +const modIdInput = document.getElementById("mod-id-input"); + +modNameInput.oninput = () => { + refreshModIdPlaceholder(); + validateModId(); +}; + +function refreshModIdPlaceholder() { + modIdInput.placeholder = to_mod_id(modNameInput.value) ?? ""; +} + +// Validate mod ids +const modIdLabel = document.getElementById("mod-id-label"); +modIdInput.oninput = validateModId; + +function validateModId() { + const validation = validate_mod_id(getModId()); + + if (validation[0]) { + modIdLabel.removeAttribute("error"); + } else { + modIdLabel.setAttribute("error", validation[1]); + } +} + +function isModIdValid() { + return is_valid_mod_id(getModId()); +} + +function getModId() { + let value = modIdInput.value; + if (value === "") { + value = modIdInput.placeholder; + } + return value; +} + +function getProjectType() { + for (const input of projectTypeToggles) { + if (input.checked) { + return input.getAttribute("projecttype"); + } + } +} + +function getMappingSet() { + for (const input of document.getElementsByTagName("input")) { + if (input.name !== "mappings") continue; + if (input.checked) { + return input.getAttribute("mappingset"); + } + } +} + +function updateState() { + state.mod_name = modNameInput.value; + state.mod_id = getModId(); + state.package_name = document.getElementById("package-input").value; + state.game_version = mcSelect.value; + state.project_type = getProjectType(); + state.mapping_set = getMappingSet(); + state.subprojects.fabric = document.getElementById("fabric-loader-input").checked; + state.subprojects.forge = document.getElementById("forge-loader-input").checked; + state.subprojects.neoforge = document.getElementById("neoforge-loader-input").checked && isNeoForgeAvailable(); + state.subprojects.quilt = document.getElementById("quilt-loader-input").checked; + state.subprojects.fabric_likes = document.getElementById("fabric-like-input").checked && isFabricLikeAvailable(); + state.dependencies.architectury_api = document.getElementById("architectury-api-input").checked; +} + +function showError(error) { + let container = document.getElementById("error-message-container"); + container.textContent = error; + container.classList.remove("hidden"); +} + +function clearError() { + let container = document.getElementById("error-message-container"); + container.textContent = ""; + container.classList.add("hidden"); +} + +function refreshDisplayedProjectType() { + if (multiplatformInput.checked) { + multiplatformSettings.classList.remove("hidden"); + } else { + multiplatformSettings.classList.add("hidden"); + } +} + +function isFabricLikeAvailable() { + const fabricInput = document.getElementById("fabric-loader-input"); + const quiltInput = document.getElementById("quilt-loader-input"); + return fabricInput.checked && quiltInput.checked; +} + +function isNeoForgeAvailable() { + const version = mcSelect.value; + return supports_neoforge(version); +} + +function refreshAvailablePlatforms() { + const hasNeoForge = isNeoForgeAvailable(); + const neoForgeProjectInput = document.getElementById("neoforge-project-input"); + const neoForgeLoaderInput = document.getElementById("neoforge-loader-input"); + neoForgeProjectInput.disabled = !hasNeoForge; + neoForgeLoaderInput.disabled = !hasNeoForge; + + // Change project type if Neo is not available. + if (!hasNeoForge && neoForgeProjectInput.checked) { + multiplatformInput.checked = true; + neoForgeProjectInput.checked = false; + refreshDisplayedProjectType(); + } +} + +// Enables/disables the Fabric-like checkbox based on whether it can be selected for the current state. +function refreshFabricLikeCheckbox() { + const hasFabricLike = isFabricLikeAvailable(); + const fabricLikeInput = document.getElementById("fabric-like-input"); + fabricLikeInput.disabled = !hasFabricLike; +} + +document.getElementById("generate-button").onclick = async () => { + updateState(); + + if (state.mod_name === "") { + showError("Mod name is empty"); + return; + } else if (!isModIdValid()) { + showError("Mod ID is not valid"); + return; + } else if (state.package_name === "") { + showError("Package name is empty"); + return; + } + + clearError(); + await generate(state); +}; + +// Apply initial state +modNameInput.value = state.mod_name; +modIdInput.value = state.mod_id; +refreshModIdPlaceholder(); +document.getElementById("package-input").value = state.package_name; +document.getElementById("architectury-api-input").checked = state.dependencies.architectury_api; diff --git a/style.css b/style.css new file mode 100644 index 0000000..3196add --- /dev/null +++ b/style.css @@ -0,0 +1,190 @@ +/* + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. +*/ + +:root { + font-family: sans-serif; + cursor: default; + user-select: none; + background-color: var(--canvas-color); + color: var(--text-color); + + --error-color: #BB0000; + --border-color: #888888; + --canvas-color: #F0F0F0; + --card-color: white; + --text-color: black; + --button-accent-color: blue; + --active-button-text-color: white; + --disable-button-color: #CCCCCC; + --text-field-background: white; +} + +fieldset { + border-radius: 1ex; + margin: 1ex; +} + +fieldset, fieldset > legend { + background-color: var(--card-color); + border: solid 1px var(--border-color); +} + +fieldset > legend { + padding: 0.7ex; + border-radius: 0.5ex; +} + +fieldset h2 { + margin-bottom: 0.5ex; +} + +fieldset > h2:first-of-type, h3:first-of-type { + margin-top: 0; +} + +input[type = "text"] { + display: block; + width: 24em; + padding: 0.8ex; + + background-color: var(--text-field-background); + color: var(--text-color); + border: solid 1px var(--border-color); +} + +select { + padding: 1ex; +} + +.label-heading { + font-weight: bold; +} + +.property-description { + display: block; + margin-top: 1ex; + margin-bottom: 1ex; +} + +.multicol, .horizontal-flow { + display: flex; + flex-direction: row; +} + +.vertical-flow { + display: flex; + flex-direction: column; + align-items: stretch; +} + +.multicol > * { + margin: 1ex; +} + +h1 { + text-align: center; +} + +.horizontal-flow { + align-items: start; + justify-content: center; +} + +.toggle-button { + display: inline-block; + margin: 0.5ex; + padding: 0.7ex; + border: solid 1px var(--button-accent-color); + border-radius: 0.5ex; + transition: background-color 0.1s; +} + +.toggle-button:hover { + background-color: color-mix(in srgb, var(--button-accent-color), transparent 75%); +} + +.toggle-button:has(input:checked) { + background-color: var(--button-accent-color); + color: var(--active-button-text-color); +} + +.toggle-button:has(input:disabled) { + background-color: var(--disable-button-color); + border-color: var(--border-color); +} + +.toggle-button input { + appearance: none; + margin: 0; +} + +.hidden { + display: none; +} + +label[error]::after { + display: block; + content: "❌ " attr(error); + color: var(--error-color); +} + +#error-message-container::before { + content: "❌ "; + color: var(--error-color); +} + +#error-message-container { + color: var(--error-color); +} + +button { + width: 100%; + height: 3em; + font-size: 1em; + + border: solid 1px var(--border-color); + border-radius: 0.5ex; +} + +@media (prefers-color-scheme: dark) { + :root { + /* Overridden properties */ + --border-color: #464666; + --canvas-color: #1D1D2A; + --card-color: #2A2A3D; + --text-color: #DADADF; + --button-accent-color: #3259CC; + --active-button-text-color: white; + --disable-button-color: #35354A; + --text-field-background: #232333; + + /* Properties unique to dark mode */ + --button-hover-color: #2948a5; + --select-background: var(--text-field-background); + --select-hover: color-mix(in srgb, var(--text-field-background), var(--card-color)); + } + + button { + border-color: var(--button-accent-color); + background-color: var(--button-accent-color); + color: var(--active-button-text-color); + } + + button:hover { + background-color: var(--button-hover-color); + } + + select { + background-color: var(--select-background); + color: var(--text-color); + border: solid 1px var(--border-color); + border-radius: 0.5ex; + } + + select:hover { + background-color: var(--select-hover); + } +} diff --git a/templateer.js b/templateer.js new file mode 100644 index 0000000..b683428 --- /dev/null +++ b/templateer.js @@ -0,0 +1,911 @@ +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} +function __wbg_adapter_36(arg0, arg1) { + wasm.wasm_bindgen__convert__closures__invoke0_mut__hff116f4730a514d0(arg0, arg1); +} + +function __wbg_adapter_39(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures__invoke1_mut__h1f9a9e3d2a14eab2(arg0, arg1, addHeapObject(arg2)); +} + +/** +* @returns {any} +*/ +export function create_state() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.create_state(retptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + if (r2) { + throw takeObject(r1); + } + return takeObject(r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +/** +* @returns {Array} +*/ +export function list_all_minecraft_versions() { + const ret = wasm.list_all_minecraft_versions(); + return takeObject(ret); +} + +/** +* @param {string} mod_name +* @returns {string} +*/ +export function to_mod_id(mod_name) { + let deferred2_0; + let deferred2_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(mod_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.to_mod_id(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + deferred2_0 = r0; + deferred2_1 = r1; + return getStringFromWasm0(r0, r1); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } +} + +/** +* @param {string} mod_id +* @returns {boolean} +*/ +export function is_valid_mod_id(mod_id) { + const ptr0 = passStringToWasm0(mod_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.is_valid_mod_id(ptr0, len0); + return ret !== 0; +} + +/** +* @param {string} mod_id +* @returns {Array} +*/ +export function validate_mod_id(mod_id) { + const ptr0 = passStringToWasm0(mod_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.validate_mod_id(ptr0, len0); + return takeObject(ret); +} + +/** +* @param {any} state +* @returns {Promise} +*/ +export function generate(state) { + const ret = wasm.generate(addHeapObject(state)); + return takeObject(ret); +} + +/** +* @param {any} game_version +* @returns {boolean} +*/ +export function supports_neoforge(game_version) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.supports_neoforge(retptr, addHeapObject(game_version)); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + if (r2) { + throw takeObject(r1); + } + return r0 !== 0; + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} +function __wbg_adapter_171(arg0, arg1, arg2, arg3) { + wasm.wasm_bindgen__convert__closures__invoke2_mut__h7187a80a21fcff54(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbindgen_in = function(arg0, arg1) { + const ret = getObject(arg0) in getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_error_new = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { + const ret = getObject(arg0) == getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_getwithrefkey_15c62c2b8546208d = function(arg0, arg1) { + const ret = getObject(arg0)[getObject(arg1)]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_fetch_381efb5e862610fa = function(arg0) { + const ret = fetch(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Element_4622f5da1249a3eb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Element; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_setid_1984ee27e5075311 = function(arg0, arg1, arg2) { + getObject(arg0).id = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_setinnerHTML_b089587252408b67 = function(arg0, arg1, arg2) { + getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_getElementsByTagName_5e330e72abb60016 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getElementsByTagName(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_remove_48288e91662163dc = function(arg0) { + getObject(arg0).remove(); + }; + imports.wbg.__wbg_instanceof_Document_0498564890e9742f = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Document; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_URL_0fa2d65a766ab4b7 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).URL; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_body_674aec4c1c0910cd = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createElement_4891554b28d3388b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_getElementsByTagName_f5ac50391c7f853c = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getElementsByTagName(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Window_9029196b662bc42a = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_document_f7ace2b956f30a4f = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_alert_8c9ebcc791f5eaa8 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).alert(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_instanceof_HtmlElement_6f4725d4677c7968 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_setinnerText_1849424c2fdc16ec = function(arg0, arg1, arg2) { + getObject(arg0).innerText = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_setonclick_4e9c9187dbc33082 = function(arg0, arg1) { + getObject(arg0).onclick = getObject(arg1); + }; + imports.wbg.__wbg_fetch_8eaf01857a5bb21f = function(arg0, arg1) { + const ret = getObject(arg0).fetch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_HtmlInputElement_31b50e0cf542c524 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLInputElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_setaccept_c88dd3ef66a1bc96 = function(arg0, arg1, arg2) { + getObject(arg0).accept = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_settype_ed9a0cf484870612 = function(arg0, arg1, arg2) { + getObject(arg0).type = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_instanceof_HtmlAnchorElement_a293f072b6174b83 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLAnchorElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_setdownload_0d874703cef6b180 = function(arg0, arg1, arg2) { + getObject(arg0).download = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_sethref_a3fde9630423d8ed = function(arg0, arg1, arg2) { + getObject(arg0).href = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_instanceof_HtmlButtonElement_6bd3bcb5370764a5 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLButtonElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_length_b37ae9be90ea7cf5 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_item_3364fbfadbf2cf08 = function(arg0, arg1) { + const ret = getObject(arg0).item(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_textContent_c5d9e21ee03c63d4 = function(arg0, arg1) { + const ret = getObject(arg1).textContent; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_appendChild_51339d4cde00ee22 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).appendChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_signal_4bd18fb489af2d4c = function(arg0) { + const ret = getObject(arg0).signal; + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_55c9955722952374 = function() { return handleError(function () { + const ret = new AbortController(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_abort_654b796176d117aa = function(arg0) { + getObject(arg0).abort(); + }; + imports.wbg.__wbg_new_1eead62f64ca15ce = function() { return handleError(function () { + const ret = new Headers(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_append_fda9e3432e3e88da = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_newwithstrandinit_cad5cd6038c7ff5d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createObjectURL_d82f2880bada6a1d = function() { return handleError(function (arg0, arg1) { + const ret = URL.createObjectURL(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_newwithu8arraysequenceandoptions_854056d2c35b489c = function() { return handleError(function (arg0, arg1) { + const ret = new Blob(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_f648bc7adcace0bc = function() { return handleError(function () { + const ret = new DOMParser(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_parseFromString_3d7be3de8b4c264e = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).parseFromString(getStringFromWasm0(arg1, arg2), takeObject(arg3)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Response_fc4327dbfcdf5ced = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_url_8503de97f69da463 = function(arg0, arg1) { + const ret = getObject(arg1).url; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_status_ac85a3142a84caa2 = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_headers_b70de86b8e989bc0 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_arrayBuffer_288fb3538806e85c = function() { return handleError(function (arg0) { + const ret = getObject(arg0).arrayBuffer(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_text_a667ac1770538491 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).text(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) { + const ret = getObject(arg0)[arg1 >>> 0]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_new_898a68150f225f2e = function() { + const ret = new Array(); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_526fc47e980da008 = function(arg0) { + const ret = getObject(arg0).next; + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_ddb3312ca1c4e32a = function() { return handleError(function (arg0) { + const ret = getObject(arg0).next(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_done_5c1f01fb660d73b5 = function(arg0) { + const ret = getObject(arg0).done; + return ret; + }; + imports.wbg.__wbg_value_1695675138684bd5 = function(arg0) { + const ret = getObject(arg0).value; + return addHeapObject(ret); + }; + imports.wbg.__wbg_iterator_97f0c81209c6c35a = function() { + const ret = Symbol.iterator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_b51585de1b234aff = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_push_ca1c26067ef907ac = function(arg0, arg1) { + const ret = getObject(arg0).push(getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ArrayBuffer; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_call_01734de55d61e11d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_entries_e51f29c7bba0c054 = function(arg0) { + const ret = Object.entries(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_43f1b47c28813cbd = function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return __wbg_adapter_171(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return addHeapObject(ret); + } finally { + state0.a = state0.b = 0; + } + }; + imports.wbg.__wbg_resolve_53698b95aaf7fcf8 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_f7e06ee3c11698eb = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_b2267541e2a73865 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_6da8e527659b86aa = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Uint8Array; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_buffer_f5b7059c439f330d = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_has_c5fcd020291e56b8 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.has(getObject(arg0), getObject(arg1)); + return ret; + }, arguments) }; + imports.wbg.__wbg_set_092e06b0f9d71865 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbg_stringify_e25465938f3f611f = function() { return handleError(function (arg0) { + const ret = JSON.stringify(getObject(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper575 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 278, __wbg_adapter_36); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper954 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 469, __wbg_adapter_39); + return addHeapObject(ret); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint8Memory0 = null; + + + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + input = new URL('templateer_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync } +export default __wbg_init; diff --git a/templateer_bg.wasm b/templateer_bg.wasm new file mode 100644 index 0000000..73521ee Binary files /dev/null and b/templateer_bg.wasm differ diff --git a/templates/fabric/build.gradle b/templates/fabric/build.gradle new file mode 100644 index 0000000..1a3be97 --- /dev/null +++ b/templates/fabric/build.gradle @@ -0,0 +1,61 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +architectury { + platformSetupLoomIde() + fabric() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentFabric.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:$rootProject.fabric_api_version" +//% if architectury_api + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "%ARCHITECTURY_GROUP%:architectury-fabric:$rootProject.architectury_api_version" +//% end + + common(project(path: ':common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':common', configuration: 'transformProductionFabric') +//% if fabric_like + common(project(path: ':fabric-like', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':fabric-like', configuration: 'transformProductionFabric') +//% end +} + +processResources { + inputs.property 'version', project.version + + filesMatching('fabric.mod.json') { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} diff --git a/templates/fabric/src/main/java/PACKAGE_DIR/fabric/ExampleModFabric.java b/templates/fabric/src/main/java/PACKAGE_DIR/fabric/ExampleModFabric.java new file mode 100644 index 0000000..8ab712d --- /dev/null +++ b/templates/fabric/src/main/java/PACKAGE_DIR/fabric/ExampleModFabric.java @@ -0,0 +1,26 @@ +package %PACKAGE_NAME%.fabric; + +import net.fabricmc.api.ModInitializer; + +//% if fabric_like +import %PACKAGE_NAME%.fabriclike.ExampleModFabricLike; +//% else +import %PACKAGE_NAME%.ExampleMod; +//% end + +public final class ExampleModFabric implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + +//% if fabric_like + // Run the Fabric-like setup. + ExampleModFabricLike.init(); +//% else + // Run our common setup. + ExampleMod.init(); +//% end + } +} diff --git a/templates/fabric/src/main/java/PACKAGE_DIR/fabric/client/ExampleModFabricClient.java b/templates/fabric/src/main/java/PACKAGE_DIR/fabric/client/ExampleModFabricClient.java new file mode 100644 index 0000000..2874e27 --- /dev/null +++ b/templates/fabric/src/main/java/PACKAGE_DIR/fabric/client/ExampleModFabricClient.java @@ -0,0 +1,10 @@ +package %PACKAGE_NAME%.fabric.client; + +import net.fabricmc.api.ClientModInitializer; + +public final class ExampleModFabricClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + // This entrypoint is suitable for setting up client-specific logic, such as rendering. + } +} diff --git a/templates/fabric/src/main/resources/fabric.mod.json b/templates/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..57290f9 --- /dev/null +++ b/templates/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "%MOD_ID%", + "version": "${version}", + "name": "%MOD_NAME%", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + "license": "CC0-1.0", + "icon": "assets/%MOD_ID%/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "%PACKAGE_NAME%.fabric.ExampleModFabric" + ], + "client": [ + "%PACKAGE_NAME%.fabric.client.ExampleModFabricClient" + ] + }, + "mixins": [ + "%MOD_ID%.mixins.json" + ], + "depends": { + "fabricloader": ">=%FABRIC_LOADER_VERSION%", + "minecraft": "~%MINECRAFT_VERSION%", + "java": ">=%JAVA_MAJOR_VERSION%", +//% if architectury_api + "architectury": ">=%ARCHITECTURY_API_VERSION%", +//% end + "fabric-api": "*" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/templates/fabric_like/build.gradle b/templates/fabric_like/build.gradle new file mode 100644 index 0000000..563ad18 --- /dev/null +++ b/templates/fabric_like/build.gradle @@ -0,0 +1,15 @@ +architectury { + common rootProject.enabled_platforms.split(',') +} + +dependencies { + modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" + modImplementation "net.fabricmc.fabric-api:fabric-api:$rootProject.fabric_api_version" +//% if architectury_api + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "%ARCHITECTURY_GROUP%:architectury-fabric:$rootProject.architectury_api_version" +//% end + + compileOnly(project(path: ':common', configuration: 'namedElements')) { transitive false } +} diff --git a/templates/fabric_like/src/main/java/PACKAGE_DIR/fabriclike/ExampleModFabricLike.java b/templates/fabric_like/src/main/java/PACKAGE_DIR/fabriclike/ExampleModFabricLike.java new file mode 100644 index 0000000..6fa63ae --- /dev/null +++ b/templates/fabric_like/src/main/java/PACKAGE_DIR/fabriclike/ExampleModFabricLike.java @@ -0,0 +1,10 @@ +package %PACKAGE_NAME%.fabriclike; + +import %PACKAGE_NAME%.ExampleMod; + +public final class ExampleModFabricLike { + public static void init() { + // Run our common setup. + ExampleMod.init(); + } +} diff --git a/templates/forge/build.gradle b/templates/forge/build.gradle new file mode 100644 index 0000000..fcc12d6 --- /dev/null +++ b/templates/forge/build.gradle @@ -0,0 +1,60 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +loom { + forge { + mixinConfig "%MOD_ID%.mixins.json" + } +} + +architectury { + platformSetupLoomIde() + forge() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentForge.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + forge "net.minecraftforge:forge:$rootProject.forge_version" +//% if architectury_api + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "%ARCHITECTURY_GROUP%:architectury-forge:$rootProject.architectury_api_version" +//% end + + common(project(path: ':common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':common', configuration: 'transformProductionForge') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/mods.toml') { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} diff --git a/templates/forge/gradle.properties b/templates/forge/gradle.properties new file mode 100644 index 0000000..a58ba14 --- /dev/null +++ b/templates/forge/gradle.properties @@ -0,0 +1 @@ +loom.platform = forge diff --git a/templates/forge/src/main/java/PACKAGE_DIR/forge/ExampleModForge.java b/templates/forge/src/main/java/PACKAGE_DIR/forge/ExampleModForge.java new file mode 100644 index 0000000..bf54c45 --- /dev/null +++ b/templates/forge/src/main/java/PACKAGE_DIR/forge/ExampleModForge.java @@ -0,0 +1,24 @@ +package %PACKAGE_NAME%.forge; + +//% if architectury_api +import %ARCHITECTURY_PACKAGE%.platform.forge.EventBuses; +//% end +import net.minecraftforge.fml.common.Mod; +//% if architectury_api +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +//% end + +import %PACKAGE_NAME%.ExampleMod; + +@Mod(ExampleMod.MOD_ID) +public final class ExampleModForge { + public ExampleModForge() { +//% if architectury_api + // Submit our event bus to let Architectury API register our content on the right time. + EventBuses.registerModEventBus(ExampleMod.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus()); + +//% end + // Run our common setup. + ExampleMod.init(); + } +} diff --git a/templates/forge/src/main/resources/META-INF/mods.toml b/templates/forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..d6873e4 --- /dev/null +++ b/templates/forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,37 @@ +modLoader = "javafml" +loaderVersion = "[%FORGE_LOADER_MAJOR%,)" +#issueTrackerURL = "" +license = "Insert License Here" + +[[mods]] +modId = "%MOD_ID%" +version = "${version}" +displayName = "%MOD_NAME%" +authors = "Me!" +description = ''' +This is an example description! Tell everyone what your mod is about! +''' +#logoFile = "" + +[[dependencies.%MOD_ID%]] +modId = "forge" +mandatory = true +versionRange = "[%FORGE_LOADER_MAJOR%,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.%MOD_ID%]] +modId = "minecraft" +mandatory = true +versionRange = "[%MINECRAFT_VERSION%,)" +ordering = "NONE" +side = "BOTH" +#% if architectury_api + +[[dependencies.%MOD_ID%]] +modId = "architectury" +mandatory = true +versionRange = "[%ARCHITECTURY_API_VERSION%,)" +ordering = "AFTER" +side = "BOTH" +#% end diff --git a/templates/forge/src/main/resources/pack.mcmeta b/templates/forge/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..47b4f92 --- /dev/null +++ b/templates/forge/src/main/resources/pack.mcmeta @@ -0,0 +1,9 @@ +{ + "pack": { + "description": "%MOD_NAME%", +//% if FORGE_DATA_PACK_FORMAT + "%FORGE_DATA_PACK_FORMAT_KEY%": %FORGE_DATA_PACK_FORMAT%, +//% end + "pack_format": %FORGE_PACK_FORMAT% + } +} diff --git a/templates/forge_only/build.gradle b/templates/forge_only/build.gradle new file mode 100644 index 0000000..4a6c45a --- /dev/null +++ b/templates/forge_only/build.gradle @@ -0,0 +1,75 @@ +plugins { + id 'dev.architectury.loom' version '%LOOM_VERSION%' + id 'maven-publish' +} + +group = project.maven_group +version = project.mod_version + +base { + archivesName = project.archives_name +} + +loom { + forge { + mixinConfig '%MOD_ID%.mixins.json' + } +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + minecraft "net.minecraft:minecraft:$project.minecraft_version" +//% if yarn + mappings "net.fabricmc:yarn:$project.yarn_mappings:v2" +//% end +//% if mojang_mappings + mappings loom.officialMojangMappings() +//% end + forge "net.minecraftforge:forge:$project.forge_version" +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/mods.toml') { + expand version: project.version + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_%GRADLE_JAVA_VERSION% + targetCompatibility = JavaVersion.VERSION_%GRADLE_JAVA_VERSION% +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = %JAVA_MAJOR_VERSION% +} + +// Configure Maven publishing. +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/templates/forge_only/gradle.properties b/templates/forge_only/gradle.properties new file mode 100644 index 0000000..9d88fb0 --- /dev/null +++ b/templates/forge_only/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx1G +loom.platform = forge + +# Mod properties +mod_version = 1.0.0 +maven_group = %PACKAGE_NAME% +archives_name = %MOD_ID% + +# Minecraft properties +minecraft_version = %MINECRAFT_VERSION% +#% if yarn +yarn_mappings = %YARN_MAPPINGS% +#% end + +# Dependencies +forge_version = %FORGE_VERSION% diff --git a/templates/forge_only/settings.gradle b/templates/forge_only/settings.gradle new file mode 100644 index 0000000..3ecc8b1 --- /dev/null +++ b/templates/forge_only/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.architectury.dev/" } + maven { url "https://files.minecraftforge.net/maven/" } + gradlePluginPortal() + } +} + +rootProject.name = '%MOD_ID%' diff --git a/templates/forge_only/src/main/java/PACKAGE_DIR/ExampleMod.java b/templates/forge_only/src/main/java/PACKAGE_DIR/ExampleMod.java new file mode 100644 index 0000000..0aedb0b --- /dev/null +++ b/templates/forge_only/src/main/java/PACKAGE_DIR/ExampleMod.java @@ -0,0 +1,14 @@ +package %PACKAGE_NAME%; + +import net.minecraftforge.fml.common.Mod; + +@Mod(ExampleMod.MOD_ID) +public final class ExampleMod { + public static final String MOD_ID = "%MOD_ID%"; + + public ExampleMod() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like registries and resources) may still be uninitialized. + // Proceed with mild caution. + } +} diff --git a/templates/forge_only/src/main/resources/META-INF/mods.toml b/templates/forge_only/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..1102e51 --- /dev/null +++ b/templates/forge_only/src/main/resources/META-INF/mods.toml @@ -0,0 +1,28 @@ +modLoader = "javafml" +loaderVersion = "[%FORGE_LOADER_MAJOR%,)" +#issueTrackerURL = "" +license = "Insert License Here" + +[[mods]] +modId = "%MOD_ID%" +version = "${version}" +displayName = "%MOD_NAME%" +authors = "Me!" +description = ''' +This is an example description! Tell everyone what your mod is about! +''' +#logoFile = "" + +[[dependencies.%MOD_ID%]] +modId = "forge" +mandatory = true +versionRange = "[%FORGE_LOADER_MAJOR%,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.%MOD_ID%]] +modId = "minecraft" +mandatory = true +versionRange = "[%MINECRAFT_VERSION%,)" +ordering = "NONE" +side = "BOTH" diff --git a/templates/forge_only/src/main/resources/MOD_ID.mixins.json b/templates/forge_only/src/main/resources/MOD_ID.mixins.json new file mode 100644 index 0000000..d9df560 --- /dev/null +++ b/templates/forge_only/src/main/resources/MOD_ID.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "%PACKAGE_NAME%.mixin", + "compatibilityLevel": "%MIXIN_COMPAT_LEVEL%", + "minVersion": "0.8", + "client": [ + ], + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/templates/forge_only/src/main/resources/pack.mcmeta b/templates/forge_only/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..47b4f92 --- /dev/null +++ b/templates/forge_only/src/main/resources/pack.mcmeta @@ -0,0 +1,9 @@ +{ + "pack": { + "description": "%MOD_NAME%", +//% if FORGE_DATA_PACK_FORMAT + "%FORGE_DATA_PACK_FORMAT_KEY%": %FORGE_DATA_PACK_FORMAT%, +//% end + "pack_format": %FORGE_PACK_FORMAT% + } +} diff --git a/templates/multiplatform/build.gradle b/templates/multiplatform/build.gradle new file mode 100644 index 0000000..a4385d7 --- /dev/null +++ b/templates/multiplatform/build.gradle @@ -0,0 +1,75 @@ +plugins { + id 'dev.architectury.loom' version '%LOOM_VERSION%' apply false + id 'architectury-plugin' version '%PLUGIN_VERSION%' + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false +} + +architectury { + minecraft = project.minecraft_version +} + +allprojects { + group = rootProject.maven_group + version = rootProject.mod_version +} + +subprojects { + apply plugin: 'dev.architectury.loom' + apply plugin: 'architectury-plugin' + apply plugin: 'maven-publish' + + base { + // Set up a suffixed format for the mod jar names, e.g. `example-fabric`. + archivesName = "$rootProject.archives_name-$project.name" + } + + repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. + } + + dependencies { + minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" +//% if yarn + mappings "net.fabricmc:yarn:$rootProject.yarn_mappings:v2" +//% end +//% if mojang_mappings + mappings loom.officialMojangMappings() +//% end + } + + java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_%GRADLE_JAVA_VERSION% + targetCompatibility = JavaVersion.VERSION_%GRADLE_JAVA_VERSION% + } + + tasks.withType(JavaCompile).configureEach { + it.options.release = %JAVA_MAJOR_VERSION% + } + + // Configure Maven publishing. + publishing { + publications { + mavenJava(MavenPublication) { + artifactId = base.archivesName.get() + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } + } +} diff --git a/templates/multiplatform/common/build.gradle b/templates/multiplatform/common/build.gradle new file mode 100644 index 0000000..e2364e8 --- /dev/null +++ b/templates/multiplatform/common/build.gradle @@ -0,0 +1,15 @@ +architectury { + common rootProject.enabled_platforms.split(',') +} + +dependencies { + // We depend on Fabric Loader here to use the Fabric @Environment annotations, + // which get remapped to the correct annotations on each platform. + // Do NOT use other classes from Fabric Loader. + modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" +//% if architectury_api + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "%ARCHITECTURY_GROUP%:architectury:$rootProject.architectury_api_version" +//% end +} diff --git a/templates/multiplatform/common/src/main/java/PACKAGE_DIR/ExampleMod.java b/templates/multiplatform/common/src/main/java/PACKAGE_DIR/ExampleMod.java new file mode 100644 index 0000000..424d26e --- /dev/null +++ b/templates/multiplatform/common/src/main/java/PACKAGE_DIR/ExampleMod.java @@ -0,0 +1,9 @@ +package %PACKAGE_NAME%; + +public final class ExampleMod { + public static final String MOD_ID = "%MOD_ID%"; + + public static void init() { + // Write common init code here. + } +} diff --git a/templates/multiplatform/common/src/main/resources/MOD_ID.mixins.json b/templates/multiplatform/common/src/main/resources/MOD_ID.mixins.json new file mode 100644 index 0000000..d9df560 --- /dev/null +++ b/templates/multiplatform/common/src/main/resources/MOD_ID.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "%PACKAGE_NAME%.mixin", + "compatibilityLevel": "%MIXIN_COMPAT_LEVEL%", + "minVersion": "0.8", + "client": [ + ], + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/templates/multiplatform/gradle.properties b/templates/multiplatform/gradle.properties new file mode 100644 index 0000000..5617431 --- /dev/null +++ b/templates/multiplatform/gradle.properties @@ -0,0 +1,34 @@ +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx2G +org.gradle.parallel=true + +# Mod properties +mod_version = 1.0.0 +maven_group = %PACKAGE_NAME% +archives_name = %MOD_ID% +enabled_platforms = %ARCHITECTURY_PLATFORMS% + +# Minecraft properties +minecraft_version = %MINECRAFT_VERSION% +#% if yarn +yarn_mappings = %YARN_MAPPINGS% +#% end + +# Dependencies +#% if architectury_api +architectury_api_version = %ARCHITECTURY_API_VERSION% +#% end +fabric_loader_version = %FABRIC_LOADER_VERSION% +#% if fabric +fabric_api_version = %FABRIC_API_VERSION% +#% end +#% if forge +forge_version = %FORGE_VERSION% +#% end +#% if neoforge +neoforge_version = %NEOFORGE_VERSION% +#% end +#% if quilt +quilt_loader_version = %QUILT_LOADER_VERSION% +quilted_fabric_api_version = %QUILTED_FABRIC_API_VERSION% +#% end diff --git a/templates/multiplatform/settings.gradle b/templates/multiplatform/settings.gradle new file mode 100644 index 0000000..0e7d390 --- /dev/null +++ b/templates/multiplatform/settings.gradle @@ -0,0 +1,27 @@ +pluginManagement { + repositories { + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.architectury.dev/" } + maven { url "https://files.minecraftforge.net/maven/" } + gradlePluginPortal() + } +} + +rootProject.name = '%MOD_ID%' + +include 'common' +//% if fabric +include 'fabric' +//% end +//% if fabric_like +include 'fabric-like' +//% end +//% if forge +include 'forge' +//% end +//% if neoforge +include 'neoforge' +//% end +//% if quilt +include 'quilt' +//% end diff --git a/templates/neoforge/build.gradle b/templates/neoforge/build.gradle new file mode 100644 index 0000000..95c5c0c --- /dev/null +++ b/templates/neoforge/build.gradle @@ -0,0 +1,61 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +architectury { + platformSetupLoomIde() + neoForge() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentNeoForge.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +repositories { + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } +} + +dependencies { + neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" +//% if architectury_api + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "%ARCHITECTURY_GROUP%:architectury-neoforge:$rootProject.architectury_api_version" +//% end + + common(project(path: ':common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/mods.toml') { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} diff --git a/templates/neoforge/gradle.properties b/templates/neoforge/gradle.properties new file mode 100644 index 0000000..2e6ed76 --- /dev/null +++ b/templates/neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform = neoforge diff --git a/templates/neoforge/src/main/java/PACKAGE_DIR/neoforge/ExampleModNeoForge.java b/templates/neoforge/src/main/java/PACKAGE_DIR/neoforge/ExampleModNeoForge.java new file mode 100644 index 0000000..892afa5 --- /dev/null +++ b/templates/neoforge/src/main/java/PACKAGE_DIR/neoforge/ExampleModNeoForge.java @@ -0,0 +1,13 @@ +package %PACKAGE_NAME%.neoforge; + +import net.neoforged.fml.common.Mod; + +import %PACKAGE_NAME%.ExampleMod; + +@Mod(ExampleMod.MOD_ID) +public final class ExampleModNeoForge { + public ExampleModNeoForge() { + // Run our common setup. + ExampleMod.init(); + } +} diff --git a/templates/neoforge/src/main/resources/META-INF/mods.toml b/templates/neoforge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..2fe9524 --- /dev/null +++ b/templates/neoforge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,40 @@ +modLoader = "javafml" +loaderVersion = "[%NEOFORGE_LOADER_MAJOR%,)" +#issueTrackerURL = "" +license = "Insert License Here" + +[[mods]] +modId = "%MOD_ID%" +version = "${version}" +displayName = "%MOD_NAME%" +authors = "Me!" +description = ''' +This is an example description! Tell everyone what your mod is about! +''' +#logoFile = "" + +[[dependencies.%MOD_ID%]] +modId = "neoforge" +type = "required" +versionRange = "[%NEOFORGE_MAJOR%,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.%MOD_ID%]] +modId = "minecraft" +type = "required" +versionRange = "[%MINECRAFT_VERSION%,)" +ordering = "NONE" +side = "BOTH" +#% if architectury_api + +[[dependencies.%MOD_ID%]] +modId = "architectury" +type = "required" +versionRange = "[%ARCHITECTURY_API_VERSION%,)" +ordering = "AFTER" +side = "BOTH" +#% end + +[[mixins]] +config = "%MOD_ID%.mixins.json" diff --git a/templates/neoforge_only/build.gradle b/templates/neoforge_only/build.gradle new file mode 100644 index 0000000..4c1ec39 --- /dev/null +++ b/templates/neoforge_only/build.gradle @@ -0,0 +1,75 @@ +plugins { + id 'dev.architectury.loom' version '%LOOM_VERSION%' + id 'maven-publish' +} + +group = project.maven_group +version = project.mod_version + +base { + archivesName = project.archives_name +} + +repositories { + // Add NeoForged repository. + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } + + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + minecraft "net.minecraft:minecraft:$project.minecraft_version" +//% if yarn + mappings "net.fabricmc:yarn:$project.yarn_mappings:v2" +//% end +//% if mojang_mappings + mappings loom.officialMojangMappings() +//% end + neoForge "net.neoforged:neoforge:$project.neoforge_version" +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/mods.toml') { + expand version: project.version + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_%GRADLE_JAVA_VERSION% + targetCompatibility = JavaVersion.VERSION_%GRADLE_JAVA_VERSION% +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = %JAVA_MAJOR_VERSION% +} + +// Configure Maven publishing. +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/templates/neoforge_only/gradle.properties b/templates/neoforge_only/gradle.properties new file mode 100644 index 0000000..7e49bc1 --- /dev/null +++ b/templates/neoforge_only/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx1G +loom.platform = neoforge + +# Mod properties +mod_version = 1.0.0 +maven_group = %PACKAGE_NAME% +archives_name = %MOD_ID% + +# Minecraft properties +minecraft_version = %MINECRAFT_VERSION% +#% if yarn +yarn_mappings = %YARN_MAPPINGS% +#% end + +# Dependencies +neoforge_version = %NEOFORGE_VERSION% diff --git a/templates/neoforge_only/settings.gradle b/templates/neoforge_only/settings.gradle new file mode 100644 index 0000000..3ecc8b1 --- /dev/null +++ b/templates/neoforge_only/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.architectury.dev/" } + maven { url "https://files.minecraftforge.net/maven/" } + gradlePluginPortal() + } +} + +rootProject.name = '%MOD_ID%' diff --git a/templates/neoforge_only/src/main/java/PACKAGE_DIR/ExampleMod.java b/templates/neoforge_only/src/main/java/PACKAGE_DIR/ExampleMod.java new file mode 100644 index 0000000..7bca4ad --- /dev/null +++ b/templates/neoforge_only/src/main/java/PACKAGE_DIR/ExampleMod.java @@ -0,0 +1,14 @@ +package %PACKAGE_NAME%; + +import net.neoforged.fml.common.Mod; + +@Mod(ExampleMod.MOD_ID) +public final class ExampleMod { + public static final String MOD_ID = "%MOD_ID%"; + + public ExampleMod() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like registries and resources) may still be uninitialized. + // Proceed with mild caution. + } +} diff --git a/templates/neoforge_only/src/main/resources/META-INF/mods.toml b/templates/neoforge_only/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..c3678a6 --- /dev/null +++ b/templates/neoforge_only/src/main/resources/META-INF/mods.toml @@ -0,0 +1,31 @@ +modLoader = "javafml" +loaderVersion = "[%NEOFORGE_LOADER_MAJOR%,)" +#issueTrackerURL = "" +license = "Insert License Here" + +[[mods]] +modId = "%MOD_ID%" +version = "${version}" +displayName = "%MOD_NAME%" +authors = "Me!" +description = ''' +This is an example description! Tell everyone what your mod is about! +''' +#logoFile = "" + +[[dependencies.%MOD_ID%]] +modId = "neoforge" +type = "required" +versionRange = "[%NEOFORGE_MAJOR%,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.%MOD_ID%]] +modId = "minecraft" +type = "required" +versionRange = "[%MINECRAFT_VERSION%,)" +ordering = "NONE" +side = "BOTH" + +[[mixins]] +config = "%MOD_ID%.mixins.json" diff --git a/templates/neoforge_only/src/main/resources/MOD_ID.mixins.json b/templates/neoforge_only/src/main/resources/MOD_ID.mixins.json new file mode 100644 index 0000000..d9df560 --- /dev/null +++ b/templates/neoforge_only/src/main/resources/MOD_ID.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "%PACKAGE_NAME%.mixin", + "compatibilityLevel": "%MIXIN_COMPAT_LEVEL%", + "minVersion": "0.8", + "client": [ + ], + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/templates/quilt/build.gradle b/templates/quilt/build.gradle new file mode 100644 index 0000000..58f99f4 --- /dev/null +++ b/templates/quilt/build.gradle @@ -0,0 +1,70 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +repositories { + maven { url 'https://maven.quiltmc.org/repository/release/' } +} + +architectury { + platformSetupLoomIde() + loader('quilt') +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentQuilt.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + modImplementation "org.quiltmc:quilt-loader:$rootProject.quilt_loader_version" + + // Quilt Standard Libraries and QSL. + modImplementation "org.quiltmc.quilted-fabric-api:quilted-fabric-api:$rootProject.quilted_fabric_api_version" +//% if architectury_api + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation("%ARCHITECTURY_GROUP%:architectury-fabric:$rootProject.architectury_api_version") { + // We must not pull Fabric Loader and Fabric API from Architectury Fabric. + exclude group: 'net.fabricmc' + exclude group: 'net.fabricmc.fabric-api' + } +//% end + + common(project(path: ':common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':common', configuration: 'transformProductionQuilt') +//% if fabric_like + common(project(path: ':fabric-like', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':fabric-like', configuration: 'transformProductionQuilt') +//% end +} + +processResources { + inputs.property 'group', project.group + inputs.property 'version', project.version + + filesMatching('quilt.mod.json') { + expand group: project.group, version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} diff --git a/templates/quilt/gradle.properties b/templates/quilt/gradle.properties new file mode 100644 index 0000000..56fe802 --- /dev/null +++ b/templates/quilt/gradle.properties @@ -0,0 +1 @@ +loom.platform = quilt diff --git a/templates/quilt/src/main/java/PACKAGE_DIR/quilt/ExampleModQuilt.java b/templates/quilt/src/main/java/PACKAGE_DIR/quilt/ExampleModQuilt.java new file mode 100644 index 0000000..c1a4d5f --- /dev/null +++ b/templates/quilt/src/main/java/PACKAGE_DIR/quilt/ExampleModQuilt.java @@ -0,0 +1,23 @@ +package %PACKAGE_NAME%.quilt; + +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; + +//% if fabric_like +import %PACKAGE_NAME%.fabriclike.ExampleModFabricLike; +//% else +import %PACKAGE_NAME%.ExampleMod; +//% end + +public final class ExampleModQuilt implements ModInitializer { + @Override + public void onInitialize(ModContainer mod) { +//% if fabric_like + // Run the Fabric-like setup. + ExampleModFabricLike.init(); +//% else + // Run our common setup. + ExampleMod.init(); +//% end + } +} diff --git a/templates/quilt/src/main/resources/quilt.mod.json b/templates/quilt/src/main/resources/quilt.mod.json new file mode 100644 index 0000000..a99f520 --- /dev/null +++ b/templates/quilt/src/main/resources/quilt.mod.json @@ -0,0 +1,45 @@ +{ + "schema_version": 1, + "quilt_loader": { + "group": "${group}", + "id": "%MOD_ID%", + "version": "${version}", + "metadata": { + "name": "%MOD_NAME%", + "description": "This is an example description! Tell everyone what your mod is about!", + "contributors": [ + "Me!" + ], + "icon": "assets/%MOD_ID%/icon.png" + }, + "intermediate_mappings": "net.fabricmc:intermediary", + "entrypoints": { + "init": [ + "%PACKAGE_NAME%.quilt.ExampleModQuilt" + ] + }, + "depends": [ + { + "id": "quilt_loader", + "version": "*" + }, + { + "id": "quilt_base", + "version": "*" + }, + { + "id": "minecraft", + "version": ">=%MINECRAFT_VERSION%" +//% if architectury_api + }, + { + "id": "architectury", + "version": ">=%ARCHITECTURY_API_VERSION%" +//% end + } + ] + }, + "mixin": [ + "%MOD_ID%.mixins.json" + ] +} diff --git a/templates/shared/gradle/wrapper/gradle-wrapper.jar b/templates/shared/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..d64cd49 Binary files /dev/null and b/templates/shared/gradle/wrapper/gradle-wrapper.jar differ diff --git a/templates/shared/gradle/wrapper/gradle-wrapper.properties b/templates/shared/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b82aa23 --- /dev/null +++ b/templates/shared/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/templates/shared/gradlew b/templates/shared/gradlew new file mode 100755 index 0000000..1aa94a4 --- /dev/null +++ b/templates/shared/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/templates/shared/gradlew.bat b/templates/shared/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/templates/shared/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/version_index.json b/version_index.json new file mode 100644 index 0000000..38278a2 --- /dev/null +++ b/version_index.json @@ -0,0 +1,62 @@ +{ + "1.16.5": { + "architectury_api": "1.32.68", + "forge": "1.16.5-36.2.42", + "neoforge": null + }, + "1.18.1": { + "architectury_api": "3.9.66", + "forge": "1.18.1-39.1.2", + "neoforge": null + }, + "1.20.4": { + "architectury_api": "11.1.17", + "forge": "1.20.4-49.0.39", + "neoforge": "20.4.227" + }, + "1.19.1": { + "architectury_api": "6.3.56", + "forge": "1.19.1-42.0.9", + "neoforge": null + }, + "1.19.3": { + "architectury_api": "7.1.86", + "forge": "1.19.3-44.1.23", + "neoforge": null + }, + "1.17.1": { + "architectury_api": "2.10.12", + "forge": "1.17.1-37.1.1", + "neoforge": null + }, + "1.19.2": { + "architectury_api": "6.6.92", + "forge": "1.19.2-43.3.9", + "neoforge": null + }, + "1.19.4": { + "architectury_api": "8.2.91", + "forge": "1.19.4-45.2.10", + "neoforge": null + }, + "1.20.1": { + "architectury_api": "9.2.14", + "forge": "1.20.1-47.2.23", + "neoforge": null + }, + "1.19": { + "architectury_api": "5.14.84", + "forge": "1.19-41.1.0", + "neoforge": null + }, + "1.18.2": { + "architectury_api": "4.12.94", + "forge": "1.18.2-40.2.18", + "neoforge": null + }, + "1.20.2": { + "architectury_api": "10.1.20", + "forge": "1.20.2-48.1.0", + "neoforge": null + } +} \ No newline at end of file