mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-11-04 07:32:59 +00:00 
			
		
		
		
	Compare commits
	
		
			157 Commits
		
	
	
		
			v1.18.2-1.
			...
			v1.19.2-1.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f9bb1b4979 | ||
| 
						 | 
					edf372a695 | ||
| 
						 | 
					aa89e51639 | ||
| 
						 | 
					7436447a6e | ||
| 
						 | 
					f629831b12 | ||
| 
						 | 
					f7fdb6e729 | ||
| 
						 | 
					db2616d1c0 | ||
| 
						 | 
					c0f982dc97 | ||
| 
						 | 
					2a9f35de5e | ||
| 
						 | 
					0fce3212a3 | ||
| 
						 | 
					652f954886 | ||
| 
						 | 
					6f65bad9af | ||
| 
						 | 
					e4dd4dbef0 | ||
| 
						 | 
					e1dffaa334 | ||
| 
						 | 
					41cd9c7544 | ||
| 
						 | 
					1f3b781a1d | ||
| 
						 | 
					d7305fb975 | ||
| 
						 | 
					9b3cadf57c | ||
| 
						 | 
					68f6fa9343 | ||
| 
						 | 
					58f2c0bd71 | ||
| 
						 | 
					b46ad62424 | ||
| 
						 | 
					12f2f854a6 | ||
| 
						 | 
					4078a2dcba | ||
| 
						 | 
					0ad12eeab6 | ||
| 
						 | 
					68a5081740 | ||
| 
						 | 
					5e701f73d6 | ||
| 
						 | 
					7df0412c2d | ||
| 
						 | 
					998efcc950 | ||
| 
						 | 
					45c5de73bb | ||
| 
						 | 
					c919011a7e | ||
| 
						 | 
					0db32bd0fe | ||
| 
						 | 
					0f1f5247ca | ||
| 
						 | 
					1d3ecb551d | ||
| 
						 | 
					aefda6a381 | ||
| 
						 | 
					c1bf9f0b24 | ||
| 
						 | 
					629abb65e3 | ||
| 
						 | 
					11ac865877 | ||
| 
						 | 
					6b93fafc46 | ||
| 
						 | 
					1acb8441ec | ||
| 
						 | 
					4b0988768d | ||
| 
						 | 
					f528046535 | ||
| 
						 | 
					93f747fb54 | ||
| 
						 | 
					5d4c34fbac | ||
| 
						 | 
					4c5b3a6ee5 | ||
| 
						 | 
					7701b343fb | ||
| 
						 | 
					14cb97cba1 | ||
| 
						 | 
					1490ca8624 | ||
| 
						 | 
					f5b89982de | ||
| 
						 | 
					1a87175ae7 | ||
| 
						 | 
					c4184a33bc | ||
| 
						 | 
					b3702fed78 | ||
| 
						 | 
					b5056fc3b8 | ||
| 
						 | 
					38b2c944f3 | ||
| 
						 | 
					5ee5b11995 | ||
| 
						 | 
					b2d2153258 | ||
| 
						 | 
					3d6ef0cf96 | ||
| 
						 | 
					71f81e1201 | ||
| 
						 | 
					1e88d37004 | ||
| 
						 | 
					97387556fe | ||
| 
						 | 
					1f910ee2ba | ||
| 
						 | 
					a9ef874174 | ||
| 
						 | 
					a2911038c5 | ||
| 
						 | 
					158850be09 | ||
| 
						 | 
					be827a21db | ||
| 
						 | 
					562f224c01 | ||
| 
						 | 
					f45614175a | ||
| 
						 | 
					af7af615c7 | ||
| 
						 | 
					8171578e80 | ||
| 
						 | 
					f4e542b4db | ||
| 
						 | 
					3e3bc8d4b1 | ||
| 
						 | 
					b48f590b92 | ||
| 
						 | 
					6ab90dc30d | ||
| 
						 | 
					0cfdd7b5e9 | ||
| 
						 | 
					af5d816798 | ||
| 
						 | 
					57cf6084e2 | ||
| 
						 | 
					e9cde9e1bf | ||
| 
						 | 
					68da044ff2 | ||
| 
						 | 
					18d9993fa7 | ||
| 
						 | 
					0c3de1087e | ||
| 
						 | 
					ff89e5feeb | ||
| 
						 | 
					0b26ab366d | ||
| 
						 | 
					cb9731306c | ||
| 
						 | 
					5d833ac634 | ||
| 
						 | 
					9db3e6d2a0 | ||
| 
						 | 
					1e703f1b07 | ||
| 
						 | 
					b663028f42 | ||
| 
						 | 
					cee60cdb5b | ||
| 
						 | 
					695ef0542a | ||
| 
						 | 
					c0d20b72c9 | ||
| 
						 | 
					cf05ab1db1 | ||
| 
						 | 
					c49547b962 | ||
| 
						 | 
					c8e15f201c | ||
| 
						 | 
					bc79100a2f | ||
| 
						 | 
					9ed5ebb868 | ||
| 
						 | 
					a9b74dc979 | ||
| 
						 | 
					12b8a0393f | ||
| 
						 | 
					cbfd83c2ba | ||
| 
						 | 
					8564c1e54b | ||
| 
						 | 
					66dff1523b | ||
| 
						 | 
					08895cdecc | ||
| 
						 | 
					5be290a1e2 | ||
| 
						 | 
					371f931140 | ||
| 
						 | 
					da5956e943 | ||
| 
						 | 
					e7533f2353 | ||
| 
						 | 
					0b7fbcde53 | ||
| 
						 | 
					76f8dd2d14 | ||
| 
						 | 
					c3b7302108 | ||
| 
						 | 
					61ac48c99f | ||
| 
						 | 
					d22e138413 | ||
| 
						 | 
					ba64e06ca7 | ||
| 
						 | 
					db8c979a06 | ||
| 
						 | 
					9d18487dc5 | ||
| 
						 | 
					34a2e87735 | ||
| 
						 | 
					feb7681c9c | ||
| 
						 | 
					ad4a2aa68d | ||
| 
						 | 
					4228011b84 | ||
| 
						 | 
					c43d851e63 | ||
| 
						 | 
					50fe7935a3 | ||
| 
						 | 
					bd19fdf350 | ||
| 
						 | 
					c3615d9c5b | ||
| 
						 | 
					e2041f7438 | ||
| 
						 | 
					d61202e2b8 | ||
| 
						 | 
					6ce88a7dcf | ||
| 
						 | 
					5d65b3e654 | ||
| 
						 | 
					abf857f864 | ||
| 
						 | 
					ebef3117f2 | ||
| 
						 | 
					25a44bea6e | ||
| 
						 | 
					b28c1ac8e0 | ||
| 
						 | 
					69b211b4fb | ||
| 
						 | 
					48147fa61c | ||
| 
						 | 
					ba976f9a16 | ||
| 
						 | 
					969feb4a1c | ||
| 
						 | 
					4a273ae8e5 | ||
| 
						 | 
					bd5de11ad5 | ||
| 
						 | 
					5366fcb9c8 | ||
| 
						 | 
					6335e77da6 | ||
| 
						 | 
					4cfd0a2d1c | ||
| 
						 | 
					be3a960273 | ||
| 
						 | 
					f25a73b8f2 | ||
| 
						 | 
					954254e7e4 | ||
| 
						 | 
					e906f3ebc3 | ||
| 
						 | 
					56f0e0674f | ||
| 
						 | 
					4e438df9ad | ||
| 
						 | 
					51c3a9d8af | ||
| 
						 | 
					d967730085 | ||
| 
						 | 
					d6afee8deb | ||
| 
						 | 
					41bddcab9f | ||
| 
						 | 
					b8d7695392 | ||
| 
						 | 
					b7fa4102df | ||
| 
						 | 
					92c613a7a2 | ||
| 
						 | 
					8fc7820a12 | ||
| 
						 | 
					a2e3d9d9bd | ||
| 
						 | 
					755f8eff93 | ||
| 
						 | 
					a879efc3d0 | ||
| 
						 | 
					a913232e62 | ||
| 
						 | 
					5382d34d29 | ||
| 
						 | 
					8f7719a8dc | 
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yaml
									
									
									
									
										vendored
									
									
								
							@@ -9,8 +9,8 @@ body:
 | 
			
		||||
    description: What version of Minecraft are you using?
 | 
			
		||||
    options:
 | 
			
		||||
      - 1.16.x
 | 
			
		||||
      - 1.17.x
 | 
			
		||||
      - 1.18.x
 | 
			
		||||
      - 1.19.x
 | 
			
		||||
  validations:
 | 
			
		||||
    required: true
 | 
			
		||||
- type: input
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +1,5 @@
 | 
			
		||||
blank_issues_enabled: false
 | 
			
		||||
contact_links:
 | 
			
		||||
- name: ComputerCraft Discord
 | 
			
		||||
  url: https://discord.computercraft.cc
 | 
			
		||||
  about: Get help on the ComputerCraft Discord.
 | 
			
		||||
- name: GitHub Discussions
 | 
			
		||||
  url: https://github.com/cc-tweaked/CC-Tweaked/discussions
 | 
			
		||||
  about: Or ask questions on GitHub Discussions.
 | 
			
		||||
  about: Ask questions on GitHub Discussions.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								.github/workflows/main-ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								.github/workflows/main-ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,20 +8,19 @@ jobs:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@v2
 | 
			
		||||
    - name: Clone repository
 | 
			
		||||
      uses: actions/checkout@v3
 | 
			
		||||
 | 
			
		||||
    - name: Set up Java 8
 | 
			
		||||
      uses: actions/setup-java@v1
 | 
			
		||||
    - name: Set up Java
 | 
			
		||||
      uses: actions/setup-java@v3
 | 
			
		||||
      with:
 | 
			
		||||
        java-version: 8
 | 
			
		||||
        java-version: 17
 | 
			
		||||
        distribution: 'temurin'
 | 
			
		||||
 | 
			
		||||
    - name: Cache gradle dependencies
 | 
			
		||||
      uses: actions/cache@v2
 | 
			
		||||
    - name: Setup Gradle
 | 
			
		||||
      uses: gradle/gradle-build-action@v2
 | 
			
		||||
      with:
 | 
			
		||||
        path: ~/.gradle/caches
 | 
			
		||||
        key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }}
 | 
			
		||||
        restore-keys: |
 | 
			
		||||
          ${{ runner.os }}-gradle-
 | 
			
		||||
        cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
 | 
			
		||||
 | 
			
		||||
    - name: Disable Gradle daemon
 | 
			
		||||
      run: |
 | 
			
		||||
@@ -32,7 +31,7 @@ jobs:
 | 
			
		||||
      run: |
 | 
			
		||||
        ./gradlew assemble || ./gradlew assemble
 | 
			
		||||
        ./gradlew downloadAssets || ./gradlew downloadAssets
 | 
			
		||||
        xvfb-run ./gradlew build
 | 
			
		||||
        ./gradlew build
 | 
			
		||||
 | 
			
		||||
    - name: Upload Jar
 | 
			
		||||
      uses: actions/upload-artifact@v2
 | 
			
		||||
@@ -40,31 +39,12 @@ jobs:
 | 
			
		||||
        name: CC-Tweaked
 | 
			
		||||
        path: build/libs
 | 
			
		||||
 | 
			
		||||
    - name: Upload Screnshots
 | 
			
		||||
      uses: actions/upload-artifact@v2
 | 
			
		||||
      with:
 | 
			
		||||
        name: Screenshots
 | 
			
		||||
        path: test-files/client/screenshots
 | 
			
		||||
        if-no-files-found: ignore
 | 
			
		||||
        retention-days: 5
 | 
			
		||||
      if: failure()
 | 
			
		||||
 | 
			
		||||
    - name: Upload Coverage
 | 
			
		||||
    - name: Upload coverage
 | 
			
		||||
      uses: codecov/codecov-action@v2
 | 
			
		||||
 | 
			
		||||
    - name: Parse test reports
 | 
			
		||||
      run: ./tools/parse-reports.py
 | 
			
		||||
      if: ${{ failure() }}
 | 
			
		||||
 | 
			
		||||
    - name: Cache pre-commit
 | 
			
		||||
      uses: actions/cache@v2
 | 
			
		||||
      with:
 | 
			
		||||
        path: ~/.cache/pre-commit
 | 
			
		||||
        key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }}
 | 
			
		||||
        restore-keys: |
 | 
			
		||||
          ${{ runner.os }}-pre-commit-
 | 
			
		||||
 | 
			
		||||
    - name: Run linters
 | 
			
		||||
      run: |
 | 
			
		||||
        pip install pre-commit
 | 
			
		||||
        pre-commit run --config config/pre-commit/config.yml --show-diff-on-failure --all --color=always
 | 
			
		||||
      uses: pre-commit/action@v3.0.0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								.github/workflows/make-doc.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.github/workflows/make-doc.yml
									
									
									
									
										vendored
									
									
								
							@@ -11,29 +11,19 @@ jobs:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@v2
 | 
			
		||||
    - name: Clone repository
 | 
			
		||||
      uses: actions/checkout@v3
 | 
			
		||||
 | 
			
		||||
    - name: Set up Java 8
 | 
			
		||||
    - name: Set up Java
 | 
			
		||||
      uses: actions/setup-java@v1
 | 
			
		||||
      with:
 | 
			
		||||
        java-version: 8
 | 
			
		||||
        java-version: 17
 | 
			
		||||
        distribution: 'temurin'
 | 
			
		||||
 | 
			
		||||
    - name: Cache gradle dependencies
 | 
			
		||||
      uses: actions/cache@v2
 | 
			
		||||
    - name: Setup Gradle
 | 
			
		||||
      uses: gradle/gradle-build-action@v2
 | 
			
		||||
      with:
 | 
			
		||||
        path: ~/.gradle/caches
 | 
			
		||||
        key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }}
 | 
			
		||||
        restore-keys: |
 | 
			
		||||
          ${{ runner.os }}-gradle-
 | 
			
		||||
 | 
			
		||||
    - name: Setup illuaminate
 | 
			
		||||
      run: |
 | 
			
		||||
        test -d bin || mkdir bin
 | 
			
		||||
        test -f bin/illuaminate || wget -q -Obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
 | 
			
		||||
        chmod +x bin/illuaminate
 | 
			
		||||
 | 
			
		||||
    - name: Setup node
 | 
			
		||||
      run: npm ci
 | 
			
		||||
        cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
 | 
			
		||||
 | 
			
		||||
    - name: Build with Gradle
 | 
			
		||||
      run: ./gradlew compileJava --no-daemon || ./gradlew compileJava --no-daemon
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,14 +2,15 @@
 | 
			
		||||
/classes
 | 
			
		||||
/logs
 | 
			
		||||
/build
 | 
			
		||||
/buildSrc/build
 | 
			
		||||
/out
 | 
			
		||||
/doc/out/
 | 
			
		||||
/node_modules
 | 
			
		||||
/.jqwik-database
 | 
			
		||||
 | 
			
		||||
# Runtime directories
 | 
			
		||||
/run
 | 
			
		||||
/run-*
 | 
			
		||||
/test-files
 | 
			
		||||
 | 
			
		||||
*.ipr
 | 
			
		||||
*.iws
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,6 @@ vscode:
 | 
			
		||||
 | 
			
		||||
tasks:
 | 
			
		||||
  - name: Setup pre-commit hool
 | 
			
		||||
    init: pre-commit install --config config/pre-commit/config.yml --allow-missing-config
 | 
			
		||||
    init: pre-commit install --allow-missing-config
 | 
			
		||||
  - name: Install npm packages
 | 
			
		||||
    init: npm ci
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,13 @@ repos:
 | 
			
		||||
 | 
			
		||||
- repo: local
 | 
			
		||||
  hooks:
 | 
			
		||||
  - id: license
 | 
			
		||||
    name: Spotless
 | 
			
		||||
    files: ".*\\.(java|kt|kts)$"
 | 
			
		||||
    language: system
 | 
			
		||||
    entry: ./gradlew spotlessApply
 | 
			
		||||
    pass_filenames: false
 | 
			
		||||
    require_serial: true
 | 
			
		||||
  - id: checkstyle
 | 
			
		||||
    name: Check Java codestyle
 | 
			
		||||
    files: ".*\\.java$"
 | 
			
		||||
@@ -31,18 +38,11 @@ repos:
 | 
			
		||||
    entry: ./gradlew checkstyleMain checkstyleTest
 | 
			
		||||
    pass_filenames: false
 | 
			
		||||
    require_serial: true
 | 
			
		||||
  - id: license
 | 
			
		||||
    name: Check Java license headers
 | 
			
		||||
    files: ".*\\.java$"
 | 
			
		||||
    language: system
 | 
			
		||||
    entry: ./gradlew licenseFormat
 | 
			
		||||
    pass_filenames: false
 | 
			
		||||
    require_serial: true
 | 
			
		||||
  - id: illuaminate
 | 
			
		||||
    name: Check Lua code
 | 
			
		||||
    files: ".*\\.(lua|java|md)"
 | 
			
		||||
    language: script
 | 
			
		||||
    entry: config/pre-commit/illuaminate-lint.sh
 | 
			
		||||
    language: system
 | 
			
		||||
    entry: ./gradlew lintLua
 | 
			
		||||
    pass_filenames: false
 | 
			
		||||
    require_serial: true
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										133
									
								
								CODE_OF_CONDUCT.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								CODE_OF_CONDUCT.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
 | 
			
		||||
# Contributor Covenant Code of Conduct
 | 
			
		||||
 | 
			
		||||
## Our Pledge
 | 
			
		||||
 | 
			
		||||
We as members, contributors, and leaders pledge to make participation in our
 | 
			
		||||
community a harassment-free experience for everyone, regardless of age, body
 | 
			
		||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
 | 
			
		||||
identity and expression, level of experience, education, socio-economic status,
 | 
			
		||||
nationality, personal appearance, race, caste, color, religion, or sexual
 | 
			
		||||
identity and orientation.
 | 
			
		||||
 | 
			
		||||
We pledge to act and interact in ways that contribute to an open, welcoming,
 | 
			
		||||
diverse, inclusive, and healthy community.
 | 
			
		||||
 | 
			
		||||
## Our Standards
 | 
			
		||||
 | 
			
		||||
Examples of behavior that contributes to a positive environment for our
 | 
			
		||||
community include:
 | 
			
		||||
 | 
			
		||||
* Demonstrating empathy and kindness toward other people
 | 
			
		||||
* Being respectful of differing opinions, viewpoints, and experiences
 | 
			
		||||
* Giving and gracefully accepting constructive feedback
 | 
			
		||||
* Accepting responsibility and apologizing to those affected by our mistakes,
 | 
			
		||||
  and learning from the experience
 | 
			
		||||
* Focusing on what is best not just for us as individuals, but for the overall
 | 
			
		||||
  community
 | 
			
		||||
 | 
			
		||||
Examples of unacceptable behavior include:
 | 
			
		||||
 | 
			
		||||
* The use of sexualized language or imagery, and sexual attention or advances of
 | 
			
		||||
  any kind
 | 
			
		||||
* Trolling, insulting or derogatory comments, and personal or political attacks
 | 
			
		||||
* Public or private harassment
 | 
			
		||||
* Publishing others' private information, such as a physical or email address,
 | 
			
		||||
  without their explicit permission
 | 
			
		||||
* Other conduct which could reasonably be considered inappropriate in a
 | 
			
		||||
  professional setting
 | 
			
		||||
 | 
			
		||||
## Enforcement Responsibilities
 | 
			
		||||
 | 
			
		||||
Community leaders are responsible for clarifying and enforcing our standards of
 | 
			
		||||
acceptable behavior and will take appropriate and fair corrective action in
 | 
			
		||||
response to any behavior that they deem inappropriate, threatening, offensive,
 | 
			
		||||
or harmful.
 | 
			
		||||
 | 
			
		||||
Community leaders have the right and responsibility to remove, edit, or reject
 | 
			
		||||
comments, commits, code, wiki edits, issues, and other contributions that are
 | 
			
		||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
 | 
			
		||||
decisions when appropriate.
 | 
			
		||||
 | 
			
		||||
## Scope
 | 
			
		||||
 | 
			
		||||
This Code of Conduct applies within all community spaces, and also applies when
 | 
			
		||||
an individual is officially representing the community in public spaces.
 | 
			
		||||
Examples of representing our community include using an official e-mail address,
 | 
			
		||||
posting via an official social media account, or acting as an appointed
 | 
			
		||||
representative at an online or offline event.
 | 
			
		||||
 | 
			
		||||
## Enforcement
 | 
			
		||||
 | 
			
		||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
 | 
			
		||||
reported to the community leaders responsible for enforcement at
 | 
			
		||||
