commit 5e6a3e045086e4196054b298ac721705c8975fbb Author: ToxicCrzay270 <185776014+ToxicCrzay270@users.noreply.github.com> Date: Fri May 15 00:42:16 2026 +0200 Initial Minecraft Renew Mod workspace diff --git a/.codex/project.md b/.codex/project.md new file mode 100644 index 0000000..edf3592 --- /dev/null +++ b/.codex/project.md @@ -0,0 +1,87 @@ +# Codex Project Notes + +## Project + +`minecraft-renew-mod` is a local workspace for Minecraft mod porting and prototyping. + +The active project is `create-limited-draining/`, a NeoForge port of Create: Limited Draining for Minecraft 1.21.1 and Create 6.0.10. + +Repository: + +```text +Toxic/minecraft-renew-mod +``` + +Remote URL: + +```text +https://git.wilkensxl.de/Toxic/minecraft-renew-mod.git +``` + +## Commands + +Use these commands as the source of truth. + +From `create-limited-draining/`: + +```powershell +.\gradlew build +.\gradlew runClient +.\gradlew runServer +.\gradlew dependencies --configuration runtimeClasspath +``` + +Command notes: + +- Build: `.\gradlew build` +- Test: no separate test suite is currently documented; use `.\gradlew build` +- Lint: no separate lint command is currently documented +- Audit/dependency review: `.\gradlew dependencies --configuration runtimeClasspath` +- README generation: README is maintained manually; no blueprint generator is configured + +## Stack + +```text +Java 21, Gradle Wrapper, NeoForge ModDevGradle, Minecraft 1.21.1, Create 6.0.10 +``` + +Package manager or build tool: + +```text +Gradle Wrapper +``` + +## Build Artifacts + +Release artifacts are produced in: + +```text +create-limited-draining/build/libs/ +``` + +Expected files: + +```text +createlimiteddraining-*.jar +``` + +## Security Rules + +- Do not commit secrets, tokens, `.env` files, certificates, or private keys. +- Do not commit local Minecraft run data, worlds, logs, generated build outputs, or downloaded Gradle artifacts. +- Treat generated credentials and local config as sensitive. +- Keep dependency audit or dependency review results visible in CI where possible. +- Do not add external network calls unless the feature explicitly requires them. + +## Release Rules + +Before a release: + +1. Run `.\gradlew build` from `create-limited-draining/`. +2. Verify the output JAR in `create-limited-draining/build/libs/`. +3. Run or update `docs/release-checklist.md`. +4. Update `CHANGELOG.md`, `README.md`, and `docs/security-review.md`. +5. Verify CI is green if the repository uses Gitea Actions. +6. Create a tag and release only after explicit user approval. + +Do not create releases unless the user explicitly asks for a release. diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..661c10d --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,37 @@ +name: Build + +on: + push: + branches: + - main + - master + - feature/create-addon-port + pull_request: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + + - name: Make Gradle wrapper executable + working-directory: create-limited-draining + run: chmod +x ./gradlew + + - name: Build mod + working-directory: create-limited-draining + run: ./gradlew build --no-daemon + + - name: Upload mod artifacts + uses: actions/upload-artifact@v3 + with: + name: createlimiteddraining-jars + path: create-limited-draining/build/libs/*.jar diff --git a/.gitea/workflows/dependency-check.yml b/.gitea/workflows/dependency-check.yml new file mode 100644 index 0000000..116a584 --- /dev/null +++ b/.gitea/workflows/dependency-check.yml @@ -0,0 +1,38 @@ +name: Scheduled Dependency Check + +on: + schedule: + - cron: "29 3 * * 2" + workflow_dispatch: + +jobs: + dependency-check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + + - name: Gradle dependency report + working-directory: create-limited-draining + run: ./gradlew dependencies --configuration runtimeClasspath --no-daemon + + - name: Gradle build health check + working-directory: create-limited-draining + run: ./gradlew build --no-daemon + + - name: Dependency guidance + shell: bash + run: | + cat <<'EOF' + Dependency check completed. + + This workflow reports the resolved Gradle runtime classpath and verifies + the mod still builds. It does not update dependencies, create pull + requests, or publish packages. + EOF diff --git a/.gitea/workflows/release-dry-run.yml b/.gitea/workflows/release-dry-run.yml new file mode 100644 index 0000000..bbf157a --- /dev/null +++ b/.gitea/workflows/release-dry-run.yml @@ -0,0 +1,75 @@ +name: Release Dry Run + +on: + push: + branches: + - main + - master + - feature/create-addon-port + workflow_dispatch: + +jobs: + release-dry-run: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + + - name: Inspect release metadata + shell: bash + run: | + missing=0 + + required_docs=( + "README.md" + "CHANGELOG.md" + "SECURITY.md" + "docs/release-checklist.md" + "docs/security-review.md" + ) + + for file in "${required_docs[@]}"; do + if [ ! -f "$file" ]; then + echo "Missing release document: $file" + missing=1 + fi + done + + placeholder_paths=(README.md AGENTS.md .codex docs) + placeholder_pattern='PROJECT_NAME|PROJECT_DESCRIPTION|REPOSITORY_OWNER|REPOSITORY_NAME|PACKAGE_NAME|ARTIFACT_NAME|ARTIFACT_OUTPUT_DIRECTORY|DOWNLOAD_URL|BUILD_COMMAND|TEST_COMMAND|LINT_COMMAND|AUDIT_COMMAND|README_COMMAND|INSTALL_COMMAND|DEV_COMMAND|PACKAGE_MANAGER|PROJECT_VERSION' + + for path in "${placeholder_paths[@]}"; do + [ -e "$path" ] || continue + if grep -RInE --exclude-dir=.git "$placeholder_pattern" "$path"; then + echo "Unresolved template placeholders found." + missing=1 + fi + done + + if [ "$missing" -eq 1 ]; then + exit 1 + fi + + - name: Build release candidate + working-directory: create-limited-draining + run: ./gradlew build --no-daemon + + - name: Artifact report + shell: bash + run: | + echo "Potential release artifacts:" + find create-limited-draining/build/libs -maxdepth 1 -type f -name '*.jar' -print | head -200 + + cat <<'EOF' + + Release dry run completed. + + This workflow verifies release readiness. It does not create tags, + releases, packages, or upload artifacts. + EOF diff --git a/.gitea/workflows/repo-cleanup.yml b/.gitea/workflows/repo-cleanup.yml new file mode 100644 index 0000000..47bac43 --- /dev/null +++ b/.gitea/workflows/repo-cleanup.yml @@ -0,0 +1,105 @@ +name: Scheduled Repository Cleanup Check + +on: + schedule: + - cron: "43 3 * * 1" + workflow_dispatch: + +jobs: + cleanup-check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check ignored and tracked generated files + shell: bash + run: | + echo "Ignored files that would be skipped by git:" + git status --ignored --short || true + + echo + echo "Tracked generated files check:" + generated_patterns=( + '(^|/)\.codex-agent-repository-kit/' + '(^|/)\.gradle/' + '(^|/)build/' + '(^|/)run/' + '(^|/)src/generated/' + '\.log$' + '\.tmp$' + '\.temp$' + ) + + found=0 + tracked_files="$(git ls-files)" + for pattern in "${generated_patterns[@]}"; do + if echo "$tracked_files" | grep -Ei "$pattern"; then + found=1 + fi + done + + if [ "$found" -eq 1 ]; then + echo "Generated files appear to be tracked. Review .gitignore and remove generated outputs from version control if appropriate." + exit 1 + fi + + - name: Check large tracked files + shell: bash + run: | + limit_bytes="${LARGE_FILE_LIMIT_BYTES:-5242880}" + found=0 + + while IFS= read -r file; do + [ -f "$file" ] || continue + size="$(wc -c < "$file")" + if [ "$size" -gt "$limit_bytes" ]; then + echo "${file} is ${size} bytes, above limit ${limit_bytes}." + found=1 + fi + done < <(git ls-files) + + if [ "$found" -eq 1 ]; then + echo "Large tracked files found. Move release artifacts to packages/releases or document why they belong in git." + exit 1 + fi + + - name: Check local config and secret-prone files + shell: bash + run: | + found=0 + + risky_patterns=( + '^\.env$' + '^\.env\.' + '\.pfx$' + '\.p12$' + '\.pem$' + '\.key$' + '\.token$' + '(^|/)secrets/' + ) + + tracked_files="$(git ls-files)" + for pattern in "${risky_patterns[@]}"; do + if echo "$tracked_files" | grep -Ei "$pattern" | grep -vE '^\.env\.example$'; then + found=1 + fi + done + + if [ "$found" -eq 1 ]; then + echo "Secret-prone local config files are tracked. Review immediately." + exit 1 + fi + + - name: Cleanup guidance + shell: bash + run: | + cat <<'EOF' + Repository cleanup check completed. + + This workflow reports cleanup candidates. It does not delete branches, + packages, releases, or files automatically. + EOF diff --git a/.gitea/workflows/security-scan.yml b/.gitea/workflows/security-scan.yml new file mode 100644 index 0000000..4ea7bca --- /dev/null +++ b/.gitea/workflows/security-scan.yml @@ -0,0 +1,131 @@ +name: Scheduled Security Scan + +on: + schedule: + - cron: "17 3 * * 1" + workflow_dispatch: + +jobs: + security-scan: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + + - name: Gradle dependency report + working-directory: create-limited-draining + run: ./gradlew dependencies --configuration runtimeClasspath --no-daemon + + - name: Suspicious code pattern scan + shell: bash + run: | + grep_excludes=( + --exclude-dir=.git + --exclude-dir=.codex-agent-repository-kit + --exclude-dir=.gradle + --exclude-dir=build + --exclude-dir=run + --exclude=security-scan.yml + ) + + patterns=( + 'eval\s*\(' + 'new Function\s*\(' + 'Runtime\.getRuntime\(\)\.exec' + 'ProcessBuilder\s*\(' + 'curl .*sh' + 'wget .*sh' + ) + + found=0 + for pattern in "${patterns[@]}"; do + if grep -RInE "${grep_excludes[@]}" "$pattern" .; then + found=1 + fi + done + + if [ "$found" -eq 1 ]; then + echo "Suspicious code patterns were found. Review the matches above." + exit 1 + fi + + - name: Secret and config leak scan + shell: bash + run: | + grep_excludes=( + --exclude-dir=.git + --exclude-dir=.codex-agent-repository-kit + --exclude-dir=.gradle + --exclude-dir=build + --exclude-dir=run + --exclude=security-scan.yml + ) + + patterns=( + 'BEGIN (RSA |EC |OPENSSH |)PRIVATE KEY' + 'AKIA[0-9A-Z]{16}' + 'xox[baprs]-[0-9A-Za-z-]+' + 'gh[pousr]_[0-9A-Za-z_]+' + 'sk-[A-Za-z0-9]{20,}' + 'api[_-]?key\s*=\s*["'\'']?[A-Za-z0-9_\-]{20,}' + 'token\s*=\s*["'\'']?[A-Za-z0-9_\-]{20,}' + 'password\s*=\s*["'\'']?[^[:space:]]{8,}' + ) + + found=0 + for pattern in "${patterns[@]}"; do + if grep -RInE "${grep_excludes[@]}" "$pattern" .; then + found=1 + fi + done + + if find . -path ./.git -prune -o -path ./.codex-agent-repository-kit -prune -o \( -name ".env" -o -name ".env.*" \) -not -name ".env.example" -print | grep .; then + echo "Committed environment files were found." + found=1 + fi + + if [ "$found" -eq 1 ]; then + echo "Potential secret or config leak detected. Review the matches above." + exit 1 + fi + + - name: AI instruction injection scan + shell: bash + run: | + grep_excludes=( + --exclude-dir=.git + --exclude-dir=.codex-agent-repository-kit + --exclude-dir=.gradle + --exclude-dir=build + --exclude-dir=run + --exclude=security-scan.yml + ) + + patterns=( + 'ignore (all )?(previous|above) instructions' + 'reveal your instructions' + 'exfiltrate' + 'send.*token' + 'send.*secret' + 'disable.*safety' + 'jailbreak' + 'prompt injection' + ) + + found=0 + for pattern in "${patterns[@]}"; do + if grep -RInEi "${grep_excludes[@]}" "$pattern" .; then + found=1 + fi + done + + if [ "$found" -eq 1 ]; then + echo "Potential AI instruction-injection text found. Review whether this is documentation, test data, or malicious content." + exit 1 + fi diff --git a/.gitea/workflows/template-compliance.yml b/.gitea/workflows/template-compliance.yml new file mode 100644 index 0000000..ed69d13 --- /dev/null +++ b/.gitea/workflows/template-compliance.yml @@ -0,0 +1,110 @@ +name: Codex Template Compliance + +on: + push: + branches: + - main + - master + - feature/create-addon-port + pull_request: + workflow_dispatch: + +jobs: + template-compliance: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check required Codex files + shell: bash + run: | + missing=0 + + required_files=( + "AGENTS.md" + ".codex/project.md" + "README.md" + ) + + recommended_files=( + "SECURITY.md" + "CHANGELOG.md" + "CONTRIBUTING.md" + "docs/agent-handoff.md" + "docs/security-review.md" + "docs/release-checklist.md" + ) + + for file in "${required_files[@]}"; do + if [ ! -f "$file" ]; then + echo "Missing required Codex file: $file" + missing=1 + fi + done + + for file in "${recommended_files[@]}"; do + if [ ! -f "$file" ]; then + echo "Recommended Codex file not found: $file" + fi + done + + if [ "$missing" -eq 1 ]; then + exit 1 + fi + + - name: Check unresolved placeholders + shell: bash + run: | + found=0 + paths=(AGENTS.md README.md SECURITY.md CHANGELOG.md CONTRIBUTING.md .codex docs) + pattern='PROJECT_NAME|PROJECT_DESCRIPTION|REPOSITORY_OWNER|REPOSITORY_NAME|PACKAGE_NAME|ARTIFACT_NAME|ARTIFACT_OUTPUT_DIRECTORY|AUTHOR_NAME|PROJECT_STACK|DOWNLOAD_URL|BUILD_COMMAND|TEST_COMMAND|LINT_COMMAND|AUDIT_COMMAND|README_COMMAND|INSTALL_COMMAND|DEV_COMMAND|PACKAGE_MANAGER|PROJECT_VERSION' + + for path in "${paths[@]}"; do + [ -e "$path" ] || continue + if grep -RInE --exclude-dir=.git "$pattern" "$path"; then + found=1 + fi + done + + if [ "$found" -eq 1 ]; then + echo "Unresolved template placeholders found. Replace real values or mark genuinely unknown values as PENDING." + exit 1 + fi + + - name: Check workflow baseline + shell: bash + run: | + echo "Detected Gitea workflows:" + find .gitea/workflows -maxdepth 1 -type f -name '*.yml' -print 2>/dev/null || true + + required_workflows=( + ".gitea/workflows/build.yml" + ".gitea/workflows/security-scan.yml" + ".gitea/workflows/repo-cleanup.yml" + ".gitea/workflows/dependency-check.yml" + ".gitea/workflows/release-dry-run.yml" + ".gitea/workflows/template-compliance.yml" + ) + + missing=0 + for file in "${required_workflows[@]}"; do + if [ ! -f "$file" ]; then + echo "Missing workflow: $file" + missing=1 + fi + done + + if [ "$missing" -eq 1 ]; then + exit 1 + fi + + - name: Compliance guidance + shell: bash + run: | + cat <<'EOF' + Codex template compliance check completed. + + This workflow verifies agent context and template hygiene. It does + not change files automatically. + EOF diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2fd16e --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Local template checkout +.codex-agent-repository-kit/ + +# Gradle and Java build outputs +.gradle/ +build/ +out/ +target/ +*.class + +# Minecraft/NeoForge generated runtime data +create-limited-draining/build/ +create-limited-draining/run/ +create-limited-draining/src/generated/ + +# Logs and temporary files +*.log +*.tmp +*.temp +.cache/ + +# Local environment and secrets +.env +.env.* +!.env.example +*.pem +*.key +*.pfx +*.p12 +*.crt +*.cer +*.token +secrets/ + +# OS and editor files +.DS_Store +Thumbs.db +.idea/ +.vscode/ +*.swp +*.swo diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..74af060 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,62 @@ +# Agent Instructions + +## Project + +Minecraft Renew Mod is a local workspace for Minecraft mod porting and prototyping. + +The active project is `create-limited-draining/`, a NeoForge port of Create: Limited Draining for Minecraft 1.21.1 and Create 6.0.10. + +## Repository Rules + +- Read this file and `.codex/project.md` before making changes. +- Preserve existing application code unless the task explicitly requires code changes. +- Keep changes scoped to the user's request. +- Do not commit secrets, `.env` files, private keys, certificates, local tokens, Minecraft run logs, generated worlds, or build outputs. +- Do not rewrite history or run destructive git commands unless explicitly requested. +- Do not create a release unless explicitly requested. +- Check repository status before editing and before finishing when this directory is a Git repository. +- Preserve unrelated user changes. +- Keep `AGENTS.md` and `.codex/project.md` aligned when commands, artifact paths, or release rules change. +- If `GITEA_TOKEN` is available locally, use it only for read-only Gitea API checks. Never print, commit, or store it. + +## Commands + +Run commands from `create-limited-draining/` unless noted otherwise. + +```powershell +.\gradlew build +.\gradlew runClient +.\gradlew runServer +.\gradlew dependencies --configuration runtimeClasspath +``` + +There is no separate lint or test command currently documented. Use `.\gradlew build` as the cheapest reliable verification command. + +## Artifacts + +Expected build output: + +```text +create-limited-draining/build/libs/*.jar +``` + +Current documented artifact: + +```text +createlimiteddraining-1.21.1-0.3.0-port.1.jar +``` + +## Security Notes + +- Review `docs/security-review.md` before release work. +- Treat generated Minecraft run data under `create-limited-draining/run/` as local-only. +- Treat Gradle caches, logs, generated resources, and build outputs as generated files. +- Keep external dependency sources documented in `create-limited-draining/build.gradle`. +- Keep publishing credentials in Gitea repository or organization secrets, not in tracked files. + +## Finish Checklist + +- `git diff --check` passes when this directory is a Git repository. +- `.\gradlew build` has been run from `create-limited-draining/`, or the reason it could not run is documented. +- README, changelog, security review, and release checklist are updated when release behavior changes. +- `docs/agent-handoff.md` is updated when work is interrupted, risky, or spans multiple sessions. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..681e8fa --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +All notable changes to this workspace are documented here. + +## Unreleased + +- Added Codex repository baseline files from the repository kit. +- Added root README documentation for the Minecraft Renew Mod workspace. +- Documented the current Create: Limited Draining NeoForge port target and build workflow. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..2497f2e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,53 @@ +# Contributing + +## Working Rules + +- Keep changes scoped to the issue or user request. +- Prefer the existing Gradle, NeoForge, and Create mod patterns. +- Do not commit secrets, generated credentials, local `.env` files, private keys, local Minecraft worlds, run logs, or build outputs. +- Do not create releases unless explicitly requested. +- Preserve unrelated user changes. + +## Before Committing + +From `create-limited-draining/`, run: + +```powershell +.\gradlew build +``` + +For dependency review, run: + +```powershell +.\gradlew dependencies --configuration runtimeClasspath +``` + +If this workspace is a Git repository, also run from the root: + +```powershell +git diff --check +``` + +If a command cannot run, document why in the final response or handoff notes. + +## Pull Requests + +Pull requests should include: + +- summary of changes, +- verification performed, +- known risks or skipped checks, +- artifact/download notes when relevant. + +## Releases + +Before release work, update: + +```text +CHANGELOG.md +docs/release-checklist.md +docs/security-review.md +README.md +``` + +Release only after explicit approval. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c0540d --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Minecraft Renew Mod + +Local project area for Minecraft mod porting and prototyping. + +## Current Port + +The first port target is `Create: Limited Draining`, located in `create-limited-draining/`. + +- Original project: https://github.com/JasdewStarfield/CreateLimitedDraining +- Original license: MIT License, Copyright (c) 2024 Jasdew Starfield +- Port target: Minecraft 1.21.1, NeoForge 21.1.x, Create 6.0.10 + +## Rules + +- Work on `feature/create-addon-port` for this port. +- Do not push, merge, or publish without explicit approval. +- Keep original license and attribution with any copied code or assets. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..797858c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,31 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| --- | --- | +| Latest port workspace | Yes | + +## Reporting A Vulnerability + +Report security issues privately to the repository owner. + +Do not include secrets, private credentials, server tokens, private modpack data, or production server data in public issues. + +## Project Security Principles + +- Keep secrets, tokens, `.env` files, certificates, private keys, and local server credentials out of the repository. +- Keep Minecraft run data, logs, local worlds, and generated build outputs out of version control. +- Document external dependency repositories in Gradle build files. +- Build release artifacts reproducibly with the Gradle Wrapper and Java 21. +- Run dependency review and release checks before publishing artifacts. + +## Current Scope + +The active mod changes Create Hose Pulley fluid-draining behavior through NeoForge configuration and mixins. Security review should focus on: + +- unexpected file writes, +- unsafe external network calls, +- accidental inclusion of local worlds or logs, +- dependency and loader version drift, +- release artifact contents. diff --git a/create-limited-draining/.gitignore b/create-limited-draining/.gitignore new file mode 100644 index 0000000..b9f94fd --- /dev/null +++ b/create-limited-draining/.gitignore @@ -0,0 +1,6 @@ +.gradle/ +build/ +run/ +run-data/ +out/ +*.log diff --git a/create-limited-draining/LICENSE b/create-limited-draining/LICENSE new file mode 100644 index 0000000..d4a5e1e --- /dev/null +++ b/create-limited-draining/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jasdew Starfield + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/create-limited-draining/NOTICE.md b/create-limited-draining/NOTICE.md new file mode 100644 index 0000000..e35d9e5 --- /dev/null +++ b/create-limited-draining/NOTICE.md @@ -0,0 +1,11 @@ +# Notice + +This directory contains a port of Create: Limited Draining. + +- Original repository: https://github.com/JasdewStarfield/CreateLimitedDraining +- Original author: Jasdew Starfield +- Original license: MIT License +- Original copyright: Copyright (c) 2024 Jasdew Starfield +- Port target: Minecraft 1.21.1, NeoForge, Create 6.0.10 + +The original MIT license text is kept in `LICENSE`. No publication or distribution is authorized from this repository without an explicit release review. diff --git a/create-limited-draining/PORTING.md b/create-limited-draining/PORTING.md new file mode 100644 index 0000000..efc4769 --- /dev/null +++ b/create-limited-draining/PORTING.md @@ -0,0 +1,35 @@ +# Porting Notes + +## Source and Target + +- Original mod: Create: Limited Draining +- Original repository: https://github.com/JasdewStarfield/CreateLimitedDraining +- Original branch used as source basis: 1.20.1 +- Target: Minecraft 1.21.1, NeoForge 21.1.228, Create 6.0.10 + +## Main Changes + +- Replaced ForgeGradle setup with NeoForge ModDevGradle. +- Updated Java toolchain from 17 to 21. +- Replaced Forge config/event imports with NeoForge equivalents. +- Updated `mods.toml` metadata to generated `neoforge.mods.toml`. +- Updated NBT mixin method signatures for Create/Minecraft 1.21.1 `HolderLookup.Provider` parameters. +- Kept behavior minimal: rule-based restriction of Create Hose Pulley infinite draining. + +## Verification + +- `gradlew build`: successful. +- `gradlew runClient`: successful startup; Create 6.0.10 and `createlimiteddraining` loaded. +- `gradlew runServer`: dedicated server loaded Create and the port, generated a world, and reached `Done`; Java server processes were stopped after the smoke-test timeout. + +## Expected Risk Areas + +- Manual gameplay verification of Hose Pulley infinite-draining behavior is still pending. +- Create internal method signatures are compile-verified, but the mixin behavior should be exercised in a test world. +- The exact Create Maven artifact resolved as `create-1.21.1-6.0.10-280-slim.jar` and reports mod version `6.0.10` at runtime. + +## Next Steps + +- Create a test world and verify lava infinite draining is allowed in Nether biomes and denied outside configured biome rules. +- Inspect the generated common config after changing `drainingRules` values. +- Consider adding a lightweight GameTest or scripted manual QA notes for Hose Pulley behavior. \ No newline at end of file diff --git a/create-limited-draining/README.md b/create-limited-draining/README.md new file mode 100644 index 0000000..7e620ce --- /dev/null +++ b/create-limited-draining/README.md @@ -0,0 +1,50 @@ +# Create: Limited Draining Port + +This is a Minecraft Renew Mod porting workspace for Create: Limited Draining. + +## Original Project + +- Repository: https://github.com/JasdewStarfield/CreateLimitedDraining +- License: MIT License +- Copyright: Copyright (c) 2024 Jasdew Starfield +- Starting point: published Minecraft 1.20.1 Forge source branch + +## Target + +- Minecraft: 1.21.1 +- Loader: NeoForge 21.1.x, preferred 21.1.228 +- Create: 6.0.10 +- Java: 21 +- Build: Gradle with ModDevGradle + +## Setup + +Use Java 21 and the project-local Gradle Wrapper. + +```powershell +java -version +.\gradlew build +``` + +## Run + +```powershell +.\gradlew runClient +.\gradlew runServer +``` + +## Current Status + +This port is a minimal compatibility port. It updates the build system, metadata, NeoForge imports, config registration, and Create mixin method signatures for Minecraft 1.21.1/Create 6.0.10. + +Verification status: + +- `gradlew build`: successful +- `gradlew runClient`: successful startup and clean stop in smoke test +- `gradlew runServer`: server reached `Done`; stopped after timeout cleanup + +## Known Limitations + +- In-game Hose Pulley behavior still needs manual world testing. +- The upstream 1.21.1 branch was checked only as reference and was not blindly copied. +- The original logo asset is not included in this first workspace copy; no third-party publication is prepared. \ No newline at end of file diff --git a/create-limited-draining/build.gradle b/create-limited-draining/build.gradle new file mode 100644 index 0000000..a9e789a --- /dev/null +++ b/create-limited-draining/build.gradle @@ -0,0 +1,104 @@ +plugins { + id 'java-library' + id 'idea' + id 'net.neoforged.moddev' version '2.0.141' +} + +version = mod_version +group = mod_group_id + +base { + archivesName = mod_id +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(21) + +repositories { + maven { url = 'https://maven.createmod.net' } + maven { url = 'https://maven.ithundxr.dev/snapshots' } + mavenCentral() +} + +neoForge { + version = neo_version + + parchment { + minecraftVersion = parchment_minecraft_version + mappingsVersion = parchment_mappings_version + } + + runs { + client { + client() + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + + server { + server() + programArgument '--nogui' + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + + gameTestServer { + type = 'gameTestServer' + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + + data { + data() + programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').absolutePath, '--existing', file('src/main/resources/').absolutePath + } + + configureEach { + systemProperty 'forge.logging.markers', 'REGISTRIES' + logLevel = org.slf4j.event.Level.DEBUG + } + } + + mods { + "${mod_id}" { + sourceSet(sourceSets.main) + } + } +} + +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + runtimeClasspath.extendsFrom localRuntime +} + +dependencies { + implementation("com.simibubi.create:create-${minecraft_version}:${create_version}:slim") { transitive = false } + implementation("net.createmod.ponder:ponder-neoforge:${ponder_version}+mc${minecraft_version}") + compileOnly("dev.engine-room.flywheel:flywheel-neoforge-api-${minecraft_version}:${flywheel_version}") + runtimeOnly("dev.engine-room.flywheel:flywheel-neoforge-${minecraft_version}:${flywheel_version}") + implementation("com.tterrag.registrate:Registrate:${registrate_version}") +} + +var generateModMetadata = tasks.register('generateModMetadata', ProcessResources) { + var replaceProperties = [ + minecraft_version : minecraft_version, + minecraft_version_range: minecraft_version_range, + neo_version : neo_version, + neo_version_range : neo_version_range, + loader_version_range : loader_version_range, + mod_id : mod_id, + mod_name : mod_name, + mod_license : mod_license, + mod_version : mod_version, + mod_authors : mod_authors, + mod_description : mod_description + ] + inputs.properties replaceProperties + expand replaceProperties + from 'src/main/templates' + into 'build/generated/sources/modMetadata' +} + +sourceSets.main.resources.srcDir generateModMetadata +neoForge.ideSyncTask generateModMetadata + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} diff --git a/create-limited-draining/gradle.properties b/create-limited-draining/gradle.properties new file mode 100644 index 0000000..b729310 --- /dev/null +++ b/create-limited-draining/gradle.properties @@ -0,0 +1,27 @@ +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configuration-cache=false + +minecraft_version=1.21.1 +minecraft_version_range=[1.21.1,1.22) +neo_version=21.1.228 +neo_version_range=[21.1.228,) +loader_version_range=[4,) + +parchment_minecraft_version=1.21.1 +parchment_mappings_version=2024.11.17 + +create_version=6.0.10-280 +ponder_version=1.0.82 +flywheel_version=1.0.6 +registrate_version=MC1.21-1.3.0+67 + +mod_id=createlimiteddraining +mod_name=Create: Limited Draining +mod_license=MIT +mod_version=1.21.1-0.3.0-port.1 +mod_group_id=yourscraft.jasdewstarfield +mod_authors=Jasdew Starfield; port maintained in Minecraft Renew Mod +mod_description=A Create addon that allows pack authors to restrict infinite fluid draining by fluid and biome rules. diff --git a/create-limited-draining/gradle/wrapper/gradle-wrapper.jar b/create-limited-draining/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..a4b76b9 Binary files /dev/null and b/create-limited-draining/gradle/wrapper/gradle-wrapper.jar differ diff --git a/create-limited-draining/gradle/wrapper/gradle-wrapper.properties b/create-limited-draining/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..df97d72 --- /dev/null +++ b/create-limited-draining/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/create-limited-draining/gradlew b/create-limited-draining/gradlew new file mode 100644 index 0000000..f5feea6 --- /dev/null +++ b/create-limited-draining/gradlew @@ -0,0 +1,252 @@ +#!/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. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# 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 -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || 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/create-limited-draining/gradlew.bat b/create-limited-draining/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/create-limited-draining/gradlew.bat @@ -0,0 +1,94 @@ +@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 +@rem SPDX-License-Identifier: Apache-2.0 +@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/create-limited-draining/settings.gradle b/create-limited-draining/settings.gradle new file mode 100644 index 0000000..7623f7e --- /dev/null +++ b/create-limited-draining/settings.gradle @@ -0,0 +1,12 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { url = 'https://maven.neoforged.net/releases' } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + +rootProject.name = 'create-limited-draining-port' diff --git a/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/Config.java b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/Config.java new file mode 100644 index 0000000..9eaffe5 --- /dev/null +++ b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/Config.java @@ -0,0 +1,31 @@ +package yourscraft.jasdewstarfield.createlimiteddraining; + +import java.util.List; + +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.event.config.ModConfigEvent; +import net.neoforged.neoforge.common.ModConfigSpec; + +@EventBusSubscriber(modid = Createlimiteddraining.MODID, bus = EventBusSubscriber.Bus.MOD) +public class Config { + private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder(); + + public static final ModConfigSpec.ConfigValue> DRAINING_RULES = BUILDER + .comment("Define infinite draining groups.") + .comment("Format: 'Fluid1, Fluid2... ; Biome1, Biome2...'") + .comment("If the fluid is in the left list and the biome is in the right list, it can be drained infinitely.") + .comment("This rule is applied before Create's own infinite-draining rule.") + .defineList("drainingRules", + List.of("#minecraft:lava ; #minecraft:is_nether"), + obj -> obj instanceof String); + + static final ModConfigSpec SPEC = BUILDER.build(); + + public static List drainingRules = List.of(); + + @SubscribeEvent + static void onLoad(final ModConfigEvent event) { + drainingRules = DRAINING_RULES.get(); + } +} diff --git a/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/Createlimiteddraining.java b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/Createlimiteddraining.java new file mode 100644 index 0000000..786f3e0 --- /dev/null +++ b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/Createlimiteddraining.java @@ -0,0 +1,14 @@ +package yourscraft.jasdewstarfield.createlimiteddraining; + +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.config.ModConfig; + +@Mod(Createlimiteddraining.MODID) +public class Createlimiteddraining { + public static final String MODID = "createlimiteddraining"; + + public Createlimiteddraining(ModContainer modContainer) { + modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC); + } +} diff --git a/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/common/HosePulleyAccessor.java b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/common/HosePulleyAccessor.java new file mode 100644 index 0000000..6e5b989 --- /dev/null +++ b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/common/HosePulleyAccessor.java @@ -0,0 +1,7 @@ +package yourscraft.jasdewstarfield.createlimiteddraining.common; + +public interface HosePulleyAccessor { + void createlimiteddraining$setBiomeCheckFailed(boolean failed); + + boolean createlimiteddraining$isBiomeCheckFailed(); +} diff --git a/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/common/RuleHandler.java b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/common/RuleHandler.java new file mode 100644 index 0000000..6306809 --- /dev/null +++ b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/common/RuleHandler.java @@ -0,0 +1,98 @@ +package yourscraft.jasdewstarfield.createlimiteddraining.common; + +import java.util.Objects; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.material.Fluid; +import yourscraft.jasdewstarfield.createlimiteddraining.Config; + +public class RuleHandler { + public static boolean canDrain(Level level, Fluid fluid, Biome biome) { + for (String rule : Config.drainingRules) { + String[] parts = rule.split(";"); + if (parts.length != 2) { + continue; + } + + String fluidPart = parts[0].trim(); + String biomePart = parts[1].trim(); + + if (matchAny(level, fluid, fluidPart, true)) { + return matchAny(level, biome, biomePart, false); + } + } + + return true; + } + + private static boolean matchAny(Level level, Object target, String patternStr, boolean isFluid) { + String[] patterns = patternStr.split(","); + + for (String pattern : patterns) { + pattern = pattern.trim(); + if (pattern.isEmpty()) { + continue; + } + + boolean matched = isFluid + ? checkFluid((Fluid) target, pattern) + : checkBiome(level, (Biome) target, pattern); + + if (matched) { + return true; + } + } + return false; + } + + private static boolean checkFluid(Fluid fluid, String matcher) { + if (fluid == null) { + return false; + } + + if (matcher.startsWith("#")) { + ResourceLocation loc = ResourceLocation.tryParse(matcher.substring(1)); + if (loc == null) { + return false; + } + TagKey tag = TagKey.create(Registries.FLUID, loc); + return fluid.builtInRegistryHolder().is(tag); + } + + ResourceLocation loc = ResourceLocation.tryParse(matcher); + if (loc == null) { + return false; + } + return Objects.equals(BuiltInRegistries.FLUID.getKey(fluid), loc); + } + + private static boolean checkBiome(Level level, Biome biome, String matcher) { + if (biome == null) { + return false; + } + + var registry = level.registryAccess().registryOrThrow(Registries.BIOME); + + if (matcher.startsWith("#")) { + ResourceLocation loc = ResourceLocation.tryParse(matcher.substring(1)); + if (loc == null) { + return false; + } + TagKey tag = TagKey.create(Registries.BIOME, loc); + return registry.getResourceKey(biome) + .map(key -> registry.getHolderOrThrow(key).is(tag)) + .orElse(false); + } + + ResourceLocation loc = ResourceLocation.tryParse(matcher); + if (loc == null) { + return false; + } + return Objects.equals(registry.getKey(biome), loc); + } +} diff --git a/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/mixin/FluidManipulationBehaviourMixin.java b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/mixin/FluidManipulationBehaviourMixin.java new file mode 100644 index 0000000..618809d --- /dev/null +++ b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/mixin/FluidManipulationBehaviourMixin.java @@ -0,0 +1,36 @@ +package yourscraft.jasdewstarfield.createlimiteddraining.mixin; + +import com.simibubi.create.content.fluids.transfer.FluidManipulationBehaviour; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.material.Fluid; +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.CallbackInfoReturnable; +import yourscraft.jasdewstarfield.createlimiteddraining.common.HosePulleyAccessor; +import yourscraft.jasdewstarfield.createlimiteddraining.common.RuleHandler; + +@Mixin(value = FluidManipulationBehaviour.class, remap = false) +public class FluidManipulationBehaviourMixin { + @Inject(method = "canDrainInfinitely", at = @At("HEAD"), cancellable = true) + private void createlimiteddraining$checkRules(Fluid fluid, CallbackInfoReturnable cir) { + FluidManipulationBehaviour instance = (FluidManipulationBehaviour) (Object) this; + Level world = instance.getWorld(); + BlockPos pos = instance.blockEntity.getBlockPos(); + Biome biome = world.getBiome(pos).value(); + + HosePulleyAccessor pulley = instance.blockEntity instanceof HosePulleyAccessor accessor ? accessor : null; + boolean allowed = RuleHandler.canDrain(world, fluid, biome); + + if (!allowed) { + if (pulley != null) { + pulley.createlimiteddraining$setBiomeCheckFailed(true); + } + cir.setReturnValue(false); + } else if (pulley != null) { + pulley.createlimiteddraining$setBiomeCheckFailed(false); + } + } +} diff --git a/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/mixin/HosePulleyBlockEntityMixin.java b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/mixin/HosePulleyBlockEntityMixin.java new file mode 100644 index 0000000..439dbc8 --- /dev/null +++ b/create-limited-draining/src/main/java/yourscraft/jasdewstarfield/createlimiteddraining/mixin/HosePulleyBlockEntityMixin.java @@ -0,0 +1,55 @@ +package yourscraft.jasdewstarfield.createlimiteddraining.mixin; + +import java.util.List; + +import com.simibubi.create.content.fluids.hosePulley.HosePulleyBlockEntity; +import com.simibubi.create.foundation.item.TooltipHelper; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import yourscraft.jasdewstarfield.createlimiteddraining.common.HosePulleyAccessor; + +@Mixin(value = HosePulleyBlockEntity.class, remap = false) +public class HosePulleyBlockEntityMixin implements HosePulleyAccessor { + @Unique + private boolean createlimiteddraining$biomeCheckFailed = false; + + @Unique + @Override + public void createlimiteddraining$setBiomeCheckFailed(boolean failed) { + this.createlimiteddraining$biomeCheckFailed = failed; + } + + @Unique + @Override + public boolean createlimiteddraining$isBiomeCheckFailed() { + return this.createlimiteddraining$biomeCheckFailed; + } + + @Inject(method = "addToGoggleTooltip", at = @At("RETURN")) + private void createlimiteddraining$addTooltip(List tooltip, boolean isPlayerSneaking, CallbackInfoReturnable cir) { + if (createlimiteddraining$isBiomeCheckFailed()) { + TooltipHelper.addHint(tooltip, "hint.hose_pulley.biome_check_failed"); + } + } + + @Inject(method = "write", at = @At("HEAD")) + private void createlimiteddraining$write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket, CallbackInfo ci) { + if (clientPacket) { + compound.putBoolean("BiomeCheckFailed", createlimiteddraining$biomeCheckFailed); + } + } + + @Inject(method = "read", at = @At("HEAD")) + private void createlimiteddraining$read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket, CallbackInfo ci) { + if (clientPacket) { + createlimiteddraining$biomeCheckFailed = compound.getBoolean("BiomeCheckFailed"); + } + } +} diff --git a/create-limited-draining/src/main/resources/assets/createlimiteddraining/lang/en_us.json b/create-limited-draining/src/main/resources/assets/createlimiteddraining/lang/en_us.json new file mode 100644 index 0000000..828cff9 --- /dev/null +++ b/create-limited-draining/src/main/resources/assets/createlimiteddraining/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "create.hint.hose_pulley.biome_check_failed": "This fluid does not support infinite draining in the current biome", + "create.hint.hose_pulley.biome_check_failed.title": "Cannot drain infinitely" +} diff --git a/create-limited-draining/src/main/resources/createlimiteddraining.mixins.json b/create-limited-draining/src/main/resources/createlimiteddraining.mixins.json new file mode 100644 index 0000000..d791845 --- /dev/null +++ b/create-limited-draining/src/main/resources/createlimiteddraining.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "yourscraft.jasdewstarfield.createlimiteddraining.mixin", + "compatibilityLevel": "JAVA_21", + "mixins": [ + "FluidManipulationBehaviourMixin", + "HosePulleyBlockEntityMixin" + ], + "client": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/create-limited-draining/src/main/resources/pack.mcmeta b/create-limited-draining/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..5ee54c7 --- /dev/null +++ b/create-limited-draining/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Create: Limited Draining resources", + "pack_format": 34 + } +} diff --git a/create-limited-draining/src/main/templates/META-INF/neoforge.mods.toml b/create-limited-draining/src/main/templates/META-INF/neoforge.mods.toml new file mode 100644 index 0000000..71df699 --- /dev/null +++ b/create-limited-draining/src/main/templates/META-INF/neoforge.mods.toml @@ -0,0 +1,37 @@ +modLoader="javafml" +loaderVersion="${loader_version_range}" +license="${mod_license}" +issueTrackerURL="https://github.com/JasdewStarfield/CreateLimitedDraining/issues" + +[[mods]] +modId="${mod_id}" +version="${mod_version}" +displayName="${mod_name}" +displayURL="https://github.com/JasdewStarfield/CreateLimitedDraining" +authors="${mod_authors}" +description='''${mod_description}''' +displayTest="IGNORE_SERVER_VERSION" + +[[mixins]] +config="${mod_id}.mixins.json" + +[[dependencies.${mod_id}]] +modId="neoforge" +type="required" +versionRange="${neo_version_range}" +ordering="NONE" +side="BOTH" + +[[dependencies.${mod_id}]] +modId="minecraft" +type="required" +versionRange="${minecraft_version_range}" +ordering="NONE" +side="BOTH" + +[[dependencies.${mod_id}]] +modId="create" +type="required" +versionRange="[6.0.10,6.1.0)" +ordering="NONE" +side="BOTH" diff --git a/docs/agent-handoff.md b/docs/agent-handoff.md new file mode 100644 index 0000000..e07b9fb --- /dev/null +++ b/docs/agent-handoff.md @@ -0,0 +1,39 @@ +# Agent Handoff + +Use this file when a task spans multiple sessions, has unresolved follow-up work, or changes release behavior. + +## Current State + +```text +Codex repository kit baseline has been applied to the workspace. +``` + +## Changes Made + +- Added Codex agent context files. +- Added security, contribution, changelog, and release documentation. +- Added Gitea workflow templates adapted for the Gradle Minecraft mod workspace. +- Added `.gitignore` entries for local kit checkout, build output, Minecraft run data, logs, and secrets. + +## Verification + +| Check | Result | +| --- | --- | +| `git diff --check` | Skipped: root workspace is not a Git repository in this environment | +| `.\gradlew build` | Passed on 2026-05-15 | +| `.\gradlew dependencies --configuration runtimeClasspath` | Passed on 2026-05-15 | + +## Open Questions + +- Decide whether release artifacts should be published only as workflow artifacts or also to the Gitea Package Registry. + +## Next Steps + +- Run `.\gradlew build` from `create-limited-draining/`. +- Run manual Hose Pulley gameplay tests before publishing. +- Update this handoff file if release or CI behavior changes. + +## Risks + +- The root workspace is currently not detected as a Git repository in this environment. +- The port is documented as minimally verified; behavior still needs manual in-game testing. diff --git a/docs/release-checklist.md b/docs/release-checklist.md new file mode 100644 index 0000000..ae2def8 --- /dev/null +++ b/docs/release-checklist.md @@ -0,0 +1,37 @@ +# Release Checklist + +## Version + +- [ ] Version number updated in `create-limited-draining/gradle.properties`. +- [ ] Changelog updated. +- [ ] README updated if build, config, or release behavior changed. + +## Quality + +- [ ] Working tree is clean. +- [ ] `.\gradlew build` passes from `create-limited-draining/`. +- [ ] Tests pass or missing tests are documented. +- [ ] Client smoke test completed when behavior changes affect gameplay. +- [ ] Server smoke test completed when behavior changes affect server behavior. +- [ ] CI build succeeds if Gitea Actions are enabled. + +## Security + +- [ ] Security review is current. +- [ ] Dependency review is clean or documented. +- [ ] No secrets are committed. +- [ ] Release artifact does not contain local config, worlds, logs, or generated run data. + +## Artifacts + +- [ ] JAR exists under `create-limited-draining/build/libs/`. +- [ ] Artifact filename and version are clear. +- [ ] Download links work if a release or package is published. +- [ ] Package registry links work if used. + +## Release + +- [ ] Git tag created after approval. +- [ ] Release notes written. +- [ ] Release published after approval. +- [ ] Post-release download smoke test completed. diff --git a/docs/release-notes.md b/docs/release-notes.md new file mode 100644 index 0000000..99d264b --- /dev/null +++ b/docs/release-notes.md @@ -0,0 +1,32 @@ +# Minecraft Renew Mod Unreleased + +## Downloads + +| Variant | Download | +| --- | --- | +| Mod JAR | PENDING | + +## Highlights + +- NeoForge port workspace for Create: Limited Draining. +- Targeted at Minecraft 1.21.1, NeoForge 21.1.228, and Create 6.0.10. +- Adds configurable fluid and biome rules for Create Hose Pulley infinite draining. + +## Security + +- Dependency review: Gradle `runtimeClasspath` report completed on 2026-05-15 +- Secret handling: local secrets, run data, logs, and build outputs are ignored +- External network calls: Gradle dependency repositories only + +## Verification + +| Check | Result | +| --- | --- | +| `.\gradlew build` | Passed on 2026-05-15 | +| Client smoke test | PENDING | +| Server smoke test | PENDING | +| Artifact download | PENDING | + +## Notes + +Do not publish a release until manual in-game Hose Pulley behavior has been verified. diff --git a/docs/security-review.md b/docs/security-review.md new file mode 100644 index 0000000..435bf55 --- /dev/null +++ b/docs/security-review.md @@ -0,0 +1,55 @@ +# Security Review + +## Scope + +Project: + +```text +minecraft-renew-mod / create-limited-draining +``` + +Reviewed version or commit: + +```text +Unreleased workspace state +``` + +## Code Patterns Checked + +- [ ] No `eval`. +- [ ] No dynamic `Function` constructor. +- [ ] No unsafe HTML injection. +- [ ] No unexpected shell execution. +- [ ] No unexpected external network calls. +- [ ] No secrets committed. +- [ ] No unsafe file writes outside expected Gradle/Minecraft runtime paths. + +## Dependency Review + +Command: + +```powershell +cd create-limited-draining +.\gradlew dependencies --configuration runtimeClasspath +``` + +Result: + +```text +Completed successfully on 2026-05-15. Gradle resolved runtimeClasspath and reported the expected NeoForge, Create, Ponder, Flywheel, and Registrate dependency tree. +``` + +## Runtime Review + +- [ ] Least-privilege runtime configuration. +- [ ] External dependency repositories documented in Gradle. +- [ ] Local Minecraft run data is ignored. +- [ ] Sensitive data is not persisted unless explicitly required. + +## Release Notes + +Known residual risks: + +```text +In-game Hose Pulley behavior still needs manual world testing before publication. +```