diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..9f8dcb9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,79 @@ +name: Bug Report +description: Something doesn't seem correct and it might be a bug +labels: [] +body: + - type: textarea + id: description + attributes: + label: Bug description + description: | + A clear and concise description of what the bug is. + Is it a game crash, an unexpected behavior, or has something gone wrong? + If applicable, add screenshots to help explain the bug. + placeholder: Tell us what you see! + validations: + required: true + - type: textarea + id: to-reproduce + attributes: + label: Steps to reproduce + description: Steps to reproduce the bug + placeholder: | + 1. Create a world + 2. Wait until midnight + 3. Hug a creeper + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: What did you expect to happen? + placeholder: The creeper explodes + - type: textarea + id: actual-behavior + attributes: + label: Actual behavior + description: What actually happened? + placeholder: The creeper launches itself into the sky + - type: textarea + id: logs + attributes: + label: Relevant logs + description: |- + If it's a crash, send the corresponding Minecraft log in the `logs` folder, or crash report in the `crash-reports` folder, here. + Please upload the log file as an attachment, or upload the log to [pastebin](https://pastebin.com/) / [mclo.gs](https://mclo.gs/) and paste the url here. + Please refrain from pasting the entire log file directly. + Leave empty if there is none. + placeholder: https://pastebin.com/J6b7lKxR + - type: input + id: minecraft-version + attributes: + label: Minecraft version + description: The Minecraft version(s) where this bug occurs in. + placeholder: 1.15.2 + validations: + required: true + - type: input + id: mod-version + attributes: + label: TemplateMod version + description: The TemplateMod version(s) where this bug occurs in. + placeholder: 1.2.3 + validations: + required: true + - type: textarea + id: other-information + attributes: + label: Other information + description: Other useful information to this bug report, e.g. other related mod version(s). Leave empty if there is none. + placeholder: The issue only occurs if the player is in survival mode + - type: checkboxes + id: check-list + attributes: + label: Check list + options: + - label: I have verified that the issue persists in the latest version of the mod. + required: true + - label: I have searched the existing issues and confirmed that this is not a duplicate. + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..75d7db3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,25 @@ +name: Feature Request +description: Suggest an idea for this project +labels: [] +body: + - type: textarea + id: motivation + attributes: + label: Motivation + description: Why do you want this feature? What problem do you want to solve? How can the suggested feature help with that? + placeholder: Tell us what you want! + validations: + required: true + - type: textarea + id: description + attributes: + label: Description + description: Describe the feature you want, as detailed as possible + placeholder: I want to see a fancy starry sky when I look up at midnight. + validations: + required: true + - type: textarea + id: other-information + attributes: + label: Other information + description: Other useful information to this feature request. Leave empty if there is none. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..511d421 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,109 @@ +name: _step.build + +on: + workflow_call: + inputs: + release: + type: boolean + required: false + default: false + target_subproject: + description: see release.yml, leave it empty to build all + type: string + required: false + default: '' +# # [FEATURE] MIXIN_AUDITOR +# mixin_audit: +# description: run mixin audit for Minecraft server after build +# type: boolean +# required: false +# default: false + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 21 + + - name: Cache gradle files + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ./.gradle/loom-cache + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle', '**/gradle.properties', '**/*.accesswidener', 'settings.json') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Build with gradle + run: | + chmod +x gradlew + if [ -z "${{ inputs.target_subproject }}" ]; then + echo "Building all subprojects" + ./gradlew build + else + args=$(echo "${{ inputs.target_subproject }}" | tr ',' '\n' | sed 's/$/:build/' | paste -sd ' ') + echo "Building with arguments=$args" + ./gradlew $args + fi + env: + BUILD_ID: ${{ github.run_number }} + BUILD_RELEASE: ${{ inputs.release }} + +# # [FEATURE] MIXIN_AUDITOR +# - name: Run mixin audit check for Minecraft server +# if: ${{ inputs.mixin_audit }} +# timeout-minutes: 10 +# run: | +# mkdir -p ./run +# echo eula=true > ./run/eula.txt +# ./gradlew runServerMixinAudit + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts + path: versions/*/build/libs/ + +# # [FEATURE] FALLENS_MAVEN +# - name: Publish with gradle +# if: inputs.release || github.ref == 'refs/heads/dev' +# run: | +# if [ -z "${{ inputs.target_subproject }}" ]; then +# echo "Publishing all subprojects" +# ./gradlew publish +# else +# args=$(echo "${{ inputs.target_subproject }}" | tr ',' '\n' | sed 's/$/:publish/' | paste -sd ' ') +# echo "Publishing with arguments=$args" +# ./gradlew $args +# fi +# env: +# BUILD_ID: ${{ github.run_number }} +# BUILD_RELEASE: ${{ inputs.release }} +# FALLENS_MAVEN_TOKEN: ${{ secrets.FALLENS_MAVEN_TOKEN }} + + summary: + runs-on: ubuntu-22.04 + needs: + - build + + steps: + - uses: actions/checkout@v4 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + path: build-artifacts + + - name: Make build summary + run: python3 .github/workflows/scripts/summary.py # ubuntu-22.04 uses Python 3.10.6 + env: + TARGET_SUBPROJECT: ${{ inputs.target_subproject }} diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..c8314b7 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,20 @@ +name: Dev Builds + +on: + push: + paths: + - "*.gradle" + - "gradle.properties" + - "src/**" + - "versions/**" + - ".github/**" + pull_request: + + +jobs: + build: + uses: ./.github/workflows/build.yml + secrets: inherit +# # [FEATURE] MIXIN_AUDITOR +# with: +# mixin_audit: true diff --git a/.github/workflows/matrix_prep.yml b/.github/workflows/matrix_prep.yml new file mode 100644 index 0000000..d0a0cc4 --- /dev/null +++ b/.github/workflows/matrix_prep.yml @@ -0,0 +1,29 @@ +name: _step.matrix_prepare + +on: + workflow_call: + inputs: + target_subproject: + description: see release.yml, for generating matrix entries + type: string + required: false + default: '' + outputs: + matrix: + description: The generated run matrix + value: ${{ jobs.matrix_prep.outputs.matrix }} + + +jobs: + matrix_prep: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - id: setmatrix + run: python3 .github/workflows/scripts/matrix.py # ubuntu-22.04 uses Python 3.10.6 + env: + TARGET_SUBPROJECT: ${{ inputs.target_subproject }} + + outputs: + matrix: ${{ steps.setmatrix.outputs.matrix }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c955077 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,208 @@ +name: Release + +# release: (release title) +# dispatch (all): Manual release for $target_release_tag +# dispatch (specified): Manual release for $target_release_tag (subproject: $target_subproject) +run-name: |- + ${{ github.event_name == 'workflow_dispatch' && format('Manual release for {0}{1}', inputs.target_release_tag, inputs.target_subproject && format(' (subproject: {0})', inputs.target_subproject) || '') || '' }} + +on: + release: + types: + - published + workflow_dispatch: + inputs: + target_subproject: + description: |- + The subproject name(s) of the specified Minecraft version to be released, seperated with ",". + By default all subprojects will be released + type: string + required: false + default: '' + target_release_tag: + description: The tag of the release you want to append the artifact to + type: string + required: true + + +jobs: + show_action_parameters: + runs-on: ubuntu-latest + steps: + - name: Show action parameters + run: | + cat < $GITHUB_STEP_SUMMARY + ## Action Parameters + - target_subproject: \`${{ github.event.inputs.target_subproject }}\` + - target_release_tag: \`${{ github.event.inputs.target_release_tag }}\` + EOF + + matrix_prep: + uses: ./.github/workflows/matrix_prep.yml + with: + target_subproject: ${{ github.event.inputs.target_subproject }} + + # ensure the input release tag is valid + validate_release: + runs-on: ubuntu-latest + steps: + - name: Get github release information + if: ${{ github.event_name == 'workflow_dispatch' }} + uses: cardinalby/git-get-release-action@1.2.5 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + tag: ${{ github.event.inputs.target_release_tag }} + + build: + uses: ./.github/workflows/build.yml + secrets: inherit + needs: + - validate_release + with: + target_subproject: ${{ github.event.inputs.target_subproject }} + release: true + + release: + needs: + - matrix_prep + - build + runs-on: ubuntu-latest + + # allow the mod publish step to add asserts to release + # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token + permissions: + contents: write + + strategy: + matrix: ${{ fromJson(needs.matrix_prep.outputs.matrix) }} + + steps: + - uses: actions/checkout@v4 + + - name: Display context + run: | + echo ref_name = ${{ github.ref_name }} + echo target_subproject = ${{ github.event.inputs.target_subproject }} + echo target_release_tag = ${{ github.event.inputs.target_release_tag }} + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + path: build-artifacts + + - name: Get github release information + if: ${{ github.event_name == 'workflow_dispatch' }} + id: get_release + uses: cardinalby/git-get-release-action@1.2.5 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + tag: ${{ github.event.inputs.target_release_tag }} + + - name: Generate publish related information + id: release_info + run: | + if [ $GITHUB_EVENT_NAME == 'release' ] + then + # Leave an empty value here, so Kir-Antipov/mc-publish will infer the tag from the action context + echo "tag_name=" >> $GITHUB_OUTPUT + elif [ $GITHUB_EVENT_NAME == 'workflow_dispatch' ] + then + echo "tag_name=${{ github.event.inputs.target_release_tag }}" >> $GITHUB_OUTPUT + else + echo Unknown github event name $GITHUB_EVENT_NAME + exit 1 + fi + + - name: Read common properties + id: properties_g + uses: christian-draeger/read-properties@1.1.1 + with: + path: gradle.properties + properties: 'mod_name mod_version' + + - name: Read version-specific properties + id: properties_v + uses: christian-draeger/read-properties@1.1.1 + with: + path: ${{ format('versions/{0}/gradle.properties', matrix.subproject) }} + properties: 'minecraft_version game_versions' + + - name: Fix game version + id: game_versions + run: | + # Fixed \n in game_versions isn't parsed by christian-draeger/read-properties as a line separator + echo 'value<> $GITHUB_OUTPUT + echo -e "${{ steps.properties_v.outputs.game_versions }}" >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT + + - name: Prepare file information + id: file_info + run: | + shopt -s extglob + FILE_PATHS=$(ls ${{ format('build-artifacts/{0}/build/libs/!(*-@(dev|sources|shadow)).jar', matrix.subproject) }}) + if (( ${#FILE_PATHS[@]} != 1 )); then + echo "Error: Found ${#FILE_PATHS[@]} files, expected exactly 1" + exit 1 + else + FILE_PATH=${FILE_PATHS[0]} + fi + + FILE_NAME=$(basename $FILE_PATH) + FILE_HASH=$(sha256sum $FILE_PATH | awk '{ print $1 }') + echo "path=$FILE_PATH" >> $GITHUB_OUTPUT + echo "name=$FILE_NAME" >> $GITHUB_OUTPUT + echo "hash=$FILE_HASH" >> $GITHUB_OUTPUT + cat $GITHUB_OUTPUT + + - name: Prepare changelog + uses: actions/github-script@v7 + id: changelog + with: + script: return process.env.CHANGELOG + result-encoding: string + env: + CHANGELOG: |- + ${{ format('{0}{1}', github.event.release.body, steps.get_release.outputs.body) }} + + ------- + + Build Information + + - File name: `${{ steps.file_info.outputs.name }}` + - SHA-256: `${{ steps.file_info.outputs.hash }}` + - Built from: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + + - name: Publish Minecraft Mods + uses: Kir-Antipov/mc-publish@v3.3 + with: + # https://modrinth.com/settings/pats +# modrinth-id: fo0Bar +# modrinth-token: ${{ secrets.MODRINTH_API_TOKEN }} + + # https://legacy.curseforge.com/account/api-tokens +# curseforge-id: 314159 +# curseforge-token: ${{ secrets.CF_API_TOKEN }} + + github-tag: ${{ steps.release_info.outputs.tag_name }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + files: ${{ steps.file_info.outputs.path }} + + name: ${{ format('{0} v{1} for mc{2}', steps.properties_g.outputs.mod_name, steps.properties_g.outputs.mod_version, steps.properties_v.outputs.minecraft_version) }} + version: ${{ format('v{1}-mc{0}', steps.properties_v.outputs.minecraft_version, steps.properties_g.outputs.mod_version) }} + version-type: release + + loaders: fabric + game-versions: ${{ steps.game_versions.outputs.value }} + game-version-filter: any + dependencies: '' # declare the dependencies explicitly, so mc-publish won't try to load from fabric.mod.json + + github-changelog: ${{ format('{0}{1}', github.event.release.body, steps.get_release.outputs.body) }} + modrinth-changelog: ${{ steps.changelog.outputs.result }} + curseforge-changelog: ${{ steps.changelog.outputs.result }} + + retry-attempts: 3 + retry-delay: 10000 diff --git a/.github/workflows/scripts/matrix.py b/.github/workflows/scripts/matrix.py new file mode 100644 index 0000000..a20e581 --- /dev/null +++ b/.github/workflows/scripts/matrix.py @@ -0,0 +1,46 @@ +""" +A script to scan through the versions directory and collect all folder names as the subproject list, +then output a json as the github action include matrix +""" +__author__ = 'Fallen_Breath' + +import json +import os +import sys + + +def main(): + target_subproject_env = os.environ.get('TARGET_SUBPROJECT', '') + target_subprojects = list(filter(None, target_subproject_env.split(',') if target_subproject_env != '' else [])) + print('target_subprojects: {}'.format(target_subprojects)) + + with open('settings.json') as f: + settings: dict = json.load(f) + + if len(target_subprojects) == 0: + subprojects = settings['versions'] + else: + subprojects = [] + for subproject in settings['versions']: + if subproject in target_subprojects: + subprojects.append(subproject) + target_subprojects.remove(subproject) + if len(target_subprojects) > 0: + print('Unexpected subprojects: {}'.format(target_subprojects), file=sys.stderr) + sys.exit(1) + + matrix_entries = [] + for subproject in subprojects: + matrix_entries.append({ + 'subproject': subproject, + }) + matrix = {'include': matrix_entries} + with open(os.environ['GITHUB_OUTPUT'], 'w') as f: + f.write('matrix={}\n'.format(json.dumps(matrix))) + + print('matrix:') + print(json.dumps(matrix, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/.github/workflows/scripts/summary.py b/.github/workflows/scripts/summary.py new file mode 100644 index 0000000..6f2bebe --- /dev/null +++ b/.github/workflows/scripts/summary.py @@ -0,0 +1,73 @@ +""" +A script to scan through all valid mod jars in build-artifacts.zip/$version/build/libs, +and generate an artifact summary table for that to GitHub action step summary +""" +__author__ = 'Fallen_Breath' + +import functools +import glob +import hashlib +import json +import os + + +def read_prop(file_name: str, key: str) -> str: + with open(file_name) as prop: + return next(filter( + lambda l: l.split('=', 1)[0].strip() == key, + prop.readlines() + )).split('=', 1)[1].lstrip() + + +def get_sha256_hash(file_path: str) -> str: + sha256_hash = hashlib.sha256() + + with open(file_path, 'rb') as f: + for buf in iter(functools.partial(f.read, 4096), b''): + sha256_hash.update(buf) + + return sha256_hash.hexdigest() + + +def main(): + target_subproject_env = os.environ.get('TARGET_SUBPROJECT', '') + target_subprojects = list(filter(None, target_subproject_env.split(',') if target_subproject_env != '' else [])) + print('target_subprojects: {}'.format(target_subprojects)) + + with open('settings.json') as f: + settings: dict = json.load(f) + + with open(os.environ['GITHUB_STEP_SUMMARY'], 'w') as f: + f.write('## Build Artifacts Summary\n\n') + f.write('| Subproject | for Minecraft | File | Size | SHA-256 |\n') + f.write('| --- | --- | --- | --- | --- |\n') + + warnings = [] + for subproject in settings['versions']: + if len(target_subprojects) > 0 and subproject not in target_subprojects: + print('skipping {}'.format(subproject)) + continue + game_versions = read_prop('versions/{}/gradle.properties'.format(subproject), 'game_versions') + game_versions = game_versions.strip().replace('\\n', ', ') + file_paths = glob.glob('build-artifacts/{}/build/libs/*.jar'.format(subproject)) + file_paths = list(filter(lambda fp: not fp.endswith('-sources.jar') and not fp.endswith('-dev.jar') and not fp.endswith('-shadow.jar'), file_paths)) + if len(file_paths) == 0: + file_name = '*not found*' + sha256 = '*N/A*' + else: + file_name = '`{}`'.format(os.path.basename(file_paths[0])) + file_size = '{} B'.format(os.path.getsize(file_paths[0])) + sha256 = '`{}`'.format(get_sha256_hash(file_paths[0])) + if len(file_paths) > 1: + warnings.append('Found too many build files in subproject {}: {}'.format(subproject, ', '.join(file_paths))) + + f.write('| {} | {} | {} | {} | {} |\n'.format(subproject, game_versions, file_name, file_size, sha256)) + + if len(warnings) > 0: + f.write('\n### Warnings\n\n') + for warning in warnings: + f.write('- {}\n'.format(warning)) + + +if __name__ == '__main__': + main() diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..09cd281 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# gradle + +.gradle/ +build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# macos + +*.DS_Store + +# fabric + +run/ diff --git a/HEADER.txt b/HEADER.txt new file mode 100644 index 0000000..8099a84 --- /dev/null +++ b/HEADER.txt @@ -0,0 +1,17 @@ +This file is part of the ${name} project, licensed under the +GNU Lesser General Public License v3.0 + +Copyright (C) ${year} ${author} and contributors + +${name} is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +${name} is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with ${name}. If not, see . diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0486eab --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +## fabric-mod-template + +[![License](https://img.shields.io/github/license/Fallen-Breath/fabric-mod-template.svg)](http://www.gnu.org/licenses/lgpl-3.0.html) +[![workflow](https://github.com/Fallen-Breath/fabric-mod-template/actions/workflows/gradle.yml/badge.svg)](https://github.com/Fallen-Breath/fabric-mod-template/actions/workflows/gradle.yml) + +fallen's fabric mod template + +If you find it helpful, a credit to this template in your project will be greatly appreciated + +## To use + +1. Clone / Use this template to get a new project +2. Search `[FEATURE]` in the project, delete or uncomment those addons +3. Setup the mod + - Edit java package name + - Edit [gradle.properties](gradle.properties) for mod id / name etc. + - Edit mod name in [bug_report.yml](.github/ISSUE_TEMPLATE/bug_report.yml) + - Edit [common.gradle](common.gradle) for mod file location constants + - Change the Minecraft versions in [settings.json](settings.json), [build.gradle](build.gradle), and files in the [versions](versions) folder + - Search `template` in the project to see if there are any missing unedited stuffs +4. Edit [README](README.md) for the new mod diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..e57030b --- /dev/null +++ b/build.gradle @@ -0,0 +1,56 @@ +plugins { + id 'maven-publish' + id 'com.github.hierynomus.license' version '0.16.1' apply false + id 'fabric-loom' version '1.7-SNAPSHOT' apply false + + // https://github.com/ReplayMod/preprocessor + // https://github.com/Fallen-Breath/preprocessor + id 'com.replaymod.preprocess' version 'ce1aeb2b' + + // https://github.com/Fallen-Breath/yamlang + id 'me.fallenbreath.yamlang' version '1.4.0' apply false +} + +preprocess { + def mc114 = createNode('1.14.4', 1_14_04, '') + def mc115 = createNode('1.15.2', 1_15_02, '') + def mc116 = createNode('1.16.5', 1_16_05, '') + def mc117 = createNode('1.17.1', 1_17_01, '') + def mc118 = createNode('1.18.2', 1_18_02, '') + def mc119 = createNode('1.19.4', 1_19_04, '') + def mc120 = createNode('1.20.6', 1_20_06, '') + def mc121 = createNode('1.21.1', 1_21_01, '') + + mc115.link(mc114, null) + mc115.link(mc116, null) + mc116.link(mc117, null) + mc117.link(mc118, null) + mc118.link(mc119, null) + mc119.link(mc120, null) + mc120.link(mc121, null) +} + +tasks.register('buildAndGather') { + subprojects { + dependsOn project.tasks.named('build').get() + } + doFirst { + println 'Gathering builds' + def buildLibs = { + p -> p.buildDir.toPath().resolve('libs') + } + delete fileTree(buildLibs(rootProject)) { + include '*' + } + subprojects { + copy { + from(buildLibs(project)) { + include '*.jar' + exclude '*-dev.jar', '*-sources.jar', '*-shadow.jar' + } + into buildLibs(rootProject) + duplicatesStrategy DuplicatesStrategy.INCLUDE + } + } + } +} diff --git a/common.gradle b/common.gradle new file mode 100644 index 0000000..51b5a56 --- /dev/null +++ b/common.gradle @@ -0,0 +1,235 @@ +apply plugin: 'maven-publish' +apply plugin: 'com.github.hierynomus.license' +apply plugin: 'fabric-loom' +apply plugin: 'com.replaymod.preprocess' +apply plugin: 'me.fallenbreath.yamlang' + +int mcVersion = project.mcVersion + +preprocess { + tabIndentation = true +} + +repositories { + maven { + url 'https://jitpack.io' + } + maven { + url 'https://maven.fallenbreath.me/releases' + } +} + +// https://github.com/FabricMC/fabric-loader/issues/783 +configurations { + modRuntimeOnly.exclude group: 'net.fabricmc', module: 'fabric-loader' +} + +dependencies { + // loom + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // runtime mods +// if (mcVersion < 11904) { +// modRuntimeOnly(mcVersion < 11900 ? "com.github.astei:lazydfu:0.1.2" : "com.github.Fallen-Breath:lazydfu:a7cfc44c0c") +// } +// // [FEATURE] MIXIN_AUDITOR +// modRuntimeOnly 'me.fallenbreath:mixin-auditor:0.1.0' + + // dependencies +// include(modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_api_version))) +// include(modImplementation("me.fallenbreath:conditional-mixin-fabric:${project.conditionalmixin_version}")) +// include(annotationProcessor(implementation("io.github.llamalad7:mixinextras-fabric:${project.mixinextras_version}"))) +} + +String MIXIN_CONFIG_PATH = 'template_mod.mixins.json' +String LANG_DIR = 'assets/template_mod/lang' +JavaVersion JAVA_COMPATIBILITY +if (mcVersion >= 12005) { + JAVA_COMPATIBILITY = JavaVersion.VERSION_21 +} else if (mcVersion >= 11800) { + JAVA_COMPATIBILITY = JavaVersion.VERSION_17 +} else if (mcVersion >= 11700) { + JAVA_COMPATIBILITY = JavaVersion.VERSION_16 +} else { + JAVA_COMPATIBILITY = JavaVersion.VERSION_1_8 +} +JavaVersion MIXIN_COMPATIBILITY_LEVEL = JAVA_COMPATIBILITY + +loom { + def commonVmArgs = ['-Dmixin.debug.export=true', '-Dmixin.debug.countInjections=true'] + runConfigs.configureEach { + // to make sure it generates all "Minecraft Client (:subproject_name)" applications + ideConfigGenerated = true + runDir '../../run' + vmArgs commonVmArgs + } +// // [FEATURE] MIXIN_AUDITOR +// runs { +// def auditVmArgs = ['-DmixinAuditor.audit=true'] +// serverMixinAudit { +// server() +// vmArgs auditVmArgs +// ideConfigGenerated false +// } +// } +} + +remapJar { + remapperIsolation = true +} + +String modVersionSuffix = '' +String artifactVersion = project.mod_version +String artifactVersionSuffix = '' +// detect github action environment variables +// https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables +if (System.getenv("BUILD_RELEASE") != "true") { + String buildNumber = System.getenv("BUILD_ID") + modVersionSuffix += buildNumber != null ? ('+build.' + buildNumber) : '-SNAPSHOT' + artifactVersionSuffix = '-SNAPSHOT' // A non-release artifact is always a SNAPSHOT artifact +} +String fullModVersion = project.mod_version + modVersionSuffix +String fullProjectVersion, fullArtifactVersion + +// Example version values: +// project.mod_version 1.0.3 (the base mod version) +// modVersionSuffix +build.88 (use github action build number if possible) +// artifactVersionSuffix -SNAPSHOT +// fullModVersion 1.0.3+build.88 (the actual mod version to use in the mod) +// fullProjectVersion v1.0.3-mc1.15.2+build.88 (in build output jar name) +// fullArtifactVersion 1.0.3-mc1.15.2-SNAPSHOT (maven artifact version) + +group = project.maven_group +if (System.getenv("JITPACK") == "true") { + // move mc version into archivesBaseName, so jitpack will be able to organize archives from multiple subprojects correctly + base.archivesName = project.archives_base_name + '-mc' + project.minecraft_version + fullProjectVersion = 'v' + project.mod_version + modVersionSuffix + fullArtifactVersion = artifactVersion + artifactVersionSuffix +} else { + base.archivesName = project.archives_base_name + fullProjectVersion = 'v' + project.mod_version + '-mc' + project.minecraft_version + modVersionSuffix + fullArtifactVersion = artifactVersion + '-mc' + project.minecraft_version + artifactVersionSuffix +} +version = fullProjectVersion + +// See https://youtrack.jetbrains.com/issue/IDEA-296490 +// if IDEA complains about "Cannot resolve resource filtering of MatchingCopyAction" and you want to know why +processResources { + inputs.property "id", project.mod_id + inputs.property "name", project.mod_name + inputs.property "version", fullModVersion + inputs.property "minecraft_dependency", project.minecraft_dependency + + filesMatching("fabric.mod.json") { + def valueMap = [ + "id": project.mod_id, + "name": project.mod_name, + "version": fullModVersion, + "minecraft_dependency": project.minecraft_dependency, + ] + expand valueMap + } + + filesMatching(MIXIN_CONFIG_PATH) { + filter { s -> s.replace('{{COMPATIBILITY_LEVEL}}', "JAVA_${MIXIN_COMPATIBILITY_LEVEL.ordinal() + 1}") } + } +} + +// https://github.com/Fallen-Breath/yamlang +yamlang { + targetSourceSets = [sourceSets.main] + inputDir = LANG_DIR +} + +// ensure that the encoding is set to UTF-8, no matter what the system default is +// this fixes some edge cases with special characters not displaying correctly +// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" + options.compilerArgs << "-Xlint:deprecation" << "-Xlint:unchecked" + if (JAVA_COMPATIBILITY <= JavaVersion.VERSION_1_8) { + // suppressed "source/target value 8 is obsolete and will be removed in a future release" + options.compilerArgs << '-Xlint:-options' + } +} + +java { + sourceCompatibility = JAVA_COMPATIBILITY + targetCompatibility = JAVA_COMPATIBILITY + + // 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() +} + +jar { + from(rootProject.file('LICENSE')) { + rename { "${it}_${project.archives_base_name}" } + } +} + +// https://github.com/hierynomus/license-gradle-plugin +license { + // use "gradle licenseFormat" to apply license headers + header = rootProject.file('HEADER.txt') + include '**/*.java' + skipExistingHeaders = true + + headerDefinitions { + // ref: https://github.com/mathieucarbou/license-maven-plugin/blob/4c42374bb737378f5022a3a36849d5e23ac326ea/license-maven-plugin/src/main/java/com/mycila/maven/plugin/license/header/HeaderType.java#L48 + // modification: add a newline at the end + SLASHSTAR_STYLE_NEWLINE { + firstLine = "/*" + beforeEachLine = " * " + endLine = " */" + System.lineSeparator() + afterEachLine = "" + skipLinePattern = null + firstLineDetectionPattern = "(\\s|\\t)*/\\*.*\$" + lastLineDetectionPattern = ".*\\*/(\\s|\\t)*\$" + allowBlankLines = false + isMultiline = true + padLines = false + } + } + mapping { + java = 'SLASHSTAR_STYLE_NEWLINE' + } + ext { + name = project.mod_name + author = 'Fallen_Breath' + year = Calendar.getInstance().get(Calendar.YEAR).toString() + } +} +classes.dependsOn licenseFormatMain +testClasses.dependsOn licenseFormatTest + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + artifactId base.archivesName.get() + from components.java + version = fullArtifactVersion + } + } + + // select the repositories you want to publish to + repositories { + // mavenLocal() + +// // [FEATURE] FALLENS_MAVEN +// maven { +// url = fullArtifactVersion.endsWith("SNAPSHOT") ? "https://maven.fallenbreath.me/snapshots" : "https://maven.fallenbreath.me/releases" +// credentials(PasswordCredentials) { +// username = 'fallen' +// password = System.getenv("FALLENS_MAVEN_TOKEN") +// } +// authentication { +// basic(BasicAuthentication) +// } +// } + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..3312ff8 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Gradle Properties + org.gradle.jvmargs=-Xmx6G + +# Fabric Basic Properties + # https://fabricmc.net/versions.html + loader_version=0.16.2 + +# Mod Properties + mod_id=template_mod + mod_name=TemplateMod + mod_version=1.0.0 + maven_group=me.fallenbreath + archives_base_name=template_mod + +# Global Dependencies + # https://github.com/Fallen-Breath/conditional-mixin +# conditionalmixin_version=0.6.3 + + # https://github.com/LlamaLad7/MixinExtras +# mixinextras_version=0.3.6 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e644113 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a441313 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..b740cf1 --- /dev/null +++ b/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/platforms/jvm/plugins-application/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/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..25da30d --- /dev/null +++ b/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. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +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/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..33e78ef --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,3 @@ +before_install: + - sdk install java 21.0.2-tem + - sdk use java 21.0.2-tem diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..dcf86ee --- /dev/null +++ b/settings.gradle @@ -0,0 +1,35 @@ +import groovy.json.JsonSlurper + +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + maven { + name = 'Jitpack' + url = 'https://jitpack.io' + } + mavenCentral() + gradlePluginPortal() + } + resolutionStrategy { + eachPlugin { + switch (requested.id.id) { + case "com.replaymod.preprocess": { + useModule("com.github.Fallen-Breath:preprocessor:${requested.version}") + break + } + } + } + } +} + +def settings = new JsonSlurper().parseText(file('settings.json').text) +for (String version : settings.versions) { + include(":$version") + + def proj = project(":$version") + proj.projectDir = file("versions/$version") + proj.buildFileName = "../../common.gradle" +} diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..d08fab0 --- /dev/null +++ b/settings.json @@ -0,0 +1,12 @@ +{ + "versions": [ + "1.14.4", + "1.15.2", + "1.16.5", + "1.17.1", + "1.18.2", + "1.19.4", + "1.20.6", + "1.21.1" + ] +} \ No newline at end of file diff --git a/src/main/java/me/fallenbreath/template_mod/TemplateMod.java b/src/main/java/me/fallenbreath/template_mod/TemplateMod.java new file mode 100644 index 0000000..31ed875 --- /dev/null +++ b/src/main/java/me/fallenbreath/template_mod/TemplateMod.java @@ -0,0 +1,55 @@ +/* + * This file is part of the TemplateMod project, licensed under the + * GNU Lesser General Public License v3.0 + * + * Copyright (C) 2023 Fallen_Breath and contributors + * + * TemplateMod is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TemplateMod is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with TemplateMod. If not, see . + */ + +package me.fallenbreath.template_mod; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.metadata.ModMetadata; + +//#if MC >= 11802 +//$$ import com.mojang.logging.LogUtils; +//$$ import org.slf4j.Logger; +//#else +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +//#endif + +public class TemplateMod implements ModInitializer +{ + public static final Logger LOGGER = + //#if MC >= 11802 + //$$ LogUtils.getLogger(); + //#else + LogManager.getLogger(); + //#endif + + public static final String MOD_ID = "template_mod"; + public static String MOD_VERSION = "unknown"; + public static String MOD_NAME = "unknown"; + + @Override + public void onInitialize() + { + ModMetadata metadata = FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow(RuntimeException::new).getMetadata(); + MOD_NAME = metadata.getName(); + MOD_VERSION = metadata.getVersion().getFriendlyString(); + } +} diff --git a/src/main/java/me/fallenbreath/template_mod/mixins/MinecraftServerMixin.java b/src/main/java/me/fallenbreath/template_mod/mixins/MinecraftServerMixin.java new file mode 100644 index 0000000..3214fae --- /dev/null +++ b/src/main/java/me/fallenbreath/template_mod/mixins/MinecraftServerMixin.java @@ -0,0 +1,53 @@ +/* + * This file is part of the TemplateMod project, licensed under the + * GNU Lesser General Public License v3.0 + * + * Copyright (C) 2023 Fallen_Breath and contributors + * + * TemplateMod is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TemplateMod is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with TemplateMod. If not, see . + */ + +package me.fallenbreath.template_mod.mixins; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftServer.class) +public abstract class MinecraftServerMixin +{ + @Inject( + //#if MC >= 11600 + //$$ method = "runServer", + //#else + method = "run", + //#endif + at = @At("HEAD") + ) + private void onRun(CallbackInfo ci) + { + //#if MC >= 11500 + System.err.println("Hello world from mc11500 branch"); + //#elseif MC >= 11400 + //$$ System.err.println("Hello world from mc11400 branch"); + //#endif + + CompoundTag nbt = new CompoundTag(); + nbt.putString("key", "value"); + System.err.println("nbt: " + nbt); + } +} diff --git a/src/main/resources/assets/template_mod/icon.png b/src/main/resources/assets/template_mod/icon.png new file mode 100644 index 0000000..047b91f Binary files /dev/null and b/src/main/resources/assets/template_mod/icon.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..c2ad6c7 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "id": "${id}", + "version": "${version}", + + "name": "${name}", + "description": "Template for my fabric mods", + "authors": [ + "Fallen_Breath" + ], + "contact": { + "homepage": "https://modrinth.com", + "sources": "https://github.com/Fallen-Breath/fabric-mod-template" + }, + + "icon": "assets/template_mod/icon.png", + + "environment": "*", + "entrypoints": { + "main": [ + "me.fallenbreath.template_mod.TemplateMod" + ] + }, + "mixins": [ + "template_mod.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.11.4", + "minecraft": "${minecraft_dependency}" + } +} diff --git a/src/main/resources/template_mod.mixins.json b/src/main/resources/template_mod.mixins.json new file mode 100644 index 0000000..ec9fdd3 --- /dev/null +++ b/src/main/resources/template_mod.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "me.fallenbreath.template_mod.mixins", + "compatibilityLevel": "{{COMPATIBILITY_LEVEL}}", + "mixins": [ + "MinecraftServerMixin" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/versions/1.14.4/gradle.properties b/versions/1.14.4/gradle.properties new file mode 100644 index 0000000..d3776dd --- /dev/null +++ b/versions/1.14.4/gradle.properties @@ -0,0 +1,14 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.14.4 + minecraft_version=1.14.4 + yarn_mappings=1.14.4+build.18 + +# Fabric Mod Metadata + minecraft_dependency=1.14.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.14.4 + +# Dependencies + # fabric_api_version=0.28.5+1.14 diff --git a/versions/1.15.2/gradle.properties b/versions/1.15.2/gradle.properties new file mode 100644 index 0000000..caee1d2 --- /dev/null +++ b/versions/1.15.2/gradle.properties @@ -0,0 +1,14 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.15.2 + minecraft_version=1.15.2 + yarn_mappings=1.15.2+build.17 + +# Fabric Mod Metadata + minecraft_dependency=1.15.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.15.2 + +# Dependencies + # fabric_api_version=0.28.5+1.15 diff --git a/versions/1.16.5/gradle.properties b/versions/1.16.5/gradle.properties new file mode 100644 index 0000000..07e18e1 --- /dev/null +++ b/versions/1.16.5/gradle.properties @@ -0,0 +1,15 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.16.5 + minecraft_version=1.16.5 + yarn_mappings=1.16.5+build.10 + +# Fabric Mod Metadata + minecraft_dependency=1.16.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.16.4\n1.16.5 + +# Dependencies + # fabric_api_version=0.42.0+1.16 + diff --git a/versions/1.17.1/gradle.properties b/versions/1.17.1/gradle.properties new file mode 100644 index 0000000..3dae319 --- /dev/null +++ b/versions/1.17.1/gradle.properties @@ -0,0 +1,15 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.17.1 + minecraft_version=1.17.1 + yarn_mappings=1.17.1+build.65 + +# Fabric Mod Metadata + minecraft_dependency=1.17.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.17.1 + +# Dependencies + # fabric_api_version=0.46.1+1.17 + diff --git a/versions/1.18.2/gradle.properties b/versions/1.18.2/gradle.properties new file mode 100644 index 0000000..6ee521a --- /dev/null +++ b/versions/1.18.2/gradle.properties @@ -0,0 +1,14 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.18.2 + minecraft_version=1.18.2 + yarn_mappings=1.18.2+build.4 + +# Fabric Mod Metadata + minecraft_dependency=1.18.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.18.2 + +# Dependencies + # fabric_api_version=0.76.0+1.18.2 diff --git a/versions/1.19.4/gradle.properties b/versions/1.19.4/gradle.properties new file mode 100644 index 0000000..8bfbb95 --- /dev/null +++ b/versions/1.19.4/gradle.properties @@ -0,0 +1,14 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.19.4 + minecraft_version=1.19.4 + yarn_mappings=1.19.4+build.2 + +# Fabric Mod Metadata + minecraft_dependency=1.19.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.19.4 + +# Dependencies + # fabric_api_version=0.87.2+1.19.4 diff --git a/versions/1.20.6/gradle.properties b/versions/1.20.6/gradle.properties new file mode 100644 index 0000000..6b3c91a --- /dev/null +++ b/versions/1.20.6/gradle.properties @@ -0,0 +1,14 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.20.6 + minecraft_version=1.20.6 + yarn_mappings=1.20.6+build.3 + +# Fabric Mod Metadata + minecraft_dependency=1.20.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.20.6 + +# Dependencies + # fabric_api_version=0.100.4+1.20.6 \ No newline at end of file diff --git a/versions/1.21.1/gradle.properties b/versions/1.21.1/gradle.properties new file mode 100644 index 0000000..24b2c75 --- /dev/null +++ b/versions/1.21.1/gradle.properties @@ -0,0 +1,14 @@ +# Fabric Properties + # check these on https://fallen-breath.github.io/fabric-versions/?&version=1.21.1 + minecraft_version=1.21.1 + yarn_mappings=1.21.1+build.3 + +# Fabric Mod Metadata + minecraft_dependency=1.21.x + +# Build Information + # The target mc versions for the mod during mod publishing, separated with \n + game_versions=1.21\n1.21.1 + +# Dependencies + # fabric_api_version=0.102.1+1.21.1 \ No newline at end of file diff --git a/versions/mainProject b/versions/mainProject new file mode 100644 index 0000000..4761f0e --- /dev/null +++ b/versions/mainProject @@ -0,0 +1 @@ +1.15.2 \ No newline at end of file