"conduct AT squiddev DOT cc". All complaints will be reviewed and investigated
 | 
			
		||||
promptly and fairly.
 | 
			
		||||
 | 
			
		||||
All community leaders are obligated to respect the privacy and security of the
 | 
			
		||||
reporter of any incident.
 | 
			
		||||
 | 
			
		||||
## Enforcement Guidelines
 | 
			
		||||
 | 
			
		||||
Community leaders will follow these Community Impact Guidelines in determining
 | 
			
		||||
the consequences for any action they deem in violation of this Code of Conduct:
 | 
			
		||||
 | 
			
		||||
### 1. Correction
 | 
			
		||||
 | 
			
		||||
**Community Impact**: Use of inappropriate language or other behavior deemed
 | 
			
		||||
unprofessional or unwelcome in the community.
 | 
			
		||||
 | 
			
		||||
**Consequence**: A private, written warning from community leaders, providing
 | 
			
		||||
clarity around the nature of the violation and an explanation of why the
 | 
			
		||||
behavior was inappropriate. A public apology may be requested.
 | 
			
		||||
 | 
			
		||||
### 2. Warning
 | 
			
		||||
 | 
			
		||||
**Community Impact**: A violation through a single incident or series of
 | 
			
		||||
actions.
 | 
			
		||||
 | 
			
		||||
**Consequence**: A warning with consequences for continued behavior. No
 | 
			
		||||
interaction with the people involved, including unsolicited interaction with
 | 
			
		||||
those enforcing the Code of Conduct, for a specified period of time. This
 | 
			
		||||
includes avoiding interactions in community spaces as well as external channels
 | 
			
		||||
like social media. Violating these terms may lead to a temporary or permanent
 | 
			
		||||
ban.
 | 
			
		||||
 | 
			
		||||
### 3. Temporary Ban
 | 
			
		||||
 | 
			
		||||
**Community Impact**: A serious violation of community standards, including
 | 
			
		||||
sustained inappropriate behavior.
 | 
			
		||||
 | 
			
		||||
**Consequence**: A temporary ban from any sort of interaction or public
 | 
			
		||||
communication with the community for a specified period of time. No public or
 | 
			
		||||
private interaction with the people involved, including unsolicited interaction
 | 
			
		||||
with those enforcing the Code of Conduct, is allowed during this period.
 | 
			
		||||
Violating these terms may lead to a permanent ban.
 | 
			
		||||
 | 
			
		||||
### 4. Permanent Ban
 | 
			
		||||
 | 
			
		||||
**Community Impact**: Demonstrating a pattern of violation of community
 | 
			
		||||
standards, including sustained inappropriate behavior, harassment of an
 | 
			
		||||
individual, or aggression toward or disparagement of classes of individuals.
 | 
			
		||||
 | 
			
		||||
**Consequence**: A permanent ban from any sort of public interaction within the
 | 
			
		||||
community.
 | 
			
		||||
 | 
			
		||||
## Attribution
 | 
			
		||||
 | 
			
		||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
 | 
			
		||||
version 2.1, available at
 | 
			
		||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
 | 
			
		||||
 | 
			
		||||
Community Impact Guidelines were inspired by
 | 
			
		||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
 | 
			
		||||
 | 
			
		||||
For answers to common questions about this code of conduct, see the FAQ at
 | 
			
		||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
 | 
			
		||||
[https://www.contributor-covenant.org/translations][translations].
 | 
			
		||||
 | 
			
		||||
[homepage]: https://www.contributor-covenant.org
 | 
			
		||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
 | 
			
		||||
[Mozilla CoC]: https://github.com/mozilla/diversity
 | 
			
		||||
[FAQ]: https://www.contributor-covenant.org/faq
 | 
			
		||||
[translations]: https://www.contributor-covenant.org/translations
 | 
			
		||||
@@ -39,40 +39,30 @@ are run whenever you submit a PR, it's often useful to run this before committin
 | 
			
		||||
 | 
			
		||||
 - **[Checkstyle]:** Checks Java code to ensure it is consistently formatted. This can be run with `./gradlew build` or
 | 
			
		||||
   `./gradle check`.
 | 
			
		||||
 - **[illuaminate]:** Checks Lua code for semantic and styleistic issues. See [the usage section][illuaminate-usage] for
 | 
			
		||||
   how to download and run it. You may need to generate the Java documentation stubs (see "Documentation" below) for all
 | 
			
		||||
   lints to pass.
 | 
			
		||||
 - **[illuaminate]:** Checks Lua code for semantic and styleistic issues. This can be run with `./gradlew lintLua`.
 | 
			
		||||
 | 
			
		||||
### Documentation
 | 
			
		||||
When writing documentation for [CC: Tweaked's documentation website][docs], it may be useful to build the documentation
 | 
			
		||||
and preview it yourself before submitting a PR.
 | 
			
		||||
 | 
			
		||||
Building all documentation is, sadly, a multi-stage process (though this is largely hidden by Gradle). First we need to
 | 
			
		||||
convert Java doc-comments into Lua ones, we also generate some Javascript to embed. All of this is then finally fed into
 | 
			
		||||
illuaminate, which spits out our HTML.
 | 
			
		||||
Our documentation generation pipeline is rather complex, and involves invoking several external tools. Most of this
 | 
			
		||||
complexity is hidden by Gradle, but you will need to perform some initial setup:
 | 
			
		||||
 | 
			
		||||
#### Setting up the tooling
 | 
			
		||||
For various reasons, getting the environment set up to build documentation can be pretty complex. I'd quite like to
 | 
			
		||||
automate this via Docker and/or nix in the future, but this needs to be done manually for now.
 | 
			
		||||
 - Install [Node/npm][node].
 | 
			
		||||
 - Run `npm ci` to install our Node dependencies.
 | 
			
		||||
 | 
			
		||||
This tooling is only needed if you need to build the whole website. If you just want to generate the Lua stubs, you can
 | 
			
		||||
skp this section.
 | 
			
		||||
 - Install Node/npm and install our Node packages with `npm ci`.
 | 
			
		||||
 - Install [illuaminate][illuaminate-usage] as described above.
 | 
			
		||||
 | 
			
		||||
#### Building documentation
 | 
			
		||||
Gradle should be your entrypoint to building most documentation. There's two tasks which are of interest:
 | 
			
		||||
 | 
			
		||||
 - `./gradlew luaJavadoc` - Generate documentation stubs for Java methods.
 | 
			
		||||
 - `./gradlew docWebsite` - Generate the whole website (including Javascript pages). The resulting HTML is stored at
 | 
			
		||||
   `./build/docs/site/`.
 | 
			
		||||
You can now run `./gradlew docWebsite`. This generates documentation from our Lua and Java code, writing the resulting
 | 
			
		||||
HTML into `./build/docs/site`.
 | 
			
		||||
 | 
			
		||||
#### Writing documentation
 | 
			
		||||
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
 | 
			
		||||
[ldoc][ldoc]. Documentation comments are written in Markdown,
 | 
			
		||||
 | 
			
		||||
Our markdown engine does _not_ support GitHub flavoured markdown, and so does not support all the features one might
 | 
			
		||||
expect (such as tables). It is very much recommended that you build and preview the docs locally first.
 | 
			
		||||
expect. It is recommended that you build and preview the docs locally first.
 | 
			
		||||
 | 
			
		||||
When iterating on documentation, you can get Gradle to rebuild the website every time a file changes by running
 | 
			
		||||
`./gradlew docWebsite -t`. This will take a couple of seconds to run, but definitely beats running it manually!
 | 
			
		||||
 | 
			
		||||
### Testing
 | 
			
		||||
Thankfully running tests is much simpler than running the documentation generator! `./gradlew check` will run the
 | 
			
		||||
@@ -90,11 +80,10 @@ Before we get into writing tests, it's worth mentioning the various test suites
 | 
			
		||||
 | 
			
		||||
   These tests are run by the '"Core" Java' test suite, and so are also run with `./gradlew test`.
 | 
			
		||||
 | 
			
		||||
 - In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server and client,
 | 
			
		||||
   using [the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
 | 
			
		||||
 - In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
 | 
			
		||||
   the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
 | 
			
		||||
 | 
			
		||||
   These are run by `./gradlew testClient` and `./gradlew testServer`. You may want to run the client under `xvfb-run`
 | 
			
		||||
   or similar when running in a headless environment.
 | 
			
		||||
   These tests are run with `./gradlew runGametest`.
 | 
			
		||||
 | 
			
		||||
## CraftOS tests
 | 
			
		||||
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
 | 
			
		||||
@@ -107,9 +96,9 @@ asserts that your variable `foo` is equal to the expected value `"bar"`.
 | 
			
		||||
[community]: README.md#Community "Get in touch with the community."
 | 
			
		||||
[checkstyle]: https://checkstyle.org/
 | 
			
		||||
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
 | 
			
		||||
[illuaminate-usage]: https://github.com/SquidDev/illuaminate/blob/master/README.md#usage "Installing Illuaminate"
 | 
			
		||||
[weblate]: https://i18n.tweaked.cc/projects/cc-tweaked/minecraft/ "CC: Tweaked weblate instance"
 | 
			
		||||
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
 | 
			
		||||
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
 | 
			
		||||
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
 | 
			
		||||
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
 | 
			
		||||
[node]: https://nodejs.org/en/ "Node.js"
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,8 @@ developing the mod, [check out the instructions here](CONTRIBUTING.md#developing
 | 
			
		||||
 | 
			
		||||
## Community
 | 
			
		||||
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
 | 
			
		||||
ComputerCraft we have a [forum](https://forums.computercraft.cc/) and [Discord guild](https://discord.computercraft.cc)!
 | 
			
		||||
There's also a fairly populated, albeit quiet [IRC channel](http://webchat.esper.net/?channels=computercraft), if that's
 | 
			
		||||
more your cup of tea.
 | 
			
		||||
ComputerCraft, do check out our [forum] and [GitHub discussions page][GitHub discussions]! There's also a fairly
 | 
			
		||||
populated, albeit quiet [IRC channel][irc], if that's more your cup of tea.
 | 
			
		||||
 | 
			
		||||
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
 | 
			
		||||
 | 
			
		||||
@@ -52,3 +51,6 @@ the generated documentation [can be browsed online](https://tweaked.cc/javadoc/)
 | 
			
		||||
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
 | 
			
		||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
 | 
			
		||||
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
 | 
			
		||||
[forum]: https://forums.computercraft.cc/
 | 
			
		||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
 | 
			
		||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										599
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										599
									
								
								build.gradle
									
									
									
									
									
								
							@@ -1,599 +0,0 @@
 | 
			
		||||
plugins {
 | 
			
		||||
    id "checkstyle"
 | 
			
		||||
    id "jacoco"
 | 
			
		||||
    id "maven-publish"
 | 
			
		||||
    id "org.cadixdev.licenser" version "0.6.1"
 | 
			
		||||
    id "com.matthewprenger.cursegradle" version "1.4.0"
 | 
			
		||||
    id "com.github.breadmoirai.github-release" version "2.2.12"
 | 
			
		||||
    id "org.jetbrains.kotlin.jvm" version "1.7.0"
 | 
			
		||||
    id "com.modrinth.minotaur" version "2.+"
 | 
			
		||||
    id "net.minecraftforge.gradle" version "5.1.+"
 | 
			
		||||
    id "org.spongepowered.mixin" version "0.7.+"
 | 
			
		||||
    id "org.parchmentmc.librarian.forgegradle" version "1.+"
 | 
			
		||||
    id "com.github.johnrengelman.shadow" version "7.1.2"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
import org.apache.tools.ant.taskdefs.condition.Os
 | 
			
		||||
 | 
			
		||||
version = mod_version
 | 
			
		||||
 | 
			
		||||
group = "org.squiddev"
 | 
			
		||||
archivesBaseName = "cc-tweaked-${mc_version}"
 | 
			
		||||
 | 
			
		||||
def javaVersion = JavaLanguageVersion.of(17)
 | 
			
		||||
java {
 | 
			
		||||
    toolchain {
 | 
			
		||||
        languageVersion = javaVersion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    withSourcesJar()
 | 
			
		||||
    withJavadocJar()
 | 
			
		||||
    registerFeature("extraMods") { usingSourceSet(sourceSets.main) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sourceSets {
 | 
			
		||||
    main.resources {
 | 
			
		||||
        srcDir 'src/generated/resources'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    testMod {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
minecraft {
 | 
			
		||||
    runs {
 | 
			
		||||
        all {
 | 
			
		||||
            lazyToken('minecraft_classpath') {
 | 
			
		||||
                configurations.shade.copyRecursive().resolve().collect { it.absolutePath }.join(File.pathSeparator)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            property 'forge.logging.markers', 'REGISTRIES'
 | 
			
		||||
            property 'forge.logging.console.level', 'debug'
 | 
			
		||||
            forceExit = false
 | 
			
		||||
 | 
			
		||||
            mods {
 | 
			
		||||
                computercraft {
 | 
			
		||||
                    source sourceSets.main
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            arg "-mixin.config=computercraft.mixins.json"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        client {
 | 
			
		||||
            workingDirectory project.file('run')
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        server {
 | 
			
		||||
            workingDirectory project.file("run/server")
 | 
			
		||||
            arg "--nogui"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data {
 | 
			
		||||
            workingDirectory project.file('run')
 | 
			
		||||
            args '--mod', 'computercraft', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        testClient {
 | 
			
		||||
            workingDirectory project.file('test-files/client')
 | 
			
		||||
            parent runs.client
 | 
			
		||||
 | 
			
		||||
            mods {
 | 
			
		||||
                cctest {
 | 
			
		||||
                    source sourceSets.testMod
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lazyToken('minecraft_classpath') {
 | 
			
		||||
                (configurations.shade.copyRecursive().resolve() + configurations.testModExtra.copyRecursive().resolve())
 | 
			
		||||
                    .collect { it.absolutePath }
 | 
			
		||||
                    .join(File.pathSeparator)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        gameTestServer {
 | 
			
		||||
            workingDirectory project.file('test-files/server')
 | 
			
		||||
 | 
			
		||||
            property("forge.logging.console.level", "info")
 | 
			
		||||
 | 
			
		||||
            mods {
 | 
			
		||||
                cctest {
 | 
			
		||||
                    source sourceSets.testMod
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lazyToken('minecraft_classpath') {
 | 
			
		||||
                (configurations.shade.copyRecursive().resolve() + configurations.testModExtra.copyRecursive().resolve())
 | 
			
		||||
                    .collect { it.absolutePath }
 | 
			
		||||
                    .join(File.pathSeparator)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mappings channel: 'parchment', version: "${mapping_version}-${mc_version}"
 | 
			
		||||
 | 
			
		||||
    accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
 | 
			
		||||
    accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mixin {
 | 
			
		||||
    add sourceSets.main, 'computercraft.mixins.refmap.json'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
reobf {
 | 
			
		||||
    shadowJar {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
    maven {
 | 
			
		||||
        name "SquidDev"
 | 
			
		||||
        url "https://squiddev.cc/maven"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configurations {
 | 
			
		||||
    shade { transitive = false }
 | 
			
		||||
    implementation.extendsFrom shade
 | 
			
		||||
 | 
			
		||||
    cctJavadoc
 | 
			
		||||
 | 
			
		||||
    testModExtra
 | 
			
		||||
    testModImplementation.extendsFrom(testModExtra)
 | 
			
		||||
    testModImplementation.extendsFrom(implementation)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    checkstyle "com.puppycrawl.tools:checkstyle:8.45"
 | 
			
		||||
 | 
			
		||||
    minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
 | 
			
		||||
    annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
 | 
			
		||||
 | 
			
		||||
    extraModsCompileOnly fg.deobf("mezz.jei:jei-1.18.2:9.4.1.116:api")
 | 
			
		||||
    extraModsRuntimeOnly fg.deobf("mezz.jei:jei-1.18.2:9.4.1.116")
 | 
			
		||||
 | 
			
		||||
    shade 'org.squiddev:Cobalt:0.5.5'
 | 
			
		||||
 | 
			
		||||
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
 | 
			
		||||
    testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
 | 
			
		||||
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
 | 
			
		||||
    testImplementation 'org.hamcrest:hamcrest:2.2'
 | 
			
		||||
    testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0'
 | 
			
		||||
    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2'
 | 
			
		||||
 | 
			
		||||
    testModImplementation sourceSets.main.output
 | 
			
		||||
    testModExtra('org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.0') {
 | 
			
		||||
        exclude group: "org.jetbrains", module: "annotations"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cctJavadoc 'cc.tweaked:cct-javadoc:1.4.6'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compile tasks
 | 
			
		||||
 | 
			
		||||
javadoc {
 | 
			
		||||
    include "dan200/computercraft/api/**/*.java"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def apiJar = tasks.register("apiJar", Jar.class) {
 | 
			
		||||
    archiveClassifier.set("api")
 | 
			
		||||
    from(sourceSets.main.output) {
 | 
			
		||||
        include "dan200/computercraft/api/**/*"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
assemble.dependsOn(apiJar)
 | 
			
		||||
 | 
			
		||||
def luaJavadoc = tasks.register("luaJavadoc", Javadoc.class) {
 | 
			
		||||
    description "Generates documentation for Java-side Lua functions."
 | 
			
		||||
    group "documentation"
 | 
			
		||||
 | 
			
		||||
    source = sourceSets.main.allJava
 | 
			
		||||
    destinationDir = file("${project.docsDir}/luaJavadoc")
 | 
			
		||||
    classpath = sourceSets.main.compileClasspath
 | 
			
		||||
 | 
			
		||||
    options.docletpath = configurations.cctJavadoc.files as List
 | 
			
		||||
    options.doclet = "cc.tweaked.javadoc.LuaDoclet"
 | 
			
		||||
    options.noTimestamp = false
 | 
			
		||||
 | 
			
		||||
    javadocTool = javaToolchains.javadocToolFor {
 | 
			
		||||
        languageVersion = javaVersion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
jar {
 | 
			
		||||
    finalizedBy("reobfJar")
 | 
			
		||||
 | 
			
		||||
    archiveClassifier.set("slim")
 | 
			
		||||
    manifest {
 | 
			
		||||
        attributes([
 | 
			
		||||
            "Specification-Title"     : "computercraft",
 | 
			
		||||
            "Specification-Vendor"    : "SquidDev",
 | 
			
		||||
            "Specification-Version"   : "1",
 | 
			
		||||
            "Implementation-Title"    : "CC: Tweaked",
 | 
			
		||||
            "Implementation-Version"  : "${mod_version}",
 | 
			
		||||
            "Implementation-Vendor"   : "SquidDev",
 | 
			
		||||
            "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
 | 
			
		||||
            "MixinConfigs"            : "computercraft.mixins.json",
 | 
			
		||||
        ])
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
shadowJar {
 | 
			
		||||
    finalizedBy("reobfShadowJar")
 | 
			
		||||
 | 
			
		||||
    archiveClassifier.set("")
 | 
			
		||||
    configurations = [project.configurations.shade]
 | 
			
		||||
    relocate("org.squiddev.cobalt", "cc.tweaked.internal.cobalt")
 | 
			
		||||
    minimize()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
assemble.dependsOn("shadowJar")
 | 
			
		||||
 | 
			
		||||
[
 | 
			
		||||
    tasks.named("compileJava", JavaCompile.class),
 | 
			
		||||
    tasks.named("compileTestJava", JavaCompile.class),
 | 
			
		||||
    tasks.named("compileTestModJava", JavaCompile.class)
 | 
			
		||||
].forEach {
 | 
			
		||||
    it.configure {
 | 
			
		||||
        options.compilerArgs << "-Xlint" << "-Xlint:-processing"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
processResources {
 | 
			
		||||
    def hash = 'none'
 | 
			
		||||
    Set<String> contributors = []
 | 
			
		||||
    try {
 | 
			
		||||
        hash = ["git", "-C", projectDir, "rev-parse", "HEAD"].execute().text.trim()
 | 
			
		||||
 | 
			
		||||
        def blacklist = ['GitHub', 'Daniel Ratcliffe', 'Weblate']
 | 
			
		||||
 | 
			
		||||
        // Extract all authors, commiters and co-authors from the git log.
 | 
			
		||||
        def authors = ["git", "-C", projectDir, "log", "--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)"]
 | 
			
		||||
            .execute().text.readLines().unique()
 | 
			
		||||
 | 
			
		||||
        // We now pass this through git's mailmap to de-duplicate some authors.
 | 
			
		||||
        def remapAuthors = ["git", "check-mailmap", "--stdin"].execute()
 | 
			
		||||
        remapAuthors.withWriter { stdin ->
 | 
			
		||||
            if (stdin !instanceof BufferedWriter) stdin = new BufferedWriter(stdin)
 | 
			
		||||
 | 
			
		||||
            authors.forEach {
 | 
			
		||||
                if (it == "") return
 | 
			
		||||
                if (!it.endsWith(">")) it += ">" // Some commits have broken Co-Authored-By lines!
 | 
			
		||||
                stdin.writeLine(it)
 | 
			
		||||
            }
 | 
			
		||||
            stdin.close()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // And finally extract out the actual name.
 | 
			
		||||
        def emailRegex = ~/^([^<]+) <.+>$/
 | 
			
		||||
        remapAuthors.text.readLines().forEach {
 | 
			
		||||
            def matcher = it =~ emailRegex
 | 
			
		||||
            matcher.find()
 | 
			
		||||
            def name = matcher.group(1)
 | 
			
		||||
            if (!blacklist.contains(name)) contributors.add(name)
 | 
			
		||||
        }
 | 
			
		||||
    } catch (Exception e) {
 | 
			
		||||
        e.printStackTrace()
 | 
			
		||||
    }
 | 
			
		||||
    inputs.property "commithash", hash
 | 
			
		||||
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
 | 
			
		||||
 | 
			
		||||
    from(sourceSets.main.resources.srcDirs) {
 | 
			
		||||
        include 'data/computercraft/lua/rom/help/credits.txt'
 | 
			
		||||
 | 
			
		||||
        expand(
 | 
			
		||||
            'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    from(sourceSets.main.resources.srcDirs) {
 | 
			
		||||
        exclude 'data/computercraft/lua/rom/help/credits.txt'
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sourcesJar {
 | 
			
		||||
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Web tasks
 | 
			
		||||
 | 
			
		||||
List<String> mkCommand(String command) {
 | 
			
		||||
    return Os.isFamily(Os.FAMILY_WINDOWS) ? ["cmd", "/c", command] : ["sh", "-c", command]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def rollup = tasks.register("rollup", Exec.class) {
 | 
			
		||||
    group = "build"
 | 
			
		||||
    description = "Bundles JS into rollup"
 | 
			
		||||
 | 
			
		||||
    inputs.files(fileTree("src/web")).withPropertyName("sources")
 | 
			
		||||
    inputs.file("package-lock.json").withPropertyName("package-lock.json")
 | 
			
		||||
    inputs.file("tsconfig.json").withPropertyName("Typescript config")
 | 
			
		||||
    inputs.file("rollup.config.js").withPropertyName("Rollup config")
 | 
			
		||||
    outputs.file("$buildDir/rollup/index.js").withPropertyName("output")
 | 
			
		||||
 | 
			
		||||
    commandLine mkCommand('"node_modules/.bin/rollup" --config rollup.config.js')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def illuaminateDocs = tasks.register("illuaminateDocs", Exec.class) {
 | 
			
		||||
    group = "documentation"
 | 
			
		||||
    description = "Generates docs using Illuaminate"
 | 
			
		||||
    dependsOn(rollup, luaJavadoc)
 | 
			
		||||
 | 
			
		||||
    inputs.files(fileTree("doc")).withPropertyName("docs")
 | 
			
		||||
    inputs.files(fileTree("src/main/resources/data/computercraft/lua/rom")).withPropertyName("lua rom")
 | 
			
		||||
    inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
 | 
			
		||||
    inputs.dir("$buildDir/docs/luaJavadoc")
 | 
			
		||||
    inputs.file("$buildDir/rollup/index.js").withPropertyName("scripts")
 | 
			
		||||
    inputs.file("src/web/styles.css").withPropertyName("styles")
 | 
			
		||||
    outputs.dir("$buildDir/docs/lua")
 | 
			
		||||
 | 
			
		||||
    commandLine mkCommand('"bin/illuaminate" doc-gen')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def jsxDocs = tasks.register("jsxDocs", Exec) {
 | 
			
		||||
    group = "documentation"
 | 
			
		||||
    description = "Post-processes documentation to statically render some dynamic content."
 | 
			
		||||
    dependsOn(illuaminateDocs)
 | 
			
		||||
 | 
			
		||||
    inputs.files(fileTree("src/web")).withPropertyName("sources")
 | 
			
		||||
    inputs.file("src/generated/export/index.json").withPropertyName("export")
 | 
			
		||||
    inputs.file("package-lock.json").withPropertyName("package-lock.json")
 | 
			
		||||
    inputs.file("tsconfig.json").withPropertyName("Typescript config")
 | 
			
		||||
    inputs.files(fileTree("$buildDir/docs/lua"))
 | 
			
		||||
    outputs.dir("$buildDir/docs/site")
 | 
			
		||||
 | 
			
		||||
    commandLine mkCommand('"node_modules/.bin/ts-node" --esm src/web/transform.tsx')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def docWebsite = tasks.register("docWebsite", Copy.class) {
 | 
			
		||||
    group = "documentation"
 | 
			
		||||
    description = "Copy additional assets to the website directory."
 | 
			
		||||
    dependsOn(jsxDocs)
 | 
			
		||||
 | 
			
		||||
    from('doc') {
 | 
			
		||||
        include 'logo.png'
 | 
			
		||||
        include 'images/**'
 | 
			
		||||
    }
 | 
			
		||||
    from("$buildDir/rollup") {
 | 
			
		||||
        exclude 'index.js'
 | 
			
		||||
    }
 | 
			
		||||
    from("$buildDir/docs/lua") {
 | 
			
		||||
        exclude '**/*.html'
 | 
			
		||||
    }
 | 
			
		||||
    from("src/generated/export/items") {
 | 
			
		||||
        into("images/items")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    into "${project.docsDir}/site"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check tasks
 | 
			
		||||
 | 
			
		||||
test {
 | 
			
		||||
    useJUnitPlatform()
 | 
			
		||||
    testLogging {
 | 
			
		||||
        events "skipped", "failed"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
jacocoTestReport {
 | 
			
		||||
    dependsOn('test')
 | 
			
		||||
    reports {
 | 
			
		||||
        xml.required = true
 | 
			
		||||
        html.required = true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test.finalizedBy("jacocoTestReport")
 | 
			
		||||
 | 
			
		||||
license {
 | 
			
		||||
    header = file('config/license/main.txt')
 | 
			
		||||
    lineEnding = '\n'
 | 
			
		||||
    newLine = false
 | 
			
		||||
 | 
			
		||||
    properties {
 | 
			
		||||
        year = Calendar.getInstance().get(Calendar.YEAR)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    include("**/*.java") // We could apply to Kotlin, but for now let's not
 | 
			
		||||
    matching("dan200/computercraft/api/**") {
 | 
			
		||||
        header = file('config/license/api.txt')
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check.dependsOn("licenseCheck")
 | 
			
		||||
 | 
			
		||||
def testServerClassDumpDir = new File(buildDir, "jacocoClassDump/runTestServer")
 | 
			
		||||
 | 
			
		||||
def testServer = tasks.register("testServer", JavaExec.class) {
 | 
			
		||||
    group("In-game tests")
 | 
			
		||||
    description("Runs tests on a temporary Minecraft instance.")
 | 
			
		||||
    dependsOn("cleanTestServer")
 | 
			
		||||
    finalizedBy("jacocoTestServerReport")
 | 
			
		||||
 | 
			
		||||
    // Copy from runTestServer. We do it in this slightly odd way as runTestServer
 | 
			
		||||
    // isn't created until the task is configured (which is no good for us).
 | 
			
		||||
    JavaExec exec = tasks.getByName("runGameTestServer")
 | 
			
		||||
    dependsOn(exec.getDependsOn())
 | 
			
		||||
    exec.copyTo(it)
 | 
			
		||||
    setClasspath(exec.getClasspath())
 | 
			
		||||
    mainClass = exec.mainClass
 | 
			
		||||
    javaLauncher = exec.javaLauncher
 | 
			
		||||
    setArgs(exec.getArgs())
 | 
			
		||||
 | 
			
		||||
    // Jacoco and modlauncher don't play well together as the classes loaded in-game don't
 | 
			
		||||
    // match up with those written to disk. We get Jacoco to dump all classes to disk, and
 | 
			
		||||
    // use that when generating the report.
 | 
			
		||||
    jacoco.applyTo(it)
 | 
			
		||||
    it.jacoco.setIncludes(["dan200.computercraft.*"])
 | 
			
		||||
    it.jacoco.setClassDumpDir(testServerClassDumpDir)
 | 
			
		||||
    outputs.dir(testServerClassDumpDir)
 | 
			
		||||
    // Older versions of modlauncher don't include a protection domain (and thus no code
 | 
			
		||||
    // source). Jacoco skips such classes by default, so we need to explicitly include them.
 | 
			
		||||
    it.jacoco.setIncludeNoLocationClasses(true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.register("jacocoTestServerReport", JacocoReport.class) {
 | 
			
		||||
    group("In-game tests")
 | 
			
		||||
    description("Generate coverage reports for testServer")
 | 
			
		||||
    dependsOn(testServer)
 | 
			
		||||
 | 
			
		||||
    executionData(new File(buildDir, "jacoco/testServer.exec"))
 | 
			
		||||
    sourceDirectories.from(sourceSets.main.allJava.srcDirs)
 | 
			
		||||
    classDirectories.from(testServerClassDumpDir)
 | 
			
		||||
 | 
			
		||||
    reports {
 | 
			
		||||
        xml.enabled true
 | 
			
		||||
        html.enabled true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check.dependsOn(testServer)
 | 
			
		||||
 | 
			
		||||
// Upload tasks
 | 
			
		||||
 | 
			
		||||
def checkRelease = tasks.register("checkRelease") {
 | 
			
		||||
    group "upload"
 | 
			
		||||
    description "Verifies that everything is ready for a release"
 | 
			
		||||
 | 
			
		||||
    inputs.property "version", mod_version
 | 
			
		||||
    inputs.file("src/main/resources/data/computercraft/lua/rom/help/changelog.md")
 | 
			
		||||
    inputs.file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
 | 
			
		||||
 | 
			
		||||
    doLast {
 | 
			
		||||
        def ok = true
 | 
			
		||||
 | 
			
		||||
        // Check we're targetting the current version
 | 
			
		||||
        def whatsnew = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.md").readLines()
 | 
			
		||||
        if (whatsnew[0] != "New features in CC: Tweaked $mod_version") {
 | 
			
		||||
            ok = false
 | 
			
		||||
            project.logger.error("Expected `whatsnew.md' to target $mod_version.")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check "read more" exists and trim it
 | 
			
		||||
        def idx = whatsnew.findIndexOf { it == 'Type "help changelog" to see the full version history.' }
 | 
			
		||||
        if (idx == -1) {
 | 
			
		||||
            ok = false
 | 
			
		||||
            project.logger.error("Must mention the changelog in whatsnew.md")
 | 
			
		||||
        } else {
 | 
			
		||||
            whatsnew = whatsnew.getAt(0..<idx)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check whatsnew and changelog match.
 | 
			
		||||
        def versionChangelog = "# " + whatsnew.join("\n")
 | 
			
		||||
        def changelog = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/changelog.md").getText()
 | 
			
		||||
        if (!changelog.startsWith(versionChangelog)) {
 | 
			
		||||
            ok = false
 | 
			
		||||
            project.logger.error("whatsnew and changelog are not in sync")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!ok) throw new IllegalStateException("Could not check release")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
check.dependsOn(checkRelease)
 | 
			
		||||
 | 
			
		||||
def isStable = true
 | 
			
		||||
 | 
			
		||||
curseforge {
 | 
			
		||||
    apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
 | 
			
		||||
    project {
 | 
			
		||||
        id = '282001'
 | 
			
		||||
        releaseType = isStable ? 'release' : 'alpha'
 | 
			
		||||
        changelog = "Release notes can be found on the GitHub repository (https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
 | 
			
		||||
        mainArtifact(shadowJar)
 | 
			
		||||
 | 
			
		||||
        addGameVersion "${mc_version}"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
modrinth {
 | 
			
		||||
    token = project.hasProperty('modrinthApiKey') ? project.getProperty('modrinthApiKey') : ''
 | 
			
		||||
    projectId = 'gu7yAYhd'
 | 
			
		||||
    versionNumber = "${project.mc_version}-${project.mod_version}"
 | 
			
		||||
    versionType = isStable ? 'release' : 'alpha'
 | 
			
		||||
    uploadFile = shadowJar
 | 
			
		||||
    gameVersions = [project.mc_version]
 | 
			
		||||
    changelog = "Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
publishing {
 | 
			
		||||
    publications {
 | 
			
		||||
        maven(MavenPublication) {
 | 
			
		||||
            from components.java
 | 
			
		||||
            artifact(apiJar)
 | 
			
		||||
            fg.component(it)
 | 
			
		||||
 | 
			
		||||
            pom {
 | 
			
		||||
                name = 'CC: Tweaked'
 | 
			
		||||
                description = 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
 | 
			
		||||
                url = 'https://github.com/cc-tweaked/CC-Tweaked'
 | 
			
		||||
 | 
			
		||||
                scm {
 | 
			
		||||
                    url = 'https://github.com/cc-tweaked/CC-Tweaked.git'
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                issueManagement {
 | 
			
		||||
                    system = 'github'
 | 
			
		||||
                    url = 'https://github.com/cc-tweaked/CC-Tweaked/issues'
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                licenses {
 | 
			
		||||
                    license {
 | 
			
		||||
                        name = 'ComputerCraft Public License, Version 1.0'
 | 
			
		||||
                        url = 'https://github.com/cc-tweaked/CC-Tweaked/blob/mc-1.16.x/LICENSE'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    repositories {
 | 
			
		||||
        if (project.hasProperty("mavenUser")) {
 | 
			
		||||
            maven {
 | 
			
		||||
                name = "SquidDev"
 | 
			
		||||
                url = "https://squiddev.cc/maven"
 | 
			
		||||
                credentials {
 | 
			
		||||
                    username = project.property("mavenUser") as String
 | 
			
		||||
                    password = project.property("mavenPass") as String
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
githubRelease {
 | 
			
		||||
    token project.hasProperty('githubApiKey') ? project.githubApiKey : ''
 | 
			
		||||
    owner 'cc-tweaked'
 | 
			
		||||
    repo 'CC-Tweaked'
 | 
			
		||||
    targetCommitish.set(project.provider({
 | 
			
		||||
        def cmd = ["git", "rev-parse", "--abbrev-ref", "HEAD"]
 | 
			
		||||
        println(cmd)
 | 
			
		||||
        def proc = cmd.execute([], projectDir)
 | 
			
		||||
        if (proc.waitFor() != 0) {
 | 
			
		||||
            println(proc.err.text.trim())
 | 
			
		||||
            throw new IllegalStateException("Executed with a non-0 exit code (${proc.exitValue()}).")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        def branch = proc.text.trim()
 | 
			
		||||
        if (branch == "") throw new IllegalStateException("Cannot determine branch")
 | 
			
		||||
        return branch
 | 
			
		||||
    }))
 | 
			
		||||
 | 
			
		||||
    tagName "v${mc_version}-${mod_version}"
 | 
			
		||||
    releaseName "[${mc_version}] ${mod_version}"
 | 
			
		||||
    body.set(project.provider({
 | 
			
		||||
        "## " + new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
 | 
			
		||||
            .readLines()
 | 
			
		||||
            .takeWhile { it != 'Type "help changelog" to see the full version history.' }
 | 
			
		||||
            .join("\n").trim()
 | 
			
		||||
    }))
 | 
			
		||||
    prerelease !isStable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def uploadTasks = ["publish", "curseforge", "modrinth", "githubRelease"]
 | 
			
		||||
uploadTasks.forEach { tasks.named(it) { dependsOn(checkRelease) } }
 | 
			
		||||
 | 
			
		||||
tasks.register("uploadAll") {
 | 
			
		||||
    group = "upload"
 | 
			
		||||
    description = "Uploads to all repositories (Maven, Curse, Modrinth, GitHub release)"
 | 
			
		||||
    dependsOn(uploadTasks)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										460
									
								
								build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,460 @@
 | 
			
		||||
import cc.tweaked.gradle.*
 | 
			
		||||
import net.darkhax.curseforgegradle.TaskPublishCurseForge
 | 
			
		||||
import net.minecraftforge.gradle.common.util.RunConfig
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    // Build
 | 
			
		||||
    alias(libs.plugins.forgeGradle)
 | 
			
		||||
    alias(libs.plugins.mixinGradle)
 | 
			
		||||
    alias(libs.plugins.librarian)
 | 
			
		||||
    alias(libs.plugins.shadow)
 | 
			
		||||
    // Publishing
 | 
			
		||||
    `maven-publish`
 | 
			
		||||
    alias(libs.plugins.curseForgeGradle)
 | 
			
		||||
    alias(libs.plugins.githubRelease)
 | 
			
		||||
    alias(libs.plugins.minotaur)
 | 
			
		||||
    // Utility
 | 
			
		||||
    alias(libs.plugins.taskTree)
 | 
			
		||||
 | 
			
		||||
    id("cc-tweaked.illuaminate")
 | 
			
		||||
    id("cc-tweaked.node")
 | 
			
		||||
    id("cc-tweaked.gametest")
 | 
			
		||||
    id("cc-tweaked")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val isStable = true
 | 
			
		||||
val modVersion: String by extra
 | 
			
		||||
val mcVersion: String by extra
 | 
			
		||||
 | 
			
		||||
group = "org.squiddev"
 | 
			
		||||
version = modVersion
 | 
			
		||||
base.archivesName.set("cc-tweaked-$mcVersion")
 | 
			
		||||
 | 
			
		||||
java.registerFeature("extraMods") { usingSourceSet(sourceSets.main.get()) }
 | 
			
		||||
 | 
			
		||||
sourceSets {
 | 
			
		||||
    main {
 | 
			
		||||
        resources.srcDir("src/generated/resources")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
minecraft {
 | 
			
		||||
    runs {
 | 
			
		||||
        // configureEach would be better, but we need to eagerly configure configs or otherwise the run task doesn't
 | 
			
		||||
        // get set up properly.
 | 
			
		||||
        all {
 | 
			
		||||
            lazyToken("minecraft_classpath") {
 | 
			
		||||
                configurations["shade"].copyRecursive().resolve().joinToString(File.pathSeparator) { it.absolutePath }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            property("forge.logging.markers", "REGISTRIES")
 | 
			
		||||
            property("forge.logging.console.level", "debug")
 | 
			
		||||
 | 
			
		||||
            forceExit = false
 | 
			
		||||
 | 
			
		||||
            mods.register("computercraft") { source(sourceSets.main.get()) }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val client by registering {
 | 
			
		||||
            workingDirectory(file("run"))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val server by registering {
 | 
			
		||||
            workingDirectory(file("run/server"))
 | 
			
		||||
            arg("--nogui")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val data by registering {
 | 
			
		||||
            workingDirectory(file("run"))
 | 
			
		||||
            args(
 | 
			
		||||
                "--mod",
 | 
			
		||||
                "computercraft",
 | 
			
		||||
                "--all",
 | 
			
		||||
                "--output",
 | 
			
		||||
                file("src/generated/resources/"),
 | 
			
		||||
                "--existing",
 | 
			
		||||
                file("src/main/resources/"),
 | 
			
		||||
            )
 | 
			
		||||
            property("cct.pretty-json", "true")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun RunConfig.configureForGameTest() {
 | 
			
		||||
            val old = lazyTokens.get("minecraft_classpath")
 | 
			
		||||
            lazyToken("minecraft_classpath") {
 | 
			
		||||
                // We do some terrible hacks here to basically find all things not already on the runtime classpath
 | 
			
		||||
                // and add them. /Except/ for our source sets, as those need to load inside the Minecraft classpath.
 | 
			
		||||
                val testMod = configurations["testModRuntimeClasspath"].resolve()
 | 
			
		||||
                val implementation = configurations.runtimeClasspath.get().resolve()
 | 
			
		||||
                val new = (testMod - implementation)
 | 
			
		||||
                    .asSequence()
 | 
			
		||||
                    .filter { it.isFile && !it.name.endsWith("-test-fixtures.jar") }
 | 
			
		||||
                    .map { it.absolutePath }
 | 
			
		||||
                    .joinToString(File.pathSeparator)
 | 
			
		||||
                if (old == null) new else old.get() + File.pathSeparator + new
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            property("cctest.sources", file("src/testMod/resources/data/cctest").absolutePath)
 | 
			
		||||
 | 
			
		||||
            arg("--mixin.config=computercraft-gametest.mixins.json")
 | 
			
		||||
 | 
			
		||||
            mods.register("cctest") {
 | 
			
		||||
                source(sourceSets["testMod"])
 | 
			
		||||
                source(sourceSets["testFixtures"])
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val testClient by registering {
 | 
			
		||||
            workingDirectory(file("run/testClient"))
 | 
			
		||||
            parent(client.get())
 | 
			
		||||
            configureForGameTest()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val gameTestServer by registering {
 | 
			
		||||
            workingDirectory(file("run/testServer"))
 | 
			
		||||
            configureForGameTest()
 | 
			
		||||
 | 
			
		||||
            property("forge.logging.console.level", "info")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mappings("parchment", "${libs.versions.parchmentMc.get()}-${libs.versions.parchment.get()}-$mcVersion")
 | 
			
		||||
 | 
			
		||||
    accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mixin {
 | 
			
		||||
    add(sourceSets.main.get(), "computercraft.mixins.refmap.json")
 | 
			
		||||
    config("computercraft.mixins.json")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
reobf {
 | 
			
		||||
    register("shadowJar")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configurations {
 | 
			
		||||
    val shade by registering { isTransitive = false }
 | 
			
		||||
    implementation { extendsFrom(shade.get()) }
 | 
			
		||||
    register("cctJavadoc")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    minecraft("net.minecraftforge:forge:$mcVersion-${libs.versions.forge.get()}")
 | 
			
		||||
    annotationProcessor("org.spongepowered:mixin:0.8.5:processor")
 | 
			
		||||
 | 
			
		||||
    compileOnly(libs.jetbrainsAnnotations)
 | 
			
		||||
    annotationProcessorEverywhere(libs.autoService)
 | 
			
		||||
 | 
			
		||||
    "extraModsCompileOnly"(fg.deobf("mezz.jei:jei-1.19.2-forge-api:11.3.0.262"))
 | 
			
		||||
    "extraModsCompileOnly"(fg.deobf("mezz.jei:jei-1.19.2-common-api:11.3.0.262"))
 | 
			
		||||
    "extraModsRuntimeOnly"(fg.deobf("mezz.jei:jei-1.19.2-forge:11.3.0.262"))
 | 
			
		||||
    "extraModsCompileOnly"(fg.deobf("maven.modrinth:oculus:1.2.5"))
 | 
			
		||||
 | 
			
		||||
    "shade"(libs.cobalt)
 | 
			
		||||
    "shade"("io.netty:netty-codec-http:4.1.76.Final")
 | 
			
		||||
 | 
			
		||||
    testFixturesApi(libs.bundles.test)
 | 
			
		||||
    testFixturesApi(libs.bundles.kotlin)
 | 
			
		||||
 | 
			
		||||
    testImplementation(libs.bundles.test)
 | 
			
		||||
    testImplementation(libs.bundles.kotlin)
 | 
			
		||||
    testRuntimeOnly(libs.bundles.testRuntime)
 | 
			
		||||
 | 
			
		||||
    "cctJavadoc"(libs.cctJavadoc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
illuaminate {
 | 
			
		||||
    version.set(libs.versions.illuaminate)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compile tasks
 | 
			
		||||
 | 
			
		||||
tasks.javadoc {
 | 
			
		||||
    include("dan200/computercraft/api/**/*.java")
 | 
			
		||||
    (options as StandardJavadocDocletOptions).links("https://docs.oracle.com/en/java/javase/17/docs/api/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val apiJar by tasks.registering(Jar::class) {
 | 
			
		||||
    archiveClassifier.set("api")
 | 
			
		||||
    from(sourceSets.main.get().output) {
 | 
			
		||||
        include("dan200/computercraft/api/**/*")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.assemble { dependsOn(apiJar) }
 | 
			
		||||
 | 
			
		||||
val luaJavadoc by tasks.registering(Javadoc::class) {
 | 
			
		||||
    description = "Generates documentation for Java-side Lua functions."
 | 
			
		||||
    group = JavaBasePlugin.DOCUMENTATION_GROUP
 | 
			
		||||
 | 
			
		||||
    source(sourceSets.main.get().java)
 | 
			
		||||
    setDestinationDir(buildDir.resolve("docs/luaJavadoc"))
 | 
			
		||||
    classpath = sourceSets.main.get().compileClasspath
 | 
			
		||||
 | 
			
		||||
    options.docletpath = configurations["cctJavadoc"].files.toList()
 | 
			
		||||
    options.doclet = "cc.tweaked.javadoc.LuaDoclet"
 | 
			
		||||
    (options as StandardJavadocDocletOptions).noTimestamp(false)
 | 
			
		||||
 | 
			
		||||
    javadocTool.set(
 | 
			
		||||
        javaToolchains.javadocToolFor {
 | 
			
		||||
            languageVersion.set(cc.tweaked.gradle.CCTweakedPlugin.JAVA_VERSION)
 | 
			
		||||
        },
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.processResources {
 | 
			
		||||
    inputs.property("modVersion", modVersion)
 | 
			
		||||
    inputs.property("forgeVersion", libs.versions.forge.get())
 | 
			
		||||
    inputs.property("gitHash", cct.gitHash)
 | 
			
		||||
 | 
			
		||||
    filesMatching("data/computercraft/lua/rom/help/credits.md") {
 | 
			
		||||
        expand(mapOf("gitContributors" to cct.gitContributors.get().joinToString("\n")))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    filesMatching("META-INF/mods.toml") {
 | 
			
		||||
        expand(mapOf("forgeVersion" to libs.versions.forge.get(), "file" to mapOf("jarVersion" to modVersion)))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.jar {
 | 
			
		||||
    isReproducibleFileOrder = true
 | 
			
		||||
    isPreserveFileTimestamps = false
 | 
			
		||||
    finalizedBy("reobfJar")
 | 
			
		||||
    archiveClassifier.set("slim")
 | 
			
		||||
 | 
			
		||||
    manifest {
 | 
			
		||||
        attributes(
 | 
			
		||||
            "Specification-Title" to "computercraft",
 | 
			
		||||
            "Specification-Vendor" to "SquidDev",
 | 
			
		||||
            "Specification-Version" to "1",
 | 
			
		||||
            "Implementation-Title" to "cctweaked",
 | 
			
		||||
            "Implementation-Version" to modVersion,
 | 
			
		||||
            "Implementation-Vendor" to "SquidDev",
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.shadowJar {
 | 
			
		||||
    finalizedBy("reobfShadowJar")
 | 
			
		||||
 | 
			
		||||
    archiveClassifier.set("")
 | 
			
		||||
    configurations = listOf(project.configurations["shade"])
 | 
			
		||||
    relocate("org.squiddev.cobalt", "cc.tweaked.internal.cobalt")
 | 
			
		||||
    minimize()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.assemble { dependsOn("shadowJar") }
 | 
			
		||||
 | 
			
		||||
// Web tasks
 | 
			
		||||
 | 
			
		||||
val rollup by tasks.registering(NpxExecToDir::class) {
 | 
			
		||||
    group = LifecycleBasePlugin.BUILD_GROUP
 | 
			
		||||
    description = "Bundles JS into rollup"
 | 
			
		||||
 | 
			
		||||
    // Sources
 | 
			
		||||
    inputs.files(fileTree("src/web")).withPropertyName("sources")
 | 
			
		||||
    // Config files
 | 
			
		||||
    inputs.file("tsconfig.json").withPropertyName("Typescript config")
 | 
			
		||||
    inputs.file("rollup.config.js").withPropertyName("Rollup config")
 | 
			
		||||
 | 
			
		||||
    // Output directory. Also defined in illuaminate.sexp and rollup.config.js
 | 
			
		||||
    output.set(buildDir.resolve("rollup"))
 | 
			
		||||
 | 
			
		||||
    args = listOf("rollup", "--config", "rollup.config.js")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val illuaminateDocs by tasks.registering(IlluaminateExecToDir::class) {
 | 
			
		||||
    group = JavaBasePlugin.DOCUMENTATION_GROUP
 | 
			
		||||
    description = "Generates docs using Illuaminate"
 | 
			
		||||
 | 
			
		||||
    // Config files
 | 
			
		||||
    inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
 | 
			
		||||
    // Sources
 | 
			
		||||
    inputs.files(fileTree("doc")).withPropertyName("docs")
 | 
			
		||||
    inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
 | 
			
		||||
    inputs.files(luaJavadoc)
 | 
			
		||||
    // Additional assets
 | 
			
		||||
    inputs.files(rollup)
 | 
			
		||||
    inputs.file("src/web/styles.css").withPropertyName("styles")
 | 
			
		||||
 | 
			
		||||
    // Output directory. Also defined in illuaminate.sexp and transform.tsx
 | 
			
		||||
    output.set(buildDir.resolve("illuaminate"))
 | 
			
		||||
 | 
			
		||||
    args = listOf("doc-gen")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val jsxDocs by tasks.registering(NpxExecToDir::class) {
 | 
			
		||||
    group = JavaBasePlugin.DOCUMENTATION_GROUP
 | 
			
		||||
    description = "Post-processes documentation to statically render some dynamic content."
 | 
			
		||||
 | 
			
		||||
    // Config files
 | 
			
		||||
    inputs.file("tsconfig.json").withPropertyName("Typescript config")
 | 
			
		||||
    // Sources
 | 
			
		||||
    inputs.files(fileTree("src/web")).withPropertyName("sources")
 | 
			
		||||
    inputs.file("src/generated/export/index.json").withPropertyName("export")
 | 
			
		||||
    inputs.files(illuaminateDocs)
 | 
			
		||||
 | 
			
		||||
    // Output directory. Also defined in src/web/transform.tsx
 | 
			
		||||
    output.set(buildDir.resolve("jsxDocs"))
 | 
			
		||||
 | 
			
		||||
    args = listOf("ts-node", "-T", "--esm", "src/web/transform.tsx")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val docWebsite by tasks.registering(Copy::class) {
 | 
			
		||||
    group = JavaBasePlugin.DOCUMENTATION_GROUP
 | 
			
		||||
    description = "Assemble docs and assets together into the documentation website."
 | 
			
		||||
 | 
			
		||||
    from(jsxDocs)
 | 
			
		||||
 | 
			
		||||
    from("doc") {
 | 
			
		||||
        include("logo.png")
 | 
			
		||||
        include("images/**")
 | 
			
		||||
    }
 | 
			
		||||
    from(rollup) { exclude("index.js") }
 | 
			
		||||
    from(illuaminateDocs) { exclude("**/*.html") }
 | 
			
		||||
    from("src/generated/export/items") { into("images/items") }
 | 
			
		||||
 | 
			
		||||
    into(buildDir.resolve("docs/site"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check tasks
 | 
			
		||||
 | 
			
		||||
tasks.test {
 | 
			
		||||
    systemProperty("cct.test-files", buildDir.resolve("tmp/testFiles").absolutePath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val lintLua by tasks.registering(IlluaminateExec::class) {
 | 
			
		||||
    group = JavaBasePlugin.VERIFICATION_GROUP
 | 
			
		||||
    description = "Lint Lua (and Lua docs) with illuaminate"
 | 
			
		||||
 | 
			
		||||
    // Config files
 | 
			
		||||
    inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
 | 
			
		||||
    // Sources
 | 
			
		||||
    inputs.files(fileTree("doc")).withPropertyName("docs")
 | 
			
		||||
    inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
 | 
			
		||||
    inputs.files(luaJavadoc)
 | 
			
		||||
 | 
			
		||||
    args = listOf("lint")
 | 
			
		||||
 | 
			
		||||
    doFirst { if (System.getenv("GITHUB_ACTIONS") != null) println("::add-matcher::.github/matchers/illuaminate.json") }
 | 
			
		||||
    doLast { if (System.getenv("GITHUB_ACTIONS") != null) println("::remove-matcher owner=illuaminate::") }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val runGametest by tasks.registering(JavaExec::class) {
 | 
			
		||||
    group = LifecycleBasePlugin.VERIFICATION_GROUP
 | 
			
		||||
    description = "Runs tests on a temporary Minecraft instance."
 | 
			
		||||
    dependsOn("cleanRunGametest")
 | 
			
		||||
 | 
			
		||||
    // Copy from runGameTestServer. We do it in this slightly odd way as runGameTestServer
 | 
			
		||||
    // isn't created until the task is configured (which is no good for us).
 | 
			
		||||
    val exec = tasks.getByName<JavaExec>("runGameTestServer")
 | 
			
		||||
    dependsOn(exec.dependsOn)
 | 
			
		||||
    exec.copyToFull(this)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cct.jacoco(runGametest)
 | 
			
		||||
 | 
			
		||||
tasks.check { dependsOn(runGametest) }
 | 
			
		||||
 | 
			
		||||
// Upload tasks
 | 
			
		||||
 | 
			
		||||
val checkChangelog by tasks.registering(CheckChangelog::class) {
 | 
			
		||||
    version.set(modVersion)
 | 
			
		||||
    whatsNew.set(file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md"))
 | 
			
		||||
    changelog.set(file("src/main/resources/data/computercraft/lua/rom/help/changelog.md"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.check { dependsOn(checkChangelog) }
 | 
			
		||||
 | 
			
		||||
val publishCurseForge by tasks.registering(TaskPublishCurseForge::class) {
 | 
			
		||||
    group = PublishingPlugin.PUBLISH_TASK_GROUP
 | 
			
		||||
    description = "Upload artifacts to CurseForge"
 | 
			
		||||
 | 
			
		||||
    apiToken = findProperty("curseForgeApiKey") ?: ""
 | 
			
		||||
    enabled = apiToken != ""
 | 
			
		||||
 | 
			
		||||
    val mainFile = upload("282001", tasks.shadowJar.get().archiveFile)
 | 
			
		||||
    dependsOn(tasks.shadowJar) // Ughr.
 | 
			
		||||
    mainFile.changelog = "Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
 | 
			
		||||
    mainFile.changelogType = "markdown"
 | 
			
		||||
    mainFile.releaseType = if (isStable) "release" else "alpha"
 | 
			
		||||
    mainFile.gameVersions.add(mcVersion)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.publish { dependsOn(publishCurseForge) }
 | 
			
		||||
 | 
			
		||||
modrinth {
 | 
			
		||||
    token.set(findProperty("modrinthApiKey") as String? ?: "")
 | 
			
		||||
    projectId.set("gu7yAYhd")
 | 
			
		||||
    versionNumber.set("$mcVersion-$modVersion")
 | 
			
		||||
    versionName.set(modVersion)
 | 
			
		||||
    versionType.set(if (isStable) "release" else "alpha")
 | 
			
		||||
    uploadFile.set(tasks.shadowJar as Any)
 | 
			
		||||
    gameVersions.add(mcVersion)
 | 
			
		||||
    changelog.set("Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion).")
 | 
			
		||||
 | 
			
		||||
    syncBodyFrom.set(provider { file("doc/mod-page.md").readText() })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.publish { dependsOn(tasks.modrinth) }
 | 
			
		||||
 | 
			
		||||
githubRelease {
 | 
			
		||||
    token(findProperty("githubApiKey") as String? ?: "")
 | 
			
		||||
    owner.set("cc-tweaked")
 | 
			
		||||
    repo.set("CC-Tweaked")
 | 
			
		||||
    targetCommitish.set(cct.gitBranch)
 | 
			
		||||
 | 
			
		||||
    tagName.set("v$mcVersion-$modVersion")
 | 
			
		||||
    releaseName.set("[$mcVersion] $modVersion")
 | 
			
		||||
    body.set(
 | 
			
		||||
        provider {
 | 
			
		||||
            "## " + file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
 | 
			
		||||
                .readLines()
 | 
			
		||||
                .takeWhile { it != "Type \"help changelog\" to see the full version history." }
 | 
			
		||||
                .joinToString("\n").trim()
 | 
			
		||||
        },
 | 
			
		||||
    )
 | 
			
		||||
    prerelease.set(!isStable)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.publish { dependsOn(tasks.githubRelease) }
 | 
			
		||||
 | 
			
		||||
publishing {
 | 
			
		||||
    publications {
 | 
			
		||||
        register<MavenPublication>("maven") {
 | 
			
		||||
            artifactId = base.archivesName.get()
 | 
			
		||||
            from(components["java"])
 | 
			
		||||
            artifact(apiJar)
 | 
			
		||||
            fg.component(this)
 | 
			
		||||
 | 
			
		||||
            pom {
 | 
			
		||||
                name.set("CC: Tweaked")
 | 
			
		||||
                description.set("CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.")
 | 
			
		||||
                url.set("https://github.com/cc-tweaked/CC-Tweaked")
 | 
			
		||||
 | 
			
		||||
                scm {
 | 
			
		||||
                    url.set("https://github.com/cc-tweaked/CC-Tweaked.git")
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                issueManagement {
 | 
			
		||||
                    system.set("github")
 | 
			
		||||
                    url.set("https://github.com/cc-tweaked/CC-Tweaked/issues")
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                licenses {
 | 
			
		||||
                    license {
 | 
			
		||||
                        name.set("ComputerCraft Public License, Version 1.0")
 | 
			
		||||
                        url.set("https://github.com/cc-tweaked/CC-Tweaked/blob/HEAD/LICENSE")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    repositories {
 | 
			
		||||
        maven("https://squiddev.cc/maven") {
 | 
			
		||||
            name = "SquidDev"
 | 
			
		||||
 | 
			
		||||
            credentials(PasswordCredentials::class)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								buildSrc/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								buildSrc/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
plugins {
 | 
			
		||||
    `java-gradle-plugin`
 | 
			
		||||
    `kotlin-dsl`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
    gradlePluginPortal()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    implementation(libs.kotlin.plugin)
 | 
			
		||||
    implementation(libs.spotless)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gradlePlugin {
 | 
			
		||||
    plugins {
 | 
			
		||||
        register("cc-tweaked") {
 | 
			
		||||
            id = "cc-tweaked"
 | 
			
		||||
            implementationClass = "cc.tweaked.gradle.CCTweakedPlugin"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        register("cc-tweaked.illuaminate") {
 | 
			
		||||
            id = "cc-tweaked.illuaminate"
 | 
			
		||||
            implementationClass = "cc.tweaked.gradle.IlluaminatePlugin"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        register("cc-tweaked.node") {
 | 
			
		||||
            id = "cc-tweaked.node"
 | 
			
		||||
            implementationClass = "cc.tweaked.gradle.NodePlugin"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								buildSrc/settings.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								buildSrc/settings.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
dependencyResolutionManagement {
 | 
			
		||||
    versionCatalogs {
 | 
			
		||||
        create("libs") {
 | 
			
		||||
            from(files("../gradle/libs.versions.toml"))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								buildSrc/src/main/kotlin/cc-tweaked.gametest.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								buildSrc/src/main/kotlin/cc-tweaked.gametest.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sets up the configurations for writing game tests.
 | 
			
		||||
 *
 | 
			
		||||
 * See notes in [cc.tweaked.gradle.MinecraftConfigurations] for the general design behind these cursed ideas.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    id("cc-tweaked.kotlin-convention")
 | 
			
		||||
    id("cc-tweaked.java-convention")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val main = sourceSets.main.get()
 | 
			
		||||
 | 
			
		||||
// Both testMod and testFixtures inherit from the main classpath, just so we have access to Minecraft classes.
 | 
			
		||||
val testMod by sourceSets.creating {
 | 
			
		||||
    compileClasspath += main.compileClasspath
 | 
			
		||||
    runtimeClasspath += main.runtimeClasspath
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configurations {
 | 
			
		||||
    named(testMod.compileClasspathConfigurationName) {
 | 
			
		||||
        shouldResolveConsistentlyWith(compileClasspath.get())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    named(testMod.runtimeClasspathConfigurationName) {
 | 
			
		||||
        shouldResolveConsistentlyWith(runtimeClasspath.get())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Like the main test configurations, we're safe to depend on source set outputs.
 | 
			
		||||
dependencies {
 | 
			
		||||
    add(testMod.implementationConfigurationName, main.output)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Similar to java-test-fixtures, but tries to avoid putting the obfuscated jar on the classpath.
 | 
			
		||||
 | 
			
		||||
val testFixtures by sourceSets.creating {
 | 
			
		||||
    compileClasspath += main.compileClasspath
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
java.registerFeature("testFixtures") {
 | 
			
		||||
    usingSourceSet(testFixtures)
 | 
			
		||||
    disablePublication()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    add(testFixtures.implementationConfigurationName, main.output)
 | 
			
		||||
 | 
			
		||||
    testImplementation(testFixtures(project))
 | 
			
		||||
    add(testMod.implementationConfigurationName, testFixtures(project))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										106
									
								
								buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
import cc.tweaked.gradle.CCTweakedPlugin
 | 
			
		||||
import cc.tweaked.gradle.LicenseHeader
 | 
			
		||||
import com.diffplug.gradle.spotless.FormatExtension
 | 
			
		||||
import com.diffplug.spotless.LineEnding
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    `java-library`
 | 
			
		||||
    jacoco
 | 
			
		||||
    checkstyle
 | 
			
		||||
    id("com.diffplug.spotless")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
java {
 | 
			
		||||
    toolchain {
 | 
			
		||||
        languageVersion.set(CCTweakedPlugin.JAVA_VERSION)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    withSourcesJar()
 | 
			
		||||
    withJavadocJar()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
    maven("https://squiddev.cc/maven") {
 | 
			
		||||
        name = "SquidDev"
 | 
			
		||||
        content {
 | 
			
		||||
            includeGroup("org.squiddev")
 | 
			
		||||
            includeGroup("cc.tweaked")
 | 
			
		||||
            // Things we mirror
 | 
			
		||||
            includeGroup("com.blamejared.crafttweaker")
 | 
			
		||||
            includeGroup("commoble.morered")
 | 
			
		||||
            includeGroup("maven.modrinth")
 | 
			
		||||
            includeGroup("mezz.jei")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
 | 
			
		||||
    checkstyle(libs.findLibrary("checkstyle").get())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Configure default JavaCompile tasks with our arguments.
 | 
			
		||||
sourceSets.all {
 | 
			
		||||
    tasks.named(compileJavaTaskName, JavaCompile::class.java) {
 | 
			
		||||
        // Processing just gives us "No processor claimed any of these annotations", so skip that!
 | 
			
		||||
        options.compilerArgs.addAll(listOf("-Xlint", "-Xlint:-processing"))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.withType(JavaCompile::class.java).configureEach {
 | 
			
		||||
    options.encoding = "UTF-8"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.test {
 | 
			
		||||
    finalizedBy("jacocoTestReport")
 | 
			
		||||
 | 
			
		||||
    useJUnitPlatform()
 | 
			
		||||
    testLogging {
 | 
			
		||||
        events("skipped", "failed")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.withType(JacocoReport::class.java).configureEach {
 | 
			
		||||
    reports.xml.required.set(true)
 | 
			
		||||
    reports.html.required.set(true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
spotless {
 | 
			
		||||
    encoding = StandardCharsets.UTF_8
 | 
			
		||||
    lineEndings = LineEnding.UNIX
 | 
			
		||||
 | 
			
		||||
    fun FormatExtension.defaults() {
 | 
			
		||||
        endWithNewline()
 | 
			
		||||
        trimTrailingWhitespace()
 | 
			
		||||
        indentWithSpaces(4)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val licenser = LicenseHeader.create(
 | 
			
		||||
        api = file("config/license/api.txt"),
 | 
			
		||||
        main = file("config/license/main.txt"),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    java {
 | 
			
		||||
        defaults()
 | 
			
		||||
        addStep(licenser)
 | 
			
		||||
        removeUnusedImports()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val ktlintConfig = mapOf(
 | 
			
		||||
        "disabled_rules" to "no-wildcard-imports",
 | 
			
		||||
        "ij_kotlin_allow_trailing_comma" to "true",
 | 
			
		||||
        "ij_kotlin_allow_trailing_comma_on_call_site" to "true",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    kotlinGradle {
 | 
			
		||||
        defaults()
 | 
			
		||||
        ktlint().editorConfigOverride(ktlintConfig)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kotlin {
 | 
			
		||||
        defaults()
 | 
			
		||||
        ktlint().editorConfigOverride(ktlintConfig)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
import cc.tweaked.gradle.CCTweakedPlugin
 | 
			
		||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    kotlin("jvm")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
kotlin {
 | 
			
		||||
    jvmToolchain {
 | 
			
		||||
        languageVersion.set(CCTweakedPlugin.JAVA_VERSION)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.withType(KotlinCompile::class.java).configureEach {
 | 
			
		||||
    // So technically we shouldn't need to do this as the toolchain sets it above. However, the option only appears
 | 
			
		||||
    // to be set when the task executes, so doesn't get picked up by IDEs.
 | 
			
		||||
    kotlinOptions.jvmTarget = when {
 | 
			
		||||
        CCTweakedPlugin.JAVA_VERSION.asInt() > 8 -> CCTweakedPlugin.JAVA_VERSION.toString()
 | 
			
		||||
        else -> "1.${CCTweakedPlugin.JAVA_VERSION.asInt()}"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										124
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.NamedDomainObjectProvider
 | 
			
		||||
import org.gradle.api.Project
 | 
			
		||||
import org.gradle.api.attributes.TestSuiteType
 | 
			
		||||
import org.gradle.api.file.FileSystemOperations
 | 
			
		||||
import org.gradle.api.provider.Provider
 | 
			
		||||
import org.gradle.api.reporting.ReportingExtension
 | 
			
		||||
import org.gradle.api.tasks.JavaExec
 | 
			
		||||
import org.gradle.api.tasks.SourceSetContainer
 | 
			
		||||
import org.gradle.configurationcache.extensions.capitalized
 | 
			
		||||
import org.gradle.kotlin.dsl.get
 | 
			
		||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
 | 
			
		||||
import org.gradle.testing.jacoco.plugins.JacocoCoverageReport
 | 
			
		||||
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
 | 
			
		||||
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
 | 
			
		||||
import org.gradle.testing.jacoco.tasks.JacocoReport
 | 
			
		||||
import java.io.BufferedWriter
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
import java.io.OutputStreamWriter
 | 
			
		||||
import java.util.regex.Pattern
 | 
			
		||||
 | 
			
		||||
abstract class CCTweakedExtension(
 | 
			
		||||
    private val project: Project,
 | 
			
		||||
    private val fs: FileSystemOperations,
 | 
			
		||||
) {
 | 
			
		||||
    /** Get the hash of the latest git commit. */
 | 
			
		||||
    val gitHash: Provider<String> = gitProvider(project, "<no git hash>") {
 | 
			
		||||
        ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "HEAD").trim()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Get the current git branch. */
 | 
			
		||||
    val gitBranch: Provider<String> = gitProvider(project, "<no git branch>") {
 | 
			
		||||
        ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD").trim()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all contributors to the project. */
 | 
			
		||||
    val gitContributors: Provider<List<String>> = gitProvider(project, listOf()) {
 | 
			
		||||
        val authors: Set<String> = HashSet(
 | 
			
		||||
            ProcessHelpers.captureLines(
 | 
			
		||||
                "git", "-C", project.projectDir.absolutePath, "log",
 | 
			
		||||
                "--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)",
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        val process = ProcessHelpers.startProcess("git", "check-mailmap", "--stdin")
 | 
			
		||||
        BufferedWriter(OutputStreamWriter(process.outputStream)).use { writer ->
 | 
			
		||||
            for (authorName in authors) {
 | 
			
		||||
                var author = authorName
 | 
			
		||||
 | 
			
		||||
                if (author.isEmpty()) continue
 | 
			
		||||
                if (!author.endsWith(">")) author += ">" // Some commits have broken Co-Authored-By lines!
 | 
			
		||||
                writer.write(author)
 | 
			
		||||
                writer.newLine()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        val contributors: MutableSet<String> = HashSet()
 | 
			
		||||
        for (authorLine in ProcessHelpers.captureLines(process)) {
 | 
			
		||||
            val matcher = EMAIL.matcher(authorLine)
 | 
			
		||||
            matcher.find()
 | 
			
		||||
            val name = matcher.group(1)
 | 
			
		||||
            if (!IGNORED_USERS.contains(name)) contributors.add(name)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        contributors.sortedWith(String.CASE_INSENSITIVE_ORDER)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun jacoco(task: NamedDomainObjectProvider<JavaExec>) {
 | 
			
		||||
        val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
 | 
			
		||||
        val reportTaskName = "jacoco${task.name.capitalized()}Report"
 | 
			
		||||
 | 
			
		||||
        val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
 | 
			
		||||
        task.configure {
 | 
			
		||||
            finalizedBy(reportTaskName)
 | 
			
		||||
 | 
			
		||||
            doFirst("Clean class dump directory") { fs.delete { delete(classDump) } }
 | 
			
		||||
 | 
			
		||||
            jacoco.applyTo(this)
 | 
			
		||||
            extensions.configure(JacocoTaskExtension::class.java) {
 | 
			
		||||
                includes = listOf("dan200.computercraft.*")
 | 
			
		||||
                classDumpDir = classDump
 | 
			
		||||
 | 
			
		||||
                // Older versions of modlauncher don't include a protection domain (and thus no code
 | 
			
		||||
                // source). Jacoco skips such classes by default, so we need to explicitly include them.
 | 
			
		||||
                isIncludeNoLocationClasses = true
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        project.tasks.register(reportTaskName, JacocoReport::class.java) {
 | 
			
		||||
            group = LifecycleBasePlugin.VERIFICATION_GROUP
 | 
			
		||||
            description = "Generates code coverage report for the ${task.name} task."
 | 
			
		||||
 | 
			
		||||
            executionData(task.get())
 | 
			
		||||
            classDirectories.from(classDump)
 | 
			
		||||
 | 
			
		||||
            // Don't want to use sourceSets(...) here as we have a custom class directory.
 | 
			
		||||
            val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
 | 
			
		||||
            sourceDirectories.from(sourceSets["main"].allSource.sourceDirectories)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        project.extensions.configure(ReportingExtension::class.java) {
 | 
			
		||||
            reports.register("${task.name}CodeCoverageReport", JacocoCoverageReport::class.java) {
 | 
			
		||||
                testType.set(TestSuiteType.INTEGRATION_TEST)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val EMAIL = Pattern.compile("^([^<]+) <.+>$")
 | 
			
		||||
        private val IGNORED_USERS = setOf(
 | 
			
		||||
            "GitHub", "Daniel Ratcliffe", "Weblate",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        private fun <T> gitProvider(project: Project, default: T, supplier: () -> T): Provider<T> {
 | 
			
		||||
            return project.provider {
 | 
			
		||||
                try {
 | 
			
		||||
                    supplier()
 | 
			
		||||
                } catch (e: IOException) {
 | 
			
		||||
                    project.logger.error("Cannot read Git repository: ${e.message}")
 | 
			
		||||
                    default
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.Plugin
 | 
			
		||||
import org.gradle.api.Project
 | 
			
		||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Configures projects to match a shared configuration.
 | 
			
		||||
 */
 | 
			
		||||
class CCTweakedPlugin : Plugin<Project> {
 | 
			
		||||
    override fun apply(project: Project) {
 | 
			
		||||
        project.extensions.create("cct", CCTweakedExtension::class.java)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        val JAVA_VERSION = JavaLanguageVersion.of(17)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckChangelog.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckChangelog.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.DefaultTask
 | 
			
		||||
import org.gradle.api.GradleException
 | 
			
		||||
import org.gradle.api.file.RegularFileProperty
 | 
			
		||||
import org.gradle.api.provider.Property
 | 
			
		||||
import org.gradle.api.tasks.*
 | 
			
		||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks the `changelog.md` and `whatsnew.md` files are well-formed.
 | 
			
		||||
 */
 | 
			
		||||
@CacheableTask
 | 
			
		||||
abstract class CheckChangelog : DefaultTask() {
 | 
			
		||||
    init {
 | 
			
		||||
        group = LifecycleBasePlugin.VERIFICATION_GROUP
 | 
			
		||||
        description = "Verifies the changelog and whatsnew file are consistent."
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @get:Input
 | 
			
		||||
    abstract val version: Property<String>
 | 
			
		||||
 | 
			
		||||
    @get:InputFile
 | 
			
		||||
    @get:PathSensitive(PathSensitivity.NONE)
 | 
			
		||||
    abstract val changelog: RegularFileProperty
 | 
			
		||||
 | 
			
		||||
    @get:InputFile
 | 
			
		||||
    @get:PathSensitive(PathSensitivity.NONE)
 | 
			
		||||
    abstract val whatsNew: RegularFileProperty
 | 
			
		||||
 | 
			
		||||
    @TaskAction
 | 
			
		||||
    fun check() {
 | 
			
		||||
        val version = version.get()
 | 
			
		||||
 | 
			
		||||
        var ok = true
 | 
			
		||||
 | 
			
		||||
        // Check we're targetting the current version
 | 
			
		||||
        var whatsNew = whatsNew.get().asFile.readLines()
 | 
			
		||||
        if (whatsNew[0] != "New features in CC: Tweaked $version") {
 | 
			
		||||
            ok = false
 | 
			
		||||
            logger.error("Expected `whatsnew.md' to target $version.")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check "read more" exists and trim it
 | 
			
		||||
        val idx = whatsNew.indexOfFirst { it == "Type \"help changelog\" to see the full version history." }
 | 
			
		||||
        if (idx == -1) {
 | 
			
		||||
            ok = false
 | 
			
		||||
            logger.error("Must mention the changelog in whatsnew.md")
 | 
			
		||||
        } else {
 | 
			
		||||
            whatsNew = whatsNew.slice(0 until idx)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check whatsnew and changelog match.
 | 
			
		||||
        val expectedChangelog = sequenceOf("# ${whatsNew[0]}") + whatsNew.slice(1 until whatsNew.size).asSequence()
 | 
			
		||||
        val changelog = changelog.get().asFile.readLines()
 | 
			
		||||
        val mismatch = expectedChangelog.zip(changelog.asSequence()).filter { (a, b) -> a != b }.firstOrNull()
 | 
			
		||||
        if (mismatch != null) {
 | 
			
		||||
            ok = false
 | 
			
		||||
            logger.error("whatsnew and changelog are not in sync")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!ok) throw GradleException("Could not check release")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckLicense.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckLicense.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import com.diffplug.spotless.FormatterFunc
 | 
			
		||||
import com.diffplug.spotless.FormatterStep
 | 
			
		||||
import com.diffplug.spotless.generic.LicenseHeaderStep
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.Serializable
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Similar to [LicenseHeaderStep], but supports multiple licenses.
 | 
			
		||||
 */
 | 
			
		||||
object LicenseHeader {
 | 
			
		||||
    /**
 | 
			
		||||
     * The current year to use in templates. Intentionally not dynamic to avoid failing the build.
 | 
			
		||||
     */
 | 
			
		||||
    private const val YEAR = 2022
 | 
			
		||||
 | 
			
		||||
    private val COMMENT = Regex("""^/\*(.*?)\*/\n?""", RegexOption.DOT_MATCHES_ALL)
 | 
			
		||||
 | 
			
		||||
    fun create(api: File, main: File): FormatterStep = FormatterStep.createLazy(
 | 
			
		||||
        "license",
 | 
			
		||||
        { Licenses(getTemplateText(api), getTemplateText(main)) },
 | 
			
		||||
        { state -> FormatterFunc.NeedsFile { contents, file -> formatFile(state, contents, file) } },
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private fun getTemplateText(file: File): String =
 | 
			
		||||
        file.readText().trim().replace("\${year}", "$YEAR")
 | 
			
		||||
 | 
			
		||||
    private fun formatFile(licenses: Licenses, contents: String, file: File): String {
 | 
			
		||||
        val license = getLicense(contents)
 | 
			
		||||
        val expectedLicense = getExpectedLicense(licenses, file.parentFile)
 | 
			
		||||
 | 
			
		||||
        return when {
 | 
			
		||||
            license == null -> setLicense(expectedLicense, contents)
 | 
			
		||||
            license.second != expectedLicense -> setLicense(expectedLicense, contents, license.first)
 | 
			
		||||
            else -> contents
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getExpectedLicense(licenses: Licenses, root: File): String {
 | 
			
		||||
        var file: File? = root
 | 
			
		||||
        while (file != null) {
 | 
			
		||||
            if (file.name == "api" && file.parentFile?.name == "computercraft") return licenses.api
 | 
			
		||||
            file = file.parentFile
 | 
			
		||||
        }
 | 
			
		||||
        return licenses.main
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getLicense(contents: String): Pair<Int, String>? {
 | 
			
		||||
        val match = COMMENT.find(contents) ?: return null
 | 
			
		||||
        val license = match.groups[1]!!.value
 | 
			
		||||
            .trim().lineSequence()
 | 
			
		||||
            .map { it.trimStart(' ', '*') }
 | 
			
		||||
            .joinToString("\n")
 | 
			
		||||
        return Pair(match.range.last + 1, license)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun setLicense(license: String, contents: String, start: Int = 0): String {
 | 
			
		||||
        val out = StringBuilder()
 | 
			
		||||
        out.append("/*\n")
 | 
			
		||||
        for (line in license.lineSequence()) out.append(" * ").append(line).append("\n")
 | 
			
		||||
        out.append(" */\n")
 | 
			
		||||
        out.append(contents, start, contents.length)
 | 
			
		||||
        return out.toString()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private data class Licenses(val api: String, val main: String) : Serializable {
 | 
			
		||||
        companion object {
 | 
			
		||||
            private const val serialVersionUID: Long = 7741106448372435662L
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/ExecTasks.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/ExecTasks.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.provider.Property
 | 
			
		||||
import org.gradle.api.tasks.AbstractExecTask
 | 
			
		||||
import org.gradle.api.tasks.OutputDirectory
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
abstract class ExecToDir : AbstractExecTask<ExecToDir>(ExecToDir::class.java) {
 | 
			
		||||
    @get:OutputDirectory
 | 
			
		||||
    abstract val output: Property<File>
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/Extensions.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/Extensions.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.artifacts.dsl.DependencyHandler
 | 
			
		||||
import org.gradle.api.tasks.JavaExec
 | 
			
		||||
 | 
			
		||||
fun DependencyHandler.annotationProcessorEverywhere(dep: Any) {
 | 
			
		||||
    add("compileOnly", dep)
 | 
			
		||||
    add("annotationProcessor", dep)
 | 
			
		||||
 | 
			
		||||
    add("testCompileOnly", dep)
 | 
			
		||||
    add("testAnnotationProcessor", dep)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun JavaExec.copyToFull(spec: JavaExec) {
 | 
			
		||||
    copyTo(spec)
 | 
			
		||||
    spec.classpath = classpath
 | 
			
		||||
    spec.mainClass.set(mainClass)
 | 
			
		||||
    spec.javaLauncher.set(javaLauncher)
 | 
			
		||||
    spec.args = args
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										121
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/Illuaminate.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/Illuaminate.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.DefaultTask
 | 
			
		||||
import org.gradle.api.Plugin
 | 
			
		||||
import org.gradle.api.Project
 | 
			
		||||
import org.gradle.api.Task
 | 
			
		||||
import org.gradle.api.artifacts.Dependency
 | 
			
		||||
import org.gradle.api.provider.Property
 | 
			
		||||
import org.gradle.api.provider.Provider
 | 
			
		||||
import org.gradle.api.tasks.AbstractExecTask
 | 
			
		||||
import org.gradle.api.tasks.Input
 | 
			
		||||
import org.gradle.api.tasks.TaskAction
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
abstract class IlluaminateExtension {
 | 
			
		||||
    /** The version of illuaminate to use. */
 | 
			
		||||
    abstract val version: Property<String>
 | 
			
		||||
 | 
			
		||||
    /** The path to illuaminate. If not given, illuaminate will be downloaded automatically. */
 | 
			
		||||
    abstract val file: Property<File>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class IlluaminatePlugin : Plugin<Project> {
 | 
			
		||||
    override fun apply(project: Project) {
 | 
			
		||||
        val extension = project.extensions.create("illuaminate", IlluaminateExtension::class.java)
 | 
			
		||||
        extension.file.convention(setupDependency(project, extension.version))
 | 
			
		||||
 | 
			
		||||
        project.tasks.register(SetupIlluaminate.NAME, SetupIlluaminate::class.java) {
 | 
			
		||||
            file.set(extension.file.map { it.absolutePath })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Set up a repository for illuaminate and download our binary from it. */
 | 
			
		||||
    private fun setupDependency(project: Project, version: Provider<String>): Provider<File> {
 | 
			
		||||
        project.repositories.ivy {
 | 
			
		||||
            name = "Illuaminate"
 | 
			
		||||
            setUrl("https://squiddev.cc/illuaminate/bin/")
 | 
			
		||||
            patternLayout {
 | 
			
		||||
                artifact("[revision]/[artifact]-[ext]")
 | 
			
		||||
            }
 | 
			
		||||
            metadataSources {
 | 
			
		||||
                artifact()
 | 
			
		||||
            }
 | 
			
		||||
            content {
 | 
			
		||||
                includeModule("cc.squiddev", "illuaminate")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return version.map {
 | 
			
		||||
            val dep = illuaminateArtifact(project, it)
 | 
			
		||||
            val configuration = project.configurations.detachedConfiguration(dep)
 | 
			
		||||
            configuration.isTransitive = false
 | 
			
		||||
            configuration.resolve().single()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Define a dependency for illuaminate from a version number and the current operating system. */
 | 
			
		||||
    private fun illuaminateArtifact(project: Project, version: String): Dependency {
 | 
			
		||||
        val osName = System.getProperty("os.name").toLowerCase()
 | 
			
		||||
        val (os, suffix) = when {
 | 
			
		||||
            osName.contains("windows") -> Pair("windows", ".exe")
 | 
			
		||||
            osName.contains("mac os") || osName.contains("darwin") -> Pair("macos", "")
 | 
			
		||||
            osName.contains("linux") -> Pair("linux", "")
 | 
			
		||||
            else -> error("Unsupported OS $osName for illuaminate")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val osArch = System.getProperty("os.arch").toLowerCase()
 | 
			
		||||
        val arch = when {
 | 
			
		||||
            osArch == "arm" || osArch.startsWith("aarch") -> error("Unsupported architecture '$osArch' for illuaminate")
 | 
			
		||||
            osArch.contains("64") -> "x86_64"
 | 
			
		||||
            else -> error("Unsupported architecture $osArch for illuaminate")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return project.dependencies.create(
 | 
			
		||||
            mapOf(
 | 
			
		||||
                "group" to "cc.squiddev",
 | 
			
		||||
                "name" to "illuaminate",
 | 
			
		||||
                "version" to version,
 | 
			
		||||
                "ext" to "$os-$arch$suffix",
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private val Task.illuaminatePath: String? // "?" needed to avoid overload ambiguity in setExecutable below.
 | 
			
		||||
    get() = project.extensions.getByType(IlluaminateExtension::class.java).file.get().absolutePath
 | 
			
		||||
 | 
			
		||||
/** Prepares illuaminate for being run. This simply requests the dependency and then marks it as executable. */
 | 
			
		||||
abstract class SetupIlluaminate : DefaultTask() {
 | 
			
		||||
    @get:Input
 | 
			
		||||
    abstract val file: Property<String>
 | 
			
		||||
 | 
			
		||||
    @TaskAction
 | 
			
		||||
    fun setExecutable() {
 | 
			
		||||
        val file = File(this.file.get())
 | 
			
		||||
        if (file.canExecute()) {
 | 
			
		||||
            didWork = false
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        file.setExecutable(true)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val NAME: String = "setupIlluaminate"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class IlluaminateExec : AbstractExecTask<IlluaminateExec>(IlluaminateExec::class.java) {
 | 
			
		||||
    init {
 | 
			
		||||
        dependsOn(SetupIlluaminate.NAME)
 | 
			
		||||
        executable = illuaminatePath
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class IlluaminateExecToDir : ExecToDir() {
 | 
			
		||||
    init {
 | 
			
		||||
        dependsOn(SetupIlluaminate.NAME)
 | 
			
		||||
        executable = illuaminatePath
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/Node.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/Node.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.gradle.api.DefaultTask
 | 
			
		||||
import org.gradle.api.Plugin
 | 
			
		||||
import org.gradle.api.Project
 | 
			
		||||
import org.gradle.api.file.Directory
 | 
			
		||||
import org.gradle.api.file.DirectoryProperty
 | 
			
		||||
import org.gradle.api.provider.Provider
 | 
			
		||||
import org.gradle.api.tasks.*
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class NodePlugin : Plugin<Project> {
 | 
			
		||||
    override fun apply(project: Project) {
 | 
			
		||||
        val extension = project.extensions.create("node", NodeExtension::class.java)
 | 
			
		||||
        project.tasks.register(NpmInstall.TASK_NAME, NpmInstall::class.java) {
 | 
			
		||||
            projectRoot.convention(extension.projectRoot)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class NodeExtension(project: Project) {
 | 
			
		||||
    /** The directory containing `package-lock.json` and `node_modules/`. */
 | 
			
		||||
    abstract val projectRoot: DirectoryProperty
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        projectRoot.convention(project.layout.projectDirectory)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Installs node modules as dependencies. */
 | 
			
		||||
abstract class NpmInstall : DefaultTask() {
 | 
			
		||||
    @get:Internal
 | 
			
		||||
    abstract val projectRoot: DirectoryProperty
 | 
			
		||||
 | 
			
		||||
    @get:InputFile
 | 
			
		||||
    @get:PathSensitive(PathSensitivity.NONE)
 | 
			
		||||
    val packageLock: Provider<File> = projectRoot.file("package-lock.json").map { it.asFile }
 | 
			
		||||
 | 
			
		||||
    @get:OutputDirectory
 | 
			
		||||
    val nodeModules: Provider<Directory> = projectRoot.dir("node_modules")
 | 
			
		||||
 | 
			
		||||
    @TaskAction
 | 
			
		||||
    fun install() {
 | 
			
		||||
        project.exec {
 | 
			
		||||
            commandLine("npm", "ci")
 | 
			
		||||
            workingDir = projectRoot.get().asFile
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        internal const val TASK_NAME: String = "npmInstall"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class NpxExecToDir : ExecToDir() {
 | 
			
		||||
    init {
 | 
			
		||||
        dependsOn(NpmInstall.TASK_NAME)
 | 
			
		||||
        executable = "npx"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/ProcessHelpers.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								buildSrc/src/main/kotlin/cc/tweaked/gradle/ProcessHelpers.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
package cc.tweaked.gradle
 | 
			
		||||
 | 
			
		||||
import org.codehaus.groovy.runtime.ProcessGroovyMethods
 | 
			
		||||
import java.io.BufferedReader
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
import java.io.InputStreamReader
 | 
			
		||||
import java.util.stream.Collectors
 | 
			
		||||
 | 
			
		||||
internal object ProcessHelpers {
 | 
			
		||||
    fun startProcess(vararg command: String): Process {
 | 
			
		||||
        // Something randomly passes in "GIT_DIR=" as an environment variable which clobbers everything else. Don't
 | 
			
		||||
        // inherit the environment array!
 | 
			
		||||
        return Runtime.getRuntime().exec(command, arrayOfNulls(0))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun captureOut(vararg command: String): String {
 | 
			
		||||
        val process = startProcess(*command)
 | 
			
		||||
        val result = ProcessGroovyMethods.getText(process)
 | 
			
		||||
        if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun captureLines(vararg command: String): List<String> {
 | 
			
		||||
        return captureLines(startProcess(*command))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun captureLines(process: Process): List<String> {
 | 
			
		||||
        val out = BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
 | 
			
		||||
            reader.lines().filter { it.isNotEmpty() }.collect(Collectors.toList())
 | 
			
		||||
        }
 | 
			
		||||
        ProcessGroovyMethods.closeStreams(process)
 | 
			
		||||
        if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
 | 
			
		||||
        return out
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -78,7 +78,9 @@
 | 
			
		||||
 | 
			
		||||
        <!-- Javadoc -->
 | 
			
		||||
        <!-- TODO: Missing* checks for the dan200.computercraft.api package? -->
 | 
			
		||||
        <module name="AtclauseOrder" />
 | 
			
		||||
        <module name="AtclauseOrder">
 | 
			
		||||
            <property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
 | 
			
		||||
        </module>
 | 
			
		||||
        <module name="InvalidJavadocPosition" />
 | 
			
		||||
        <module name="JavadocBlockTagLocation" />
 | 
			
		||||
        <module name="JavadocMethod"/>
 | 
			
		||||
@@ -107,7 +109,9 @@
 | 
			
		||||
        <module name="LocalFinalVariableName" />
 | 
			
		||||
        <module name="LocalVariableName" />
 | 
			
		||||
        <module name="MemberName" />
 | 
			
		||||
        <module name="MethodName" />
 | 
			
		||||
        <module name="MethodName">
 | 
			
		||||
            <property name="format" value="^(computercraft\$)?[a-z][a-zA-Z0-9]*$" />
 | 
			
		||||
        </module>
 | 
			
		||||
        <module name="MethodTypeParameterName" />
 | 
			
		||||
        <module name="PackageName">
 | 
			
		||||
            <property name="format" value="^dan200\.computercraft(\.[a-z][a-z0-9]*)*" />
 | 
			
		||||
@@ -115,11 +119,6 @@
 | 
			
		||||
        <module name="ParameterName" />
 | 
			
		||||
        <module name="StaticVariableName">
 | 
			
		||||
            <property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
 | 
			
		||||
            <property name="applyToPrivate" value="false" />
 | 
			
		||||
        </module>
 | 
			
		||||
        <module name="StaticVariableName">
 | 
			
		||||
            <property name="format" value="^(s_)?[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
 | 
			
		||||
            <property name="applyToPrivate" value="true" />
 | 
			
		||||
        </module>
 | 
			
		||||
        <module name="TypeName" />
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
#!/usr/bin/env sh
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
test -d bin || mkdir bin
 | 
			
		||||
test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
 | 
			
		||||
chmod +x bin/illuaminate
 | 
			
		||||
 | 
			
		||||
if [ -n ${GITHUB_ACTIONS+x} ]; then
 | 
			
		||||
    # Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md)
 | 
			
		||||
    # for illuaminate.
 | 
			
		||||
    echo "::add-matcher::.github/matchers/illuaminate.json"
 | 
			
		||||
    trap 'echo "::remove-matcher owner=illuaminate::"' EXIT
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
./gradlew luaJavadoc
 | 
			
		||||
bin/illuaminate lint
 | 
			
		||||
							
								
								
									
										42
									
								
								doc/events/file_transfer.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								doc/events/file_transfer.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
---
 | 
			
		||||
module: [kind=event] file_transfer
 | 
			
		||||
since: 1.101.0
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
The @{file_transfer} event is queued when a user drags-and-drops a file on an open computer.
 | 
			
		||||
 | 
			
		||||
This event contains a single argument, that in turn has a single method @{TransferredFiles.getFiles|getFiles}. This
 | 
			
		||||
returns the list of files that are being transferred. Each file is a @{fs.BinaryReadHandle|binary file handle} with an
 | 
			
		||||
additional @{TransferredFile.getName|getName} method.
 | 
			
		||||
 | 
			
		||||
## Return values
 | 
			
		||||
1. @{string}: The event name
 | 
			
		||||
2. @{TransferredFiles}: The list of transferred files.
 | 
			
		||||
 | 
			
		||||
## Example
 | 
			
		||||
Waits for a user to drop files on top of the computer, then prints the list of files and the size of each file.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
local _, files = os.pullEvent("file_transfer")
 | 
			
		||||
for _, file in ipairs(files.getFiles()) do
 | 
			
		||||
  -- Seek to the end of the file to get its size, then go back to the beginning.
 | 
			
		||||
  local size = file.seek("end")
 | 
			
		||||
  file.seek("set", 0)
 | 
			
		||||
 | 
			
		||||
  print(file.getName() .. " " .. file.getSize())
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Example
 | 
			
		||||
Save each transferred file to the computer's storage.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
local _, files = os.pullEvent("file_transfer")
 | 
			
		||||
for _, file in ipairs(files.getFiles()) do
 | 
			
		||||
  local handle = fs.open(file.getName(), "wb")
 | 
			
		||||
  handle.write(file.readAll())
 | 
			
		||||
 | 
			
		||||
  handle.close()
 | 
			
		||||
  file.close()
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										90
									
								
								doc/guides/gps_setup.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								doc/guides/gps_setup.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
---
 | 
			
		||||
module: [kind=guide] gps_setup
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Setting up GPS
 | 
			
		||||
The @{gps} API allows computers and turtles to find their current position using wireless modems.
 | 
			
		||||
 | 
			
		||||
In order to use GPS, you'll need to set up multiple *GPS hosts*. These are computers running the special `gps host`
 | 
			
		||||
program, which tell other computers the host's position. Several hosts running together are known as a *GPS
 | 
			
		||||
constellation*.
 | 
			
		||||
 | 
			
		||||
In order to give the best results, a GPS constellation needs at least four computers. More than four GPS hosts per
 | 
			
		||||
constellation is redundant, but it does not cause problems.
 | 
			
		||||
 | 
			
		||||
## Building a GPS constellation
 | 
			
		||||
{.big-image}
 | 
			
		||||
 | 
			
		||||
We are going to build our GPS constellation as shown in the image above. You will need 4 computers and either 4 wireless
 | 
			
		||||
modems or 4 ender modems. Try not to mix ender and wireless modems together as you might get some odd behavior when your
 | 
			
		||||
requesting computers are out of range.
 | 
			
		||||
 | 
			
		||||
:::tip Ender modems vs wireless modems
 | 
			
		||||
Ender modems have a very large range, which makes them very useful for setting up GPS hosts. If you do this then you
 | 
			
		||||
will likely only need one GPS constellation for the whole dimension (such as the Overworld or Nether).
 | 
			
		||||
 | 
			
		||||
If you do use wireless modems then you may find that you need multiple GPS constellations to cover your needs.
 | 
			
		||||
 | 
			
		||||
A computer needs a wireless or ender modem and to be in range of a GPS constellation that is in the same dimension as it
 | 
			
		||||
to use the GPS API. The reason for this is that ComputerCraft mimics real-life GPS by making use of the distance
 | 
			
		||||
parameter of @{modem_message|modem messages} and some maths.
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
Locate where you want to place your GPS constellation. You will need an area at least 6 blocks high, 6 blocks wide, and
 | 
			
		||||
6 blocks deep (6x6x6). If you are using wireless modems then you may want to build your constellation as high as you can
 | 
			
		||||
because high altitude boosts modem message range and thus the radius that your constellation covers.
 | 
			
		||||
 | 
			
		||||
The GPS constellation will only work when it is in a loaded chunk. If you want your constellation to always be
 | 
			
		||||
accessible, you may want to permanently load the chunk using a vanilla or modded chunk loader. Make sure that your 6x6x6
 | 
			
		||||
area fits in a single chunk to reduce the number of chunks that need to be kept loaded.
 | 
			
		||||
 | 
			
		||||
Let's get started building the constellation! Place your first computer in one of the corners of your 6x6x6. Remember
 | 
			
		||||
which computer this is as other computers need to be placed relative to it. Place the second computer 4 blocks above the
 | 
			
		||||
first. Go back to your first computer and place your third computer 5 blocks in front of your first computer, leaving 4
 | 
			
		||||
blocks of air between them. Finally for the fourth computer, go back to your first computer and place it 5 blocks right
 | 
			
		||||
of your first computer, leaving 4 blocks of air between them.
 | 
			
		||||
 | 
			
		||||
With all four computers placed within the 6x6x6, place one modem on top of each computer. You should have 4 modems and 4
 | 
			
		||||
computers all within your 6x6x6 where each modem is attached to a computer and each computer has a modem.
 | 
			
		||||
 | 
			
		||||
Currently your GPS constellation will not work, that's because each host is not aware that it's a GPS host. We will fix
 | 
			
		||||
this in the next section.
 | 
			
		||||
 | 
			
		||||
## Configuring the constellation
 | 
			
		||||
Now that the structure of your constellation is built, we need to configure each host in it.
 | 
			
		||||
 | 
			
		||||
Go back to the first computer that you placed and create a startup file, by running `edit startup`.
 | 
			
		||||
 | 
			
		||||
Type the following code into the file:
 | 
			
		||||
```lua
 | 
			
		||||
shell.run("gps", "host", x, y, z)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Escape from the computer GUI and then press <kbd>F3</kbd> to open Minecraft's debug screen and then look at the computer
 | 
			
		||||
(without opening the GUI). On the right of the screen about halfway down you should see an entry labeled `Targeted
 | 
			
		||||
Block`, the numbers correspond to the position of the block that you are looking at. Replace `x` with the first number,
 | 
			
		||||
`y` with the second number, and `z` with the third number.
 | 
			
		||||
 | 
			
		||||
For example, if I had a computer at x = 59, y = 5, z = -150, then my <kbd>F3</kbd> debug screen entry would be `Target
 | 
			
		||||
Block: 59, 5, -150` and I would change my startup file to this `shell.run("gps", "host", 59, 5, -150)`.
 | 
			
		||||
 | 
			
		||||
To hide Minecraft's debug screen, press <kbd>F3</kbd> again.
 | 
			
		||||
 | 
			
		||||
Create similar startup files for the other computers in your constellation, making sure to input the each computer's own
 | 
			
		||||
coordinates.
 | 
			
		||||
 | 
			
		||||
:::caution Modem messages come from the computer's position, not the modem's
 | 
			
		||||
Wireless modems transmit from the block that they are attached to *not* the block space that they occupy, the
 | 
			
		||||
coordinates that you input into your GPS host should be the position of the computer and not the position of the modem.
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
Congratulations, your constellation is now fully set up! You can test it by placing another computer close by, placing a
 | 
			
		||||
wireless modem on it, and running the `gps locate` program (or calling the @{gps.locate} function).
 | 
			
		||||
 | 
			
		||||
:::info Why use Minecraft's coordinates?
 | 
			
		||||
CC doesn't care if you use Minecraft's coordinate system, so long as all of the GPS hosts with overlapping ranges use
 | 
			
		||||
the same reference point (requesting computers will get confused if hosts have different reference points). However,
 | 
			
		||||
using MC's coordinate system does provide a nice standard to adopt server-wide. It also is consistent with how command
 | 
			
		||||
computers get their location, they use MC's command system to get their block which returns that in MC's coordinate
 | 
			
		||||
system.
 | 
			
		||||
:::
 | 
			
		||||
@@ -185,7 +185,7 @@ end
 | 
			
		||||
 | 
			
		||||
:::note Confused?
 | 
			
		||||
Don't worry if you don't understand this example. It's quite advanced, and does use some ideas that this guide doesn't
 | 
			
		||||
cover. That said, don't be afraid to ask on [Discord] or [IRC] either!
 | 
			
		||||
cover. That said, don't be afraid to ask on [GitHub Discussions] or [IRC] either!
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
 | 
			
		||||
@@ -200,6 +200,5 @@ This is, I'm afraid, left as an exercise to the reader.
 | 
			
		||||
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
 | 
			
		||||
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
 | 
			
		||||
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
 | 
			
		||||
 | 
			
		||||
[Discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
 | 
			
		||||
[IRC]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
 | 
			
		||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
 | 
			
		||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								doc/images/gps-constellation-example.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/images/gps-constellation-example.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 331 KiB  | 
@@ -37,8 +37,7 @@ little daunting getting started. Thankfully, there's several fantastic tutorials
 | 
			
		||||
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
 | 
			
		||||
various APIs and peripherals provided by the mod.
 | 
			
		||||
 | 
			
		||||
If you get stuck, do pop in to the [Minecraft Computer Mod Discord guild][discord] or ComputerCraft's
 | 
			
		||||
[IRC channel][irc].
 | 
			
		||||
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
 | 
			
		||||
 | 
			
		||||
## Get Involved
 | 
			
		||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
 | 
			
		||||
@@ -51,5 +50,5 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
 | 
			
		||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
 | 
			
		||||
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
 | 
			
		||||
[lua]: https://www.lua.org/ "Lua's main website"
 | 
			
		||||
[discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
 | 
			
		||||
[irc]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
 | 
			
		||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
 | 
			
		||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								doc/mod-page.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								doc/mod-page.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
# 
 | 
			
		||||
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the much-beloved [ComputerCraft], it continues its legacy with better performance, stability, and a wealth of new features.
 | 
			
		||||
 | 
			
		||||
**Fabric support is added by the [CC: Restitched][ccrestitched] project**
 | 
			
		||||
 | 
			
		||||
## Testimonials
 | 
			
		||||
 | 
			
		||||
> I'm not sure what that is [...] I don't know where that came from.
 | 
			
		||||
>
 | 
			
		||||
> \- [direwolf20, December 2020](https://youtu.be/D8Ue9I-SKeM?t=980)
 | 
			
		||||
 | 
			
		||||
> It is basically ComputerCraft. It has the turtles, and the computers, and writing Lua programs and all that stuff.
 | 
			
		||||
>
 | 
			
		||||
> \- [direwolf20, May 2022](https://youtu.be/7Ruq33XmQIQ?t=537)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
 | 
			
		||||
writing code and automating your Minecraft world.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
While computers are incredibly powerful, they're rather limited by their inability to move about. *Turtles* are the
 | 
			
		||||
solution here. They can move about the world, placing and breaking blocks, swinging a sword to protect you from zombies,
 | 
			
		||||
or whatever else you program them to!
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
Not all problems can be solved with a pickaxe though, and so CC: Tweaked also provides a bunch of additional peripherals
 | 
			
		||||
for your computers. You can play a tune with speakers, display text or images on a monitor, connect all your
 | 
			
		||||
computers together with modems, and much more.
 | 
			
		||||
 | 
			
		||||
Computers can now also interact with inventories such as chests, allowing you to build complex inventory and item
 | 
			
		||||
management systems.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## Getting Started
 | 
			
		||||
While ComputerCraft is lovely for both experienced programmers and for people who have never coded before, it can be a
 | 
			
		||||
little daunting getting started. Thankfully, there's several fantastic tutorials out there:
 | 
			
		||||
 | 
			
		||||
 - [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
 | 
			
		||||
 - [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
 | 
			
		||||
 - [Lyqyd's Computer Basics 1](http://www.computercraft.info/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
 | 
			
		||||
 | 
			
		||||
Once you're a little more familiar with the mod, the [wiki](https://tweaked.cc/) provides more detailed documentation on the
 | 
			
		||||
various APIs and peripherals provided by the mod.
 | 
			
		||||
 | 
			
		||||
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
 | 
			
		||||
 | 
			
		||||
## Get Involved
 | 
			
		||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
 | 
			
		||||
 | 
			
		||||
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
 | 
			
		||||
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
 | 
			
		||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
 | 
			
		||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
 | 
			
		||||
[ccrestitched]: https://modrinth.com/mod/cc-restitched "Download CC: Restitched from Modrinth"
 | 
			
		||||
[lua]: https://www.lua.org/ "Lua's main website"
 | 
			
		||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
 | 
			
		||||
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
 | 
			
		||||
@@ -1,34 +0,0 @@
 | 
			
		||||
--- @module fs
 | 
			
		||||
 | 
			
		||||
--- Returns true if a path is mounted to the parent filesystem.
 | 
			
		||||
--
 | 
			
		||||
-- The root filesystem "/" is considered a mount, along with disk folders and
 | 
			
		||||
-- the rom folder. Other programs (such as network shares) can exstend this to
 | 
			
		||||
-- make other mount types by correctly assigning their return value for getDrive.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string path The path to check.
 | 
			
		||||
-- @treturn boolean If the path is mounted, rather than a normal file/folder.
 | 
			
		||||
-- @throws If the path does not exist.
 | 
			
		||||
-- @see getDrive
 | 
			
		||||
-- @since 1.87.0
 | 
			
		||||
function isDriveRoot(path) end
 | 
			
		||||
 | 
			
		||||
--[[- Provides completion for a file or directory name, suitable for use with
 | 
			
		||||
@{_G.read}.
 | 
			
		||||
 | 
			
		||||
When a directory is a possible candidate for completion, two entries are
 | 
			
		||||
included - one with a trailing slash (indicating that entries within this
 | 
			
		||||
directory exist) and one without it (meaning this entry is an immediate
 | 
			
		||||
completion candidate). `include_dirs` can be set to @{false} to only include
 | 
			
		||||
those with a trailing slash.
 | 
			
		||||
 | 
			
		||||
@tparam string path The path to complete.
 | 
			
		||||
@tparam string location The location where paths are resolved from.
 | 
			
		||||
@tparam[opt] boolean include_files When @{false}, only directories will be
 | 
			
		||||
included in the returned list.
 | 
			
		||||
@tparam[opt] boolean include_dirs When @{false}, "raw" directories will not be
 | 
			
		||||
included in the returned list.
 | 
			
		||||
@treturn { string... } A list of possible completion candidates.
 | 
			
		||||
@since 1.74
 | 
			
		||||
]]
 | 
			
		||||
function complete(path, location, include_files, include_dirs) end
 | 
			
		||||
@@ -14,7 +14,7 @@ thread, not the whole program.
 | 
			
		||||
 | 
			
		||||
:::tip
 | 
			
		||||
Because sleep internally uses timers, it is a function that yields. This means
 | 
			
		||||
that you can use it to prevent "Too long without yielding" errors, however, as
 | 
			
		||||
that you can use it to prevent "Too long without yielding" errors. However, as
 | 
			
		||||
the minimum sleep time is 0.05 seconds, it will slow your program down.
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,177 +0,0 @@
 | 
			
		||||
--- Make HTTP requests, sending and receiving data to a remote web server.
 | 
			
		||||
--
 | 
			
		||||
-- @module http
 | 
			
		||||
-- @since 1.1
 | 
			
		||||
-- @see local_ips To allow accessing servers running on your local network.
 | 
			
		||||
 | 
			
		||||
--- Asynchronously make a HTTP request to the given url.
 | 
			
		||||
--
 | 
			
		||||
-- This returns immediately, a @{http_success} or @{http_failure} will be queued
 | 
			
		||||
-- once the request has completed.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam      string url   The url to request
 | 
			
		||||
-- @tparam[opt] string body  An optional string containing the body of the
 | 
			
		||||
-- request. If specified, a `POST` request will be made instead.
 | 
			
		||||
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
 | 
			
		||||
-- of this request.
 | 
			
		||||
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
 | 
			
		||||
-- the body will not be UTF-8 encoded, and the received response will not be
 | 
			
		||||
-- decoded.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam[2] {
 | 
			
		||||
--   url = string, body? = string, headers? = { [string] = string },
 | 
			
		||||
--   binary? = boolean, method? = string, redirect? = boolean,
 | 
			
		||||
-- } request Options for the request.
 | 
			
		||||
--
 | 
			
		||||
-- This table form is an expanded version of the previous syntax. All arguments
 | 
			
		||||
-- from above are passed in as fields instead (for instance,
 | 
			
		||||
-- `http.request("https://example.com")` becomes `http.request { url =
 | 
			
		||||
-- "https://example.com" }`).
 | 
			
		||||
--
 | 
			
		||||
-- This table also accepts several additional options:
 | 
			
		||||
--
 | 
			
		||||
--  - `method`: Which HTTP method to use, for instance `"PATCH"` or `"DELETE"`.
 | 
			
		||||
--  - `redirect`: Whether to follow HTTP redirects. Defaults to true.
 | 
			
		||||
--
 | 
			
		||||
-- @see http.get  For a synchronous way to make GET requests.
 | 
			
		||||
-- @see http.post For a synchronous way to make POST requests.
 | 
			
		||||
--
 | 
			
		||||
-- @changed 1.63 Added argument for headers.
 | 
			
		||||
-- @changed 1.80pr1 Added argument for binary handles.
 | 
			
		||||
-- @changed 1.80pr1.6 Added support for table argument.
 | 
			
		||||
-- @changed 1.86.0 Added PATCH and TRACE methods.
 | 
			
		||||
function request(...) end
 | 
			
		||||
 | 
			
		||||
--- Make a HTTP GET request to the given url.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string url   The url to request
 | 
			
		||||
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
 | 
			
		||||
-- of this request.
 | 
			
		||||
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
 | 
			
		||||
-- the body will not be UTF-8 encoded, and the received response will not be
 | 
			
		||||
-- decoded.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam[2] {
 | 
			
		||||
--   url = string, headers? = { [string] = string },
 | 
			
		||||
--   binary? = boolean, method? = string, redirect? = boolean,
 | 
			
		||||
-- } request Options for the request. See @{http.request} for details on how
 | 
			
		||||
-- these options behave.
 | 
			
		||||
--
 | 
			
		||||
-- @treturn Response The resulting http response, which can be read from.
 | 
			
		||||
-- @treturn[2] nil When the http request failed, such as in the event of a 404
 | 
			
		||||
-- error or connection timeout.
 | 
			
		||||
-- @treturn string A message detailing why the request failed.
 | 
			
		||||
-- @treturn Response|nil The failing http response, if available.
 | 
			
		||||
--
 | 
			
		||||
-- @changed 1.63 Added argument for headers.
 | 
			
		||||
-- @changed 1.80pr1 Response handles are now returned on error if available.
 | 
			
		||||
-- @changed 1.80pr1 Added argument for binary handles.
 | 
			
		||||
-- @changed 1.80pr1.6 Added support for table argument.
 | 
			
		||||
-- @changed 1.86.0 Added PATCH and TRACE methods.
 | 
			
		||||
--
 | 
			
		||||
-- @usage Make a request to [example.tweaked.cc](https://example.tweaked.cc),
 | 
			
		||||
-- and print the returned page.
 | 
			
		||||
-- ```lua
 | 
			
		||||
-- local request = http.get("https://example.tweaked.cc")
 | 
			
		||||
-- print(request.readAll())
 | 
			
		||||
-- -- => HTTP is working!
 | 
			
		||||
-- request.close()
 | 
			
		||||
-- ```
 | 
			
		||||
function get(...) end
 | 
			
		||||
 | 
			
		||||
--- Make a HTTP POST request to the given url.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string url   The url to request
 | 
			
		||||
-- @tparam string body  The body of the POST request.
 | 
			
		||||
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
 | 
			
		||||
-- of this request.
 | 
			
		||||
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
 | 
			
		||||
-- the body will not be UTF-8 encoded, and the received response will not be
 | 
			
		||||
-- decoded.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam[2] {
 | 
			
		||||
--   url = string, body? = string, headers? = { [string] = string },
 | 
			
		||||
--   binary? = boolean, method? = string, redirect? = boolean,
 | 
			
		||||
-- } request Options for the request. See @{http.request} for details on how
 | 
			
		||||
-- these options behave.
 | 
			
		||||
--
 | 
			
		||||
-- @treturn Response The resulting http response, which can be read from.
 | 
			
		||||
-- @treturn[2] nil When the http request failed, such as in the event of a 404
 | 
			
		||||
-- error or connection timeout.
 | 
			
		||||
-- @treturn string A message detailing why the request failed.
 | 
			
		||||
-- @treturn Response|nil The failing http response, if available.
 | 
			
		||||
--
 | 
			
		||||
-- @since 1.31
 | 
			
		||||
-- @changed 1.63 Added argument for headers.
 | 
			
		||||
-- @changed 1.80pr1 Response handles are now returned on error if available.
 | 
			
		||||
-- @changed 1.80pr1 Added argument for binary handles.
 | 
			
		||||
-- @changed 1.80pr1.6 Added support for table argument.
 | 
			
		||||
-- @changed 1.86.0 Added PATCH and TRACE methods.
 | 
			
		||||
function post(...) end
 | 
			
		||||
 | 
			
		||||
--- Asynchronously determine whether a URL can be requested.
 | 
			
		||||
--
 | 
			
		||||
-- If this returns `true`, one should also listen for @{http_check} which will
 | 
			
		||||
-- container further information about whether the URL is allowed or not.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string url The URL to check.
 | 
			
		||||
-- @treturn true When this url is not invalid. This does not imply that it is
 | 
			
		||||
-- allowed - see the comment above.
 | 
			
		||||
-- @treturn[2] false When this url is invalid.
 | 
			
		||||
-- @treturn string A reason why this URL is not valid (for instance, if it is
 | 
			
		||||
-- malformed, or blocked).
 | 
			
		||||
--
 | 
			
		||||
-- @see http.checkURL For a synchronous version.
 | 
			
		||||
function checkURLAsync(url) end
 | 
			
		||||
 | 
			
		||||
--- Determine whether a URL can be requested.
 | 
			
		||||
--
 | 
			
		||||
-- If this returns `true`, one should also listen for @{http_check} which will
 | 
			
		||||
-- container further information about whether the URL is allowed or not.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string url The URL to check.
 | 
			
		||||
-- @treturn true When this url is valid and can be requested via @{http.request}.
 | 
			
		||||
-- @treturn[2] false When this url is invalid.
 | 
			
		||||
-- @treturn string A reason why this URL is not valid (for instance, if it is
 | 
			
		||||
-- malformed, or blocked).
 | 
			
		||||
--
 | 
			
		||||
-- @see http.checkURLAsync For an asynchronous version.
 | 
			
		||||
--
 | 
			
		||||
-- @usage
 | 
			
		||||
-- ```lua
 | 
			
		||||
-- print(http.checkURL("https://example.tweaked.cc/"))
 | 
			
		||||
-- -- => true
 | 
			
		||||
-- print(http.checkURL("http://localhost/"))
 | 
			
		||||
-- -- => false Domain not permitted
 | 
			
		||||
-- print(http.checkURL("not a url"))
 | 
			
		||||
-- -- => false URL malformed
 | 
			
		||||
-- ```
 | 
			
		||||
function checkURL(url) end
 | 
			
		||||
 | 
			
		||||
--- Open a websocket.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string url The websocket url to connect to. This should have the
 | 
			
		||||
-- `ws://` or `wss://` protocol.
 | 
			
		||||
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
 | 
			
		||||
-- of the initial websocket connection.
 | 
			
		||||
--
 | 
			
		||||
-- @treturn Websocket The websocket connection.
 | 
			
		||||
-- @treturn[2] false If the websocket connection failed.
 | 
			
		||||
-- @treturn string An error message describing why the connection failed.
 | 
			
		||||
-- @since 1.80pr1.1
 | 
			
		||||
-- @changed 1.80pr1.3 No longer asynchronous.
 | 
			
		||||
-- @changed 1.95.3 Added User-Agent to default headers.
 | 
			
		||||
function websocket(url, headers) end
 | 
			
		||||
 | 
			
		||||
--- Asynchronously open a websocket.
 | 
			
		||||
--
 | 
			
		||||
-- This returns immediately, a @{websocket_success} or @{websocket_failure}
 | 
			
		||||
-- will be queued once the request has completed.
 | 
			
		||||
--
 | 
			
		||||
-- @tparam string url The websocket url to connect to. This should have the
 | 
			
		||||
-- `ws://` or `wss://` protocol.
 | 
			
		||||
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
 | 
			
		||||
-- of the initial websocket connection.
 | 
			
		||||
-- @since 1.80pr1.3
 | 
			
		||||
-- @changed 1.95.3 Added User-Agent to default headers.
 | 
			
		||||
function websocketAsync(url, headers) end
 | 
			
		||||
@@ -1,11 +1,11 @@
 | 
			
		||||
org.gradle.jvmargs=-Xmx3G
 | 
			
		||||
org.gradle.parallel=true
 | 
			
		||||
 | 
			
		||||
kotlin.stdlib.default.dependency=false
 | 
			
		||||
kotlin.jvm.target.validation.mode=error
 | 
			
		||||
 | 
			
		||||
# Mod properties
 | 
			
		||||
mod_version=1.100.8
 | 
			
		||||
modVersion=1.101.3
 | 
			
		||||
 | 
			
		||||
# Minecraft properties (update mods.toml when changing)
 | 
			
		||||
mc_version=1.18.2
 | 
			
		||||
mapping_version=2022.03.13
 | 
			
		||||
forge_version=40.1.0
 | 
			
		||||
# NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING
 | 
			
		||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
 | 
			
		||||
mcVersion=1.19.2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										71
									
								
								gradle/libs.versions.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								gradle/libs.versions.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
[versions]
 | 
			
		||||
 | 
			
		||||
# Minecraft
 | 
			
		||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
 | 
			
		||||
forge = "43.1.1"
 | 
			
		||||
parchment = "2022.10.16"
 | 
			
		||||
parchmentMc = "1.19.2"
 | 
			
		||||
 | 
			
		||||
autoService = "1.0.1"
 | 
			
		||||
cobalt = "0.6.0"
 | 
			
		||||
jetbrainsAnnotations = "23.0.0"
 | 
			
		||||
kotlin = "1.7.10"
 | 
			
		||||
kotlin-coroutines = "1.6.0"
 | 
			
		||||
 | 
			
		||||
# Testing
 | 
			
		||||
hamcrest = "2.2"
 | 
			
		||||
jqwik = "1.7.0"
 | 
			
		||||
junit = "5.9.1"
 | 
			
		||||
 | 
			
		||||
# Build tools
 | 
			
		||||
cctJavadoc = "1.5.2"
 | 
			
		||||
checkstyle = "10.3.4"
 | 
			
		||||
curseForgeGradle = "1.0.11"
 | 
			
		||||
forgeGradle = "5.1.+"
 | 
			
		||||
githubRelease = "2.2.12"
 | 
			
		||||
illuaminate = "0.1.0-20-g8c483a4"
 | 
			
		||||
librarian = "1.+"
 | 
			
		||||
minotaur = "2.+"
 | 
			
		||||
mixinGradle = "0.7.+"
 | 
			
		||||
shadow = "7.1.2"
 | 
			
		||||
spotless = "6.8.0"
 | 
			
		||||
taskTree = "2.1.0"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
 | 
			
		||||
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
 | 
			
		||||
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
 | 
			
		||||
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
 | 
			
		||||
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
 | 
			
		||||
 | 
			
		||||
# Testing
 | 
			
		||||
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
 | 
			
		||||
jqwik-api = { module = "net.jqwik:jqwik-api", version.ref = "jqwik" }
 | 
			
		||||
jqwik-engine = { module = "net.jqwik:jqwik-engine", version.ref = "jqwik" }
 | 
			
		||||
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
 | 
			
		||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
 | 
			
		||||
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
 | 
			
		||||
 | 
			
		||||
# Build tools
 | 
			
		||||
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
 | 
			
		||||
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
 | 
			
		||||
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
 | 
			
		||||
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
 | 
			
		||||
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
 | 
			
		||||
curseForgeGradle = { id = "net.darkhax.curseforgegradle", version.ref = "curseForgeGradle" }
 | 
			
		||||
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
 | 
			
		||||
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
 | 
			
		||||
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
 | 
			
		||||
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
 | 
			
		||||
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
 | 
			
		||||
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
 | 
			
		||||
 | 
			
		||||
[bundles]
 | 
			
		||||
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
 | 
			
		||||
 | 
			
		||||
# Testing
 | 
			
		||||
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
 | 
			
		||||
testRuntime = ["junit-jupiter-engine", "jqwik-engine"]
 | 
			
		||||
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
distributionBase=GRADLE_USER_HOME
 | 
			
		||||
distributionPath=wrapper/dists
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
zipStorePath=wrapper/dists
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(doc
 | 
			
		||||
  (destination build/docs/lua)
 | 
			
		||||
  (destination build/illuaminate)
 | 
			
		||||
  (index doc/index.md)
 | 
			
		||||
 | 
			
		||||
  (site
 | 
			
		||||
@@ -111,6 +111,6 @@
 | 
			
		||||
  (lint
 | 
			
		||||
    (globals
 | 
			
		||||
      :max sleep write
 | 
			
		||||
      cct_test describe expect howlci fail it pending stub)))
 | 
			
		||||
      cct_test describe expect howlci fail it pending stub before_each)))
 | 
			
		||||
 | 
			
		||||
(at /src/web/mount/expr_template.lua (lint (globals :max __expr__)))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										648
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										648
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -11,7 +11,7 @@
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@rollup/plugin-typescript": "^8.2.5",
 | 
			
		||||
    "@rollup/plugin-url": "^6.1.0",
 | 
			
		||||
    "@rollup/plugin-url": "^7.0.0",
 | 
			
		||||
    "@types/glob": "^7.2.0",
 | 
			
		||||
    "@types/react-dom": "^18.0.5",
 | 
			
		||||
    "glob": "^8.0.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -13,5 +13,5 @@ pluginManagement {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val mc_version: String by settings
 | 
			
		||||
rootProject.name = "cc-tweaked-${mc_version}"
 | 
			
		||||
val mcVersion: String by settings
 | 
			
		||||
rootProject.name = "cc-tweaked-$mcVersion"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										125
									
								
								src/generated/resources/assets/computercraft/blockstates/cable.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/generated/resources/assets/computercraft/blockstates/cable.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
{
 | 
			
		||||
  "multipart": [
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/cable_core_facing", "x": 90},
 | 
			
		||||
      "when": {
 | 
			
		||||
        "OR": [
 | 
			
		||||
          {"cable": "true", "east": "false", "north": "false", "south": "false", "up": "true", "west": "false"},
 | 
			
		||||
          {"cable": "true", "down": "true", "east": "false", "north": "false", "south": "false", "west": "false"}
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/cable_core_facing", "y": 0},
 | 
			
		||||
      "when": {
 | 
			
		||||
        "OR": [
 | 
			
		||||
          {
 | 
			
		||||
            "cable": "true",
 | 
			
		||||
            "down": "false",
 | 
			
		||||
            "east": "false",
 | 
			
		||||
            "north": "false",
 | 
			
		||||
            "south": "false",
 | 
			
		||||
            "up": "false",
 | 
			
		||||
            "west": "false"
 | 
			
		||||
          },
 | 
			
		||||
          {"cable": "true", "down": "false", "east": "false", "north": "true", "up": "false", "west": "false"},
 | 
			
		||||
          {"cable": "true", "down": "false", "east": "false", "south": "true", "up": "false", "west": "false"}
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/cable_core_facing", "y": 90},
 | 
			
		||||
      "when": {
 | 
			
		||||
        "OR": [
 | 
			
		||||
          {"cable": "true", "down": "false", "east": "true", "north": "false", "south": "false", "up": "false"},
 | 
			
		||||
          {"cable": "true", "down": "false", "north": "false", "south": "false", "up": "false", "west": "true"}
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/cable_core_any"},
 | 
			
		||||
      "when": {
 | 
			
		||||
        "OR": [
 | 
			
		||||
          {"cable": "true", "down": "true", "north": "true"},
 | 
			
		||||
          {"cable": "true", "down": "true", "south": "true"},
 | 
			
		||||
          {"cable": "true", "down": "true", "west": "true"},
 | 
			
		||||
          {"cable": "true", "down": "true", "east": "true"},
 | 
			
		||||
          {"cable": "true", "north": "true", "up": "true"},
 | 
			
		||||
          {"cable": "true", "south": "true", "up": "true"},
 | 
			
		||||
          {"cable": "true", "up": "true", "west": "true"},
 | 
			
		||||
          {"cable": "true", "east": "true", "up": "true"},
 | 
			
		||||
          {"cable": "true", "north": "true", "west": "true"},
 | 
			
		||||
          {"cable": "true", "east": "true", "north": "true"},
 | 
			
		||||
          {"cable": "true", "south": "true", "west": "true"},
 | 
			
		||||
          {"cable": "true", "east": "true", "south": "true"}
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/cable_arm", "x": 270, "y": 0}, "when": {"down": "true"}},
 | 
			
		||||
    {"apply": {"model": "computercraft:block/cable_arm", "x": 90, "y": 0}, "when": {"up": "true"}},
 | 
			
		||||
    {"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 180}, "when": {"north": "true"}},
 | 
			
		||||
    {"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 0}, "when": {"south": "true"}},
 | 
			
		||||
    {"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 90}, "when": {"west": "true"}},
 | 
			
		||||
    {"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 270}, "when": {"east": "true"}},
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_off", "x": 90, "y": 0}, "when": {"modem": "down_off"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 90, "y": 0},
 | 
			
		||||
      "when": {"modem": "down_off_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_on", "x": 90, "y": 0}, "when": {"modem": "down_on"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 90, "y": 0},
 | 
			
		||||
      "when": {"modem": "down_on_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_off", "x": 270, "y": 0}, "when": {"modem": "up_off"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 270, "y": 0},
 | 
			
		||||
      "when": {"modem": "up_off_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_on", "x": 270, "y": 0}, "when": {"modem": "up_on"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 270, "y": 0},
 | 
			
		||||
      "when": {"modem": "up_on_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 0}, "when": {"modem": "north_off"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 0},
 | 
			
		||||
      "when": {"modem": "north_off_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 0}, "when": {"modem": "north_on"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 0},
 | 
			
		||||
      "when": {"modem": "north_on_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 180}, "when": {"modem": "south_off"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 180},
 | 
			
		||||
      "when": {"modem": "south_off_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 180}, "when": {"modem": "south_on"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 180},
 | 
			
		||||
      "when": {"modem": "south_on_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 270}, "when": {"modem": "west_off"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 270},
 | 
			
		||||
      "when": {"modem": "west_off_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 270}, "when": {"modem": "west_on"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 270},
 | 
			
		||||
      "when": {"modem": "west_on_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 90}, "when": {"modem": "east_off"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 90},
 | 
			
		||||
      "when": {"modem": "east_off_peripheral"}
 | 
			
		||||
    },
 | 
			
		||||
    {"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 90}, "when": {"modem": "east_on"}},
 | 
			
		||||
    {
 | 
			
		||||
      "apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 90},
 | 
			
		||||
      "when": {"modem": "east_on_peripheral"}
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,49 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=north,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_off"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_off",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_off",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_off",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_on"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_on",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_on",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_on",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_blinking"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_blinking",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_blinking",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_advanced_blinking",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=east,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 90},
 | 
			
		||||
    "facing=east,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 90},
 | 
			
		||||
    "facing=east,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 90},
 | 
			
		||||
    "facing=north,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 0},
 | 
			
		||||
    "facing=north,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 0},
 | 
			
		||||
    "facing=north,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 0},
 | 
			
		||||
    "facing=south,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 180},
 | 
			
		||||
    "facing=south,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 180},
 | 
			
		||||
    "facing=south,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 180},
 | 
			
		||||
    "facing=west,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 270},
 | 
			
		||||
    "facing=west,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 270},
 | 
			
		||||
    "facing=west,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,49 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=north,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_off"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_off",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_off",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_off",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_on"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_on",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_on",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_on",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_blinking"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_blinking",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_blinking",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_command_blinking",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=east,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 90},
 | 
			
		||||
    "facing=east,state=off": {"model": "computercraft:block/computer_command_off", "y": 90},
 | 
			
		||||
    "facing=east,state=on": {"model": "computercraft:block/computer_command_on", "y": 90},
 | 
			
		||||
    "facing=north,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 0},
 | 
			
		||||
    "facing=north,state=off": {"model": "computercraft:block/computer_command_off", "y": 0},
 | 
			
		||||
    "facing=north,state=on": {"model": "computercraft:block/computer_command_on", "y": 0},
 | 
			
		||||
    "facing=south,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 180},
 | 
			
		||||
    "facing=south,state=off": {"model": "computercraft:block/computer_command_off", "y": 180},
 | 
			
		||||
    "facing=south,state=on": {"model": "computercraft:block/computer_command_on", "y": 180},
 | 
			
		||||
    "facing=west,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 270},
 | 
			
		||||
    "facing=west,state=off": {"model": "computercraft:block/computer_command_off", "y": 270},
 | 
			
		||||
    "facing=west,state=on": {"model": "computercraft:block/computer_command_on", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,49 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=north,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_off"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_off",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_off",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=off": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_off",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_on"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_on",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_on",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=on": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_on",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_blinking"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_blinking",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_blinking",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,state=blinking": {
 | 
			
		||||
      "model": "computercraft:block/computer_normal_blinking",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=east,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 90},
 | 
			
		||||
    "facing=east,state=off": {"model": "computercraft:block/computer_normal_off", "y": 90},
 | 
			
		||||
    "facing=east,state=on": {"model": "computercraft:block/computer_normal_on", "y": 90},
 | 
			
		||||
    "facing=north,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 0},
 | 
			
		||||
    "facing=north,state=off": {"model": "computercraft:block/computer_normal_off", "y": 0},
 | 
			
		||||
    "facing=north,state=on": {"model": "computercraft:block/computer_normal_on", "y": 0},
 | 
			
		||||
    "facing=south,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 180},
 | 
			
		||||
    "facing=south,state=off": {"model": "computercraft:block/computer_normal_off", "y": 180},
 | 
			
		||||
    "facing=south,state=on": {"model": "computercraft:block/computer_normal_on", "y": 180},
 | 
			
		||||
    "facing=west,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 270},
 | 
			
		||||
    "facing=west,state=off": {"model": "computercraft:block/computer_normal_off", "y": 270},
 | 
			
		||||
    "facing=west,state=on": {"model": "computercraft:block/computer_normal_on", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								src/generated/resources/assets/computercraft/blockstates/disk_drive.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/generated/resources/assets/computercraft/blockstates/disk_drive.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=east,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 90},
 | 
			
		||||
    "facing=east,state=full": {"model": "computercraft:block/disk_drive_full", "y": 90},
 | 
			
		||||
    "facing=east,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 90},
 | 
			
		||||
    "facing=north,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 0},
 | 
			
		||||
    "facing=north,state=full": {"model": "computercraft:block/disk_drive_full", "y": 0},
 | 
			
		||||
    "facing=north,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 0},
 | 
			
		||||
    "facing=south,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 180},
 | 
			
		||||
    "facing=south,state=full": {"model": "computercraft:block/disk_drive_full", "y": 180},
 | 
			
		||||
    "facing=south,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 180},
 | 
			
		||||
    "facing=west,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 270},
 | 
			
		||||
    "facing=west,state=full": {"model": "computercraft:block/disk_drive_full", "y": 270},
 | 
			
		||||
    "facing=west,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										20
									
								
								src/generated/resources/assets/computercraft/blockstates/printer.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/generated/resources/assets/computercraft/blockstates/printer.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "bottom=false,facing=east,top=false": {"model": "computercraft:block/printer_empty", "y": 90},
 | 
			
		||||
    "bottom=false,facing=east,top=true": {"model": "computercraft:block/printer_top_full", "y": 90},
 | 
			
		||||
    "bottom=false,facing=north,top=false": {"model": "computercraft:block/printer_empty", "y": 0},
 | 
			
		||||
    "bottom=false,facing=north,top=true": {"model": "computercraft:block/printer_top_full", "y": 0},
 | 
			
		||||
    "bottom=false,facing=south,top=false": {"model": "computercraft:block/printer_empty", "y": 180},
 | 
			
		||||
    "bottom=false,facing=south,top=true": {"model": "computercraft:block/printer_top_full", "y": 180},
 | 
			
		||||
    "bottom=false,facing=west,top=false": {"model": "computercraft:block/printer_empty", "y": 270},
 | 
			
		||||
    "bottom=false,facing=west,top=true": {"model": "computercraft:block/printer_top_full", "y": 270},
 | 
			
		||||
    "bottom=true,facing=east,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 90},
 | 
			
		||||
    "bottom=true,facing=east,top=true": {"model": "computercraft:block/printer_both_full", "y": 90},
 | 
			
		||||
    "bottom=true,facing=north,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 0},
 | 
			
		||||
    "bottom=true,facing=north,top=true": {"model": "computercraft:block/printer_both_full", "y": 0},
 | 
			
		||||
    "bottom=true,facing=south,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 180},
 | 
			
		||||
    "bottom=true,facing=south,top=true": {"model": "computercraft:block/printer_both_full", "y": 180},
 | 
			
		||||
    "bottom=true,facing=west,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 270},
 | 
			
		||||
    "bottom=true,facing=west,top=true": {"model": "computercraft:block/printer_both_full", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=north": {
 | 
			
		||||
      "model": "computercraft:block/speaker"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south": {
 | 
			
		||||
      "model": "computercraft:block/speaker",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west": {
 | 
			
		||||
      "model": "computercraft:block/speaker",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east": {
 | 
			
		||||
      "model": "computercraft:block/speaker",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=east": {"model": "computercraft:block/speaker", "y": 90},
 | 
			
		||||
    "facing=north": {"model": "computercraft:block/speaker"},
 | 
			
		||||
    "facing=south": {"model": "computercraft:block/speaker", "y": 180},
 | 
			
		||||
    "facing=west": {"model": "computercraft:block/speaker", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=north": {
 | 
			
		||||
      "model": "computercraft:block/turtle_advanced"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south": {
 | 
			
		||||
      "model": "computercraft:block/turtle_advanced",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west": {
 | 
			
		||||
      "model": "computercraft:block/turtle_advanced",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east": {
 | 
			
		||||
      "model": "computercraft:block/turtle_advanced",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=east": {"model": "computercraft:block/turtle_advanced", "y": 90},
 | 
			
		||||
    "facing=north": {"model": "computercraft:block/turtle_advanced", "y": 0},
 | 
			
		||||
    "facing=south": {"model": "computercraft:block/turtle_advanced", "y": 180},
 | 
			
		||||
    "facing=west": {"model": "computercraft:block/turtle_advanced", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=north": {
 | 
			
		||||
      "model": "computercraft:block/turtle_normal"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south": {
 | 
			
		||||
      "model": "computercraft:block/turtle_normal",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west": {
 | 
			
		||||
      "model": "computercraft:block/turtle_normal",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east": {
 | 
			
		||||
      "model": "computercraft:block/turtle_normal",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=east": {"model": "computercraft:block/turtle_normal", "y": 90},
 | 
			
		||||
    "facing=north": {"model": "computercraft:block/turtle_normal", "y": 0},
 | 
			
		||||
    "facing=south": {"model": "computercraft:block/turtle_normal", "y": 180},
 | 
			
		||||
    "facing=west": {"model": "computercraft:block/turtle_normal", "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,16 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "modem=false,peripheral=false": {
 | 
			
		||||
      "model": "computercraft:block/wired_modem_full_off"
 | 
			
		||||
    },
 | 
			
		||||
    "modem=true,peripheral=false": {
 | 
			
		||||
      "model": "computercraft:block/wired_modem_full_on"
 | 
			
		||||
    },
 | 
			
		||||
    "modem=false,peripheral=true": {
 | 
			
		||||
      "model": "computercraft:block/wired_modem_full_off_peripheral"
 | 
			
		||||
    },
 | 
			
		||||
    "modem=true,peripheral=true": {
 | 
			
		||||
      "model": "computercraft:block/wired_modem_full_on_peripheral"
 | 
			
		||||
    }
 | 
			
		||||
    "modem=false,peripheral=false": {"model": "computercraft:block/wired_modem_full_off"},
 | 
			
		||||
    "modem=false,peripheral=true": {"model": "computercraft:block/wired_modem_full_off_peripheral"},
 | 
			
		||||
    "modem=true,peripheral=false": {"model": "computercraft:block/wired_modem_full_on"},
 | 
			
		||||
    "modem=true,peripheral=true": {"model": "computercraft:block/wired_modem_full_on_peripheral"}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,54 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=down,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_off",
 | 
			
		||||
      "x": 90,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=up,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_off",
 | 
			
		||||
      "x": 270,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_off"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_off",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_off",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_off",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=down,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_on",
 | 
			
		||||
      "x": 90,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=up,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_on",
 | 
			
		||||
      "x": 270,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_on"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_on",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_on",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_advanced_on",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=down,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 90, "y": 0},
 | 
			
		||||
    "facing=down,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 90, "y": 0},
 | 
			
		||||
    "facing=east,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 90},
 | 
			
		||||
    "facing=east,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 90},
 | 
			
		||||
    "facing=north,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 0},
 | 
			
		||||
    "facing=north,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 0},
 | 
			
		||||
    "facing=south,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 180},
 | 
			
		||||
    "facing=south,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 180},
 | 
			
		||||
    "facing=up,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 270, "y": 0},
 | 
			
		||||
    "facing=up,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 270, "y": 0},
 | 
			
		||||
    "facing=west,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 270},
 | 
			
		||||
    "facing=west,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,54 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "facing=down,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_off",
 | 
			
		||||
      "x": 90,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=up,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_off",
 | 
			
		||||
      "x": 270,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_off"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_off",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_off",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,on=false": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_off",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=down,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_on",
 | 
			
		||||
      "x": 90,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=up,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_on",
 | 
			
		||||
      "x": 270,
 | 
			
		||||
      "y": 90
 | 
			
		||||
    },
 | 
			
		||||
    "facing=north,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_on"
 | 
			
		||||
    },
 | 
			
		||||
    "facing=south,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_on",
 | 
			
		||||
      "y": 180
 | 
			
		||||
    },
 | 
			
		||||
    "facing=west,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_on",
 | 
			
		||||
      "y": 270
 | 
			
		||||
    },
 | 
			
		||||
    "facing=east,on=true": {
 | 
			
		||||
      "model": "computercraft:block/wireless_modem_normal_on",
 | 
			
		||||
      "y": 90
 | 
			
		||||
    }
 | 
			
		||||
    "facing=down,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 90, "y": 0},
 | 
			
		||||
    "facing=down,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 90, "y": 0},
 | 
			
		||||
    "facing=east,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 90},
 | 
			
		||||
    "facing=east,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 90},
 | 
			
		||||
    "facing=north,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 0},
 | 
			
		||||
    "facing=north,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 0},
 | 
			
		||||
    "facing=south,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 180},
 | 
			
		||||
    "facing=south,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 180},
 | 
			
		||||
    "facing=up,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 270, "y": 0},
 | 
			
		||||
    "facing=up,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 270, "y": 0},
 | 
			
		||||
    "facing=west,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 270},
 | 
			
		||||
    "facing=west,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 270}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_advanced_side",
 | 
			
		||||
    "front": "computercraft:block/computer_advanced_front_blink",
 | 
			
		||||
    "side": "computercraft:block/computer_advanced_side",
 | 
			
		||||
    "top": "computercraft:block/computer_advanced_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_advanced_side",
 | 
			
		||||
    "front": "computercraft:block/computer_advanced_front",
 | 
			
		||||
    "side": "computercraft:block/computer_advanced_side",
 | 
			
		||||
    "top": "computercraft:block/computer_advanced_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_advanced_side",
 | 
			
		||||
    "front": "computercraft:block/computer_advanced_front_on",
 | 
			
		||||
    "side": "computercraft:block/computer_advanced_side",
 | 
			
		||||
    "top": "computercraft:block/computer_advanced_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_command_side",
 | 
			
		||||
    "front": "computercraft:block/computer_command_front_blink",
 | 
			
		||||
    "side": "computercraft:block/computer_command_side",
 | 
			
		||||
    "top": "computercraft:block/computer_command_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_command_side",
 | 
			
		||||
    "front": "computercraft:block/computer_command_front",
 | 
			
		||||
    "side": "computercraft:block/computer_command_side",
 | 
			
		||||
    "top": "computercraft:block/computer_command_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_command_side",
 | 
			
		||||
    "front": "computercraft:block/computer_command_front_on",
 | 
			
		||||
    "side": "computercraft:block/computer_command_side",
 | 
			
		||||
    "top": "computercraft:block/computer_command_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_normal_side",
 | 
			
		||||
    "front": "computercraft:block/computer_normal_front_blink",
 | 
			
		||||
    "side": "computercraft:block/computer_normal_side",
 | 
			
		||||
    "top": "computercraft:block/computer_normal_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_normal_side",
 | 
			
		||||
    "front": "computercraft:block/computer_normal_front",
 | 
			
		||||
    "side": "computercraft:block/computer_normal_side",
 | 
			
		||||
    "top": "computercraft:block/computer_normal_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/computer_normal_side",
 | 
			
		||||
    "front": "computercraft:block/computer_normal_front_on",
 | 
			
		||||
    "side": "computercraft:block/computer_normal_side",
 | 
			
		||||
    "top": "computercraft:block/computer_normal_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/generated/resources/assets/computercraft/models/block/disk_drive_empty.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/generated/resources/assets/computercraft/models/block/disk_drive_empty.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "front": "computercraft:block/disk_drive_front",
 | 
			
		||||
    "side": "computercraft:block/disk_drive_side",
 | 
			
		||||
    "top": "computercraft:block/disk_drive_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/generated/resources/assets/computercraft/models/block/disk_drive_full.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/generated/resources/assets/computercraft/models/block/disk_drive_full.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "front": "computercraft:block/disk_drive_front_accepted",
 | 
			
		||||
    "side": "computercraft:block/disk_drive_side",
 | 
			
		||||
    "top": "computercraft:block/disk_drive_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/generated/resources/assets/computercraft/models/block/disk_drive_invalid.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/generated/resources/assets/computercraft/models/block/disk_drive_invalid.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "front": "computercraft:block/disk_drive_front_rejected",
 | 
			
		||||
    "side": "computercraft:block/disk_drive_side",
 | 
			
		||||
    "top": "computercraft:block/disk_drive_top"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_32",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_16",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_32"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_36",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_20",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_36"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_4",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_32",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_15",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_33",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_19",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_33"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_45",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_31",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_45"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_34",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_18",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_34"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_46",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_30",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_46"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_40",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_24",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_5",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_40"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_43",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_27",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_6",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_43"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_39",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_25",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_5",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_39"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_42",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_28",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_6",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_42"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_35",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_17",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_35"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_47",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_29",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_47"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_41",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_23",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_5",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_41"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_44",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_26",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_6",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_44"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_38",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_22",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_5",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_38"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_37",
 | 
			
		||||
    "front": "computercraft:block/monitor_advanced_21",
 | 
			
		||||
    "side": "computercraft:block/monitor_advanced_6",
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0",
 | 
			
		||||
    "back": "computercraft:block/monitor_advanced_37"
 | 
			
		||||
    "top": "computercraft:block/monitor_advanced_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_32",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_16",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_0",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_32"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_36",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_20",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_0",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_36"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:block/orientable",
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_4",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_32",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_15",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_33",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_19",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_33"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_45",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_31",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_45"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_34",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_18",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_34"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_46",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_30",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_46"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_40",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_24",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_5",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_40"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_43",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_27",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_6",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_43"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_39",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_25",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_5",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_39"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_42",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_28",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_6",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_42"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_35",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_17",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_4",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_3",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_35"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "computercraft:block/monitor_base",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_47",
 | 
			
		||||
    "front": "computercraft:block/monitor_normal_29",
 | 
			
		||||
    "side": "computercraft:block/monitor_normal_7",
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_3",
 | 
			
		||||
    "back": "computercraft:block/monitor_normal_47"
 | 
			
		||||
    "top": "computercraft:block/monitor_normal_3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user