mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-11-03 23:22:59 +00:00 
			
		
		
		
	Compare commits
	
		
			83 Commits
		
	
	
		
			v1.14.3-1.
			...
			v1.14.4-1.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					92567b4d7e | ||
| 
						 | 
					0ae70fed13 | ||
| 
						 | 
					3b7300543a | ||
| 
						 | 
					642351af1a | ||
| 
						 | 
					121802a683 | ||
| 
						 | 
					08cf55e55f | ||
| 
						 | 
					3c8c0d78ef | ||
| 
						 | 
					c4d18aa9ca | ||
| 
						 | 
					2d4a87adc9 | ||
| 
						 | 
					bedac71e3d | ||
| 
						 | 
					ee4e42e730 | ||
| 
						 | 
					0de75f05dd | ||
| 
						 | 
					be6dd21e54 | ||
| 
						 | 
					927ddb0bde | ||
| 
						 | 
					a8fadabaf1 | ||
| 
						 | 
					44d0f78c1b | ||
| 
						 | 
					38f9a015ca | ||
| 
						 | 
					c311cdc6f5 | ||
| 
						 | 
					a93e0f3284 | ||
| 
						 | 
					14b3065ba4 | ||
| 
						 | 
					3ea2d6a0a8 | ||
| 
						 | 
					c802290437 | ||
| 
						 | 
					f7781defe5 | ||
| 
						 | 
					418420523a | ||
| 
						 | 
					d342a1f368 | ||
| 
						 | 
					81f85361d5 | ||
| 
						 | 
					f1621b30ec | ||
| 
						 | 
					d4f6a594b6 | ||
| 
						 | 
					ff5ba5c131 | ||
| 
						 | 
					4243f30308 | ||
| 
						 | 
					813e91073d | ||
| 
						 | 
					7250f22ff6 | ||
| 
						 | 
					db31a53bba | ||
| 
						 | 
					3023f235a4 | ||
| 
						 | 
					79cd8b4da5 | ||
| 
						 | 
					8e4d311cd9 | ||
| 
						 | 
					9bd8c86a94 | ||
| 
						 | 
					cbc0c1d0b6 | ||
| 
						 | 
					49c37857d4 | ||
| 
						 | 
					b1139a4bf6 | ||
| 
						 | 
					7e8559278e | ||
| 
						 | 
					1e7f1c98fc | ||
| 
						 | 
					a802f25dd6 | ||
| 
						 | 
					f1d6d21d6d | ||
| 
						 | 
					a80302c513 | ||
| 
						 | 
					1c46949da7 | ||
| 
						 | 
					07a56454a0 | ||
| 
						 | 
					a0e72d02c8 | ||
| 
						 | 
					455a59ca85 | ||
| 
						 | 
					46d78af068 | ||
| 
						 | 
					08d22fd3df | ||
| 
						 | 
					e6c691a8f8 | ||
| 
						 | 
					4b0e5c445c | ||
| 
						 | 
					eb5cff1045 | ||
| 
						 | 
					35c7792aa2 | ||
| 
						 | 
					521688d630 | ||
| 
						 | 
					75e2845c01 | ||
| 
						 | 
					2f96283286 | ||
| 
						 | 
					cbe6e9b5f5 | ||
| 
						 | 
					2ab79cf474 | ||
| 
						 | 
					6ce34aba79 | ||
| 
						 | 
					5eeb320b60 | ||
| 
						 | 
					93310850d2 | ||
| 
						 | 
					a2880b12ca | ||
| 
						 | 
					cef2657048 | ||
| 
						 | 
					ccd85eb055 | ||
| 
						 | 
					303b57779a | ||
| 
						 | 
					6279816ecc | ||
| 
						 | 
					4ae77261fa | ||
| 
						 | 
					4b7d843b78 | ||
| 
						 | 
					1c28df65c3 | ||
| 
						 | 
					85b740f484 | ||
| 
						 | 
					f9929cb27d | ||
| 
						 | 
					bafab1ac07 | ||
| 
						 | 
					e05c262468 | ||
| 
						 | 
					acfb72246c | ||
| 
						 | 
					9d51c4c340 | ||
| 
						 | 
					18068effec | ||
| 
						 | 
					7a3f7d3bba | ||
| 
						 | 
					95aa48c456 | ||
| 
						 | 
					904a168d5c | ||
| 
						 | 
					724441eddc | ||
| 
						 | 
					f68ab3edd1 | 
							
								
								
									
										18
									
								
								.github/workflows/main-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.github/workflows/main-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
name: Build
 | 
			
		||||
 | 
			
		||||
on: [push, pull_request]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@v1
 | 
			
		||||
 | 
			
		||||
    - name: Set up JDK 1.8
 | 
			
		||||
      uses: actions/setup-java@v1
 | 
			
		||||
      with:
 | 
			
		||||
        java-version: 1.8
 | 
			
		||||
 | 
			
		||||
    - name: Build with Gradle
 | 
			
		||||
      run: ./gradlew build --no-daemon
 | 
			
		||||
@@ -17,7 +17,8 @@ ignore = {
 | 
			
		||||
-- are largely unsupported.
 | 
			
		||||
include_files = {
 | 
			
		||||
    'src/main/resources/assets/computercraft/lua/rom',
 | 
			
		||||
    'src/main/resources/assets/computercraft/lua/bios.lua'
 | 
			
		||||
    'src/main/resources/assets/computercraft/lua/bios.lua',
 | 
			
		||||
    'src/test/resources/test-rom',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
files['src/main/resources/assets/computercraft/lua/bios.lua'] = {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								.travis.yml
									
									
									
									
									
								
							@@ -1,14 +0,0 @@
 | 
			
		||||
language: java
 | 
			
		||||
 | 
			
		||||
script: ./gradlew build --no-daemon
 | 
			
		||||
 | 
			
		||||
before_cache:
 | 
			
		||||
  - rm -f  $HOME/.gradle/caches/modules-2/modules-2.lock
 | 
			
		||||
  - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
 | 
			
		||||
cache:
 | 
			
		||||
  directories:
 | 
			
		||||
    - $HOME/.gradle/caches/
 | 
			
		||||
    - $HOME/.gradle/wrapper/s
 | 
			
		||||
 | 
			
		||||
jdk:
 | 
			
		||||
    - oraclejdk8
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
# 
 | 
			
		||||
[](https://travis-ci.org/SquidDev-CC/CC-Tweaked "Current build status") [](https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked on CurseForge")
 | 
			
		||||
[](https://github.com/SquidDev-CC/CC-Tweaked/actions "Current build status") [](https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked on CurseForge")
 | 
			
		||||
 | 
			
		||||
CC: Tweaked is a fork of [ComputerCraft](https://github.com/dan200/ComputerCraft), adding programmable computers,
 | 
			
		||||
turtles and more to Minecraft.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										84
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								build.gradle
									
									
									
									
									
								
							@@ -4,12 +4,12 @@ buildscript {
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        maven {
 | 
			
		||||
            name = "forge"
 | 
			
		||||
            url = "http://files.minecraftforge.net/maven"
 | 
			
		||||
            url = "https://files.minecraftforge.net/maven"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    dependencies {
 | 
			
		||||
        classpath 'com.google.code.gson:gson:2.8.1'
 | 
			
		||||
        classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.128'
 | 
			
		||||
        classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.154'
 | 
			
		||||
        classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
 | 
			
		||||
        classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
 | 
			
		||||
    }
 | 
			
		||||
@@ -67,7 +67,7 @@ minecraft {
 | 
			
		||||
repositories {
 | 
			
		||||
    maven {
 | 
			
		||||
        name "JEI"
 | 
			
		||||
        url  "http://dvs1.progwml6.com/files/maven"
 | 
			
		||||
        url "https://dvs1.progwml6.com/files/maven"
 | 
			
		||||
    }
 | 
			
		||||
    maven {
 | 
			
		||||
        name "SquidDev"
 | 
			
		||||
@@ -79,7 +79,7 @@ repositories {
 | 
			
		||||
    }
 | 
			
		||||
    maven {
 | 
			
		||||
        name "Amadornes"
 | 
			
		||||
        url "http://maven.amadornes.com/"
 | 
			
		||||
        url "https://maven.amadornes.com/"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -90,32 +90,25 @@ configurations {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    checkstyle "com.puppycrawl.tools:checkstyle:8.21"
 | 
			
		||||
    checkstyle "com.puppycrawl.tools:checkstyle:8.25"
 | 
			
		||||
 | 
			
		||||
    minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
 | 
			
		||||
 | 
			
		||||
    compileOnly fg.deobf("mezz.jei:jei-1.13.2:5.0.0.20:api")
 | 
			
		||||
    compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.25:api")
 | 
			
		||||
    // deobfProvided "pl.asie:Charset-Lib:0.5.4.6"
 | 
			
		||||
    // deobfProvided "MCMultiPart2:MCMultiPart:2.5.3"
 | 
			
		||||
 | 
			
		||||
    // runtimeOnly fg.deobf("mezz.jei:jei-1.13.2:5.0.0.20")
 | 
			
		||||
    runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.25")
 | 
			
		||||
 | 
			
		||||
    shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT'
 | 
			
		||||
 | 
			
		||||
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.0'
 | 
			
		||||
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.0'
 | 
			
		||||
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
 | 
			
		||||
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
 | 
			
		||||
 | 
			
		||||
    deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sourceSets {
 | 
			
		||||
    main {
 | 
			
		||||
        java {
 | 
			
		||||
            exclude 'dan200/computercraft/shared/integration/mcmp'
 | 
			
		||||
            exclude 'dan200/computercraft/shared/integration/charset'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// Compile tasks
 | 
			
		||||
 | 
			
		||||
javadoc {
 | 
			
		||||
    include "dan200/computercraft/api/**/*.java"
 | 
			
		||||
@@ -127,7 +120,7 @@ jar {
 | 
			
		||||
    manifest {
 | 
			
		||||
        attributes(["Specification-Title": "computercraft",
 | 
			
		||||
                    "Specification-Vendor": "SquidDev",
 | 
			
		||||
                    "Specification-Version": "26.0",
 | 
			
		||||
                    "Specification-Version": "1",
 | 
			
		||||
                    "Implementation-Title": "CC: Tweaked",
 | 
			
		||||
                    "Implementation-Version": "${mod_version}",
 | 
			
		||||
                    "Implementation-Vendor" :"SquidDev",
 | 
			
		||||
@@ -141,6 +134,14 @@ jar {
 | 
			
		||||
    from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[compileJava, compileTestJava].forEach {
 | 
			
		||||
    it.configure {
 | 
			
		||||
        options.compilerArgs << "-Xlint" << "-Xlint:-processing" << "-Werror"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
import java.nio.file.*
 | 
			
		||||
import java.util.zip.*
 | 
			
		||||
@@ -276,7 +277,14 @@ task compressJson(dependsOn: jar) {
 | 
			
		||||
 | 
			
		||||
assemble.dependsOn compressJson
 | 
			
		||||
 | 
			
		||||
/* Check tasks */
 | 
			
		||||
// Check tasks
 | 
			
		||||
 | 
			
		||||
test {
 | 
			
		||||
    useJUnitPlatform()
 | 
			
		||||
    testLogging {
 | 
			
		||||
        events "skipped", "failed"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
license {
 | 
			
		||||
    mapping("java", "SLASHSTAR_STYLE")
 | 
			
		||||
@@ -300,6 +308,13 @@ license {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gradle.projectsEvaluated {
 | 
			
		||||
    tasks.withType(LicenseFormat) {
 | 
			
		||||
        outputs.upToDateWhen { false }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
task licenseAPI(type: LicenseCheck);
 | 
			
		||||
task licenseFormatAPI(type: LicenseFormat);
 | 
			
		||||
[licenseAPI, licenseFormatAPI].forEach {
 | 
			
		||||
@@ -310,7 +325,7 @@ task licenseFormatAPI(type: LicenseFormat);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Upload tasks */
 | 
			
		||||
// Upload tasks
 | 
			
		||||
 | 
			
		||||
task checkRelease {
 | 
			
		||||
    group "upload"
 | 
			
		||||
@@ -350,12 +365,13 @@ task checkRelease {
 | 
			
		||||
        if (!ok) throw new IllegalStateException("Could not check release")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
check.dependsOn checkRelease
 | 
			
		||||
 | 
			
		||||
curseforge {
 | 
			
		||||
    apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
 | 
			
		||||
    project {
 | 
			
		||||
        id = '282001'
 | 
			
		||||
        releaseType = 'beta'
 | 
			
		||||
        releaseType = 'release'
 | 
			
		||||
        changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
 | 
			
		||||
 | 
			
		||||
        relations {
 | 
			
		||||
@@ -421,7 +437,9 @@ githubRelease {
 | 
			
		||||
    token project.hasProperty('githubApiKey') ? project.githubApiKey : ''
 | 
			
		||||
    owner 'SquidDev-CC'
 | 
			
		||||
    repo 'CC-Tweaked'
 | 
			
		||||
    targetCommitish { Grgit.open(dir: '.').branch.current().name }
 | 
			
		||||
    try {
 | 
			
		||||
        targetCommitish = Grgit.open(dir: '.').branch.current().name
 | 
			
		||||
    } catch(Exception ignored) { }
 | 
			
		||||
 | 
			
		||||
    tagName "v${mc_version}-${mod_version}"
 | 
			
		||||
    releaseName "[${mc_version}] ${mod_version}"
 | 
			
		||||
@@ -431,7 +449,7 @@ githubRelease {
 | 
			
		||||
            .takeWhile { it != 'Type "help changelog" to see the full version history.' }
 | 
			
		||||
            .join("\n").trim()
 | 
			
		||||
    }
 | 
			
		||||
    prerelease true
 | 
			
		||||
    prerelease false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
 | 
			
		||||
@@ -441,23 +459,3 @@ task uploadAll(dependsOn: uploadTasks) {
 | 
			
		||||
    group "upload"
 | 
			
		||||
    description "Uploads to all repositories (Maven, Curse, GitHub release)"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test {
 | 
			
		||||
    useJUnitPlatform()
 | 
			
		||||
    testLogging {
 | 
			
		||||
        events "passed", "skipped", "failed"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gradle.projectsEvaluated {
 | 
			
		||||
    reobfJar.dependsOn proguardMove
 | 
			
		||||
 | 
			
		||||
    tasks.withType(JavaCompile) {
 | 
			
		||||
        options.compilerArgs << "-Xlint" << "-Xlint:-processing" // Causes Forge build to fail << "-Werror"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tasks.withType(LicenseFormat) {
 | 
			
		||||
        outputs.upToDateWhen { false }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,7 @@
 | 
			
		||||
        <!-- Annotations -->
 | 
			
		||||
        <module name="AnnotationLocation" />
 | 
			
		||||
        <module name="AnnotationUseStyle" />
 | 
			
		||||
        <module name="MissingDeprecated">
 | 
			
		||||
            <property name="skipNoJavadoc" value="true" />
 | 
			
		||||
        </module>
 | 
			
		||||
        <module name="MissingDeprecated" />
 | 
			
		||||
        <module name="MissingOverride" />
 | 
			
		||||
 | 
			
		||||
        <!-- Blocks -->
 | 
			
		||||
@@ -57,6 +55,9 @@
 | 
			
		||||
        <module name="SimplifyBooleanReturn" />
 | 
			
		||||
        <module name="StringLiteralEquality" />
 | 
			
		||||
        <module name="UnnecessaryParentheses" />
 | 
			
		||||
        <module name="UnnecessarySemicolonAfterTypeMemberDeclaration" />
 | 
			
		||||
        <module name="UnnecessarySemicolonInTryWithResources" />
 | 
			
		||||
        <module name="UnnecessarySemicolonInEnumeration" />
 | 
			
		||||
 | 
			
		||||
        <!-- Imports -->
 | 
			
		||||
        <module name="CustomImportOrder" />
 | 
			
		||||
@@ -65,10 +66,16 @@
 | 
			
		||||
        <module name="UnusedImports" />
 | 
			
		||||
 | 
			
		||||
        <!-- Javadoc -->
 | 
			
		||||
        <!-- TODO: Missing* checks for the dan200.computercraft.api package? -->
 | 
			
		||||
        <module name="AtclauseOrder" />
 | 
			
		||||
        <!-- TODO: Cleanup our documentation before enabling JavadocMethod, JavadocStyle, JavadocType and SummaryJavadoc. -->
 | 
			
		||||
        <module name="InvalidJavadocPosition" />
 | 
			
		||||
        <module name="JavadocBlockTagLocation" />
 | 
			
		||||
        <module name="JavadocMethod"/>
 | 
			
		||||
        <module name="JavadocType"/>
 | 
			
		||||
        <module name="JavadocStyle" />
 | 
			
		||||
        <module name="NonEmptyAtclauseDescription" />
 | 
			
		||||
        <module name="SingleLineJavadoc" />
 | 
			
		||||
        <module name="SummaryJavadocCheck"/>
 | 
			
		||||
 | 
			
		||||
        <!-- Misc -->
 | 
			
		||||
        <module name="ArrayTypeStyle" />
 | 
			
		||||
@@ -155,5 +162,8 @@
 | 
			
		||||
 | 
			
		||||
    <module name="FileTabCharacter" />
 | 
			
		||||
    <module name="NewlineAtEndOfFile" />
 | 
			
		||||
    <module name="RegexpSingleline">
 | 
			
		||||
        <property name="format" value="\s+$"/>
 | 
			
		||||
        <property name="message" value="Trailing whitespace"/>
 | 
			
		||||
    </module>
 | 
			
		||||
</module>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,4 +6,7 @@
 | 
			
		||||
    <!-- All the config options and method fields. -->
 | 
			
		||||
    <suppress checks="StaticVariableName" files=".*[\\/]ComputerCraft.java" />
 | 
			
		||||
    <suppress checks="StaticVariableName" files=".*[\\/]ComputerCraftAPI.java" />
 | 
			
		||||
 | 
			
		||||
    <!-- Do not check for missing package Javadoc. -->
 | 
			
		||||
    <suppress checks="JavadocStyle" files=".*[\\/]package-info.java" />
 | 
			
		||||
</suppressions>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
# Mod properties
 | 
			
		||||
mod_version=1.83.1
 | 
			
		||||
mod_version=1.85.2
 | 
			
		||||
 | 
			
		||||
# Minecraft properties
 | 
			
		||||
mc_version=1.14.3
 | 
			
		||||
forge_version=27.0.3
 | 
			
		||||
mappings_version=20190626-1.14.3
 | 
			
		||||
# Minecraft properties (update mods.toml when changing)
 | 
			
		||||
mc_version=1.14.4
 | 
			
		||||
forge_version=28.1.71
 | 
			
		||||
mappings_version=20191123-1.14.3
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,9 @@
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.filesystem.IMount;
 | 
			
		||||
import dan200.computercraft.api.turtle.event.TurtleAction;
 | 
			
		||||
import dan200.computercraft.core.apis.AddressPredicate;
 | 
			
		||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
 | 
			
		||||
import dan200.computercraft.core.filesystem.ResourceMount;
 | 
			
		||||
import dan200.computercraft.shared.Config;
 | 
			
		||||
import dan200.computercraft.shared.computer.blocks.BlockComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
 | 
			
		||||
@@ -194,13 +192,6 @@ public final class ComputerCraft
 | 
			
		||||
        return "${version}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static IMount createResourceMount( String domain, String subPath )
 | 
			
		||||
    {
 | 
			
		||||
        IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
 | 
			
		||||
        ResourceMount mount = new ResourceMount( domain, subPath, manager );
 | 
			
		||||
        return mount.exists( "" ) ? mount : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static InputStream getResourceFile( String domain, String subPath )
 | 
			
		||||
    {
 | 
			
		||||
        IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.MapMaker;
 | 
			
		||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
 | 
			
		||||
import dan200.computercraft.api.filesystem.IMount;
 | 
			
		||||
import dan200.computercraft.api.filesystem.IWritableMount;
 | 
			
		||||
@@ -20,20 +21,26 @@ import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
 | 
			
		||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
 | 
			
		||||
import dan200.computercraft.core.apis.ApiFactories;
 | 
			
		||||
import dan200.computercraft.core.filesystem.FileMount;
 | 
			
		||||
import dan200.computercraft.core.filesystem.ResourceMount;
 | 
			
		||||
import dan200.computercraft.shared.*;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
 | 
			
		||||
import dan200.computercraft.shared.util.IDAssigner;
 | 
			
		||||
import dan200.computercraft.shared.wired.CapabilityWiredElement;
 | 
			
		||||
import dan200.computercraft.shared.wired.WiredNode;
 | 
			
		||||
import net.minecraft.resources.IReloadableResourceManager;
 | 
			
		||||
import net.minecraft.tileentity.TileEntity;
 | 
			
		||||
import net.minecraft.util.Direction;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.IBlockReader;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraftforge.common.util.LazyOptional;
 | 
			
		||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.lang.ref.WeakReference;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
 | 
			
		||||
{
 | 
			
		||||
@@ -43,6 +50,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private WeakReference<IReloadableResourceManager> currentResources;
 | 
			
		||||
    private final Map<ResourceLocation, ResourceMount> mountCache = new MapMaker().weakValues().concurrencyLevel( 1 ).makeMap();
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getInstalledVersion()
 | 
			
		||||
@@ -72,7 +82,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
 | 
			
		||||
    @Override
 | 
			
		||||
    public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
 | 
			
		||||
    {
 | 
			
		||||
        return ComputerCraft.createResourceMount( domain, subPath );
 | 
			
		||||
        IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
 | 
			
		||||
        ResourceMount mount = ResourceMount.get( domain, subPath, manager );
 | 
			
		||||
        return mount.exists( "" ) ? mount : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,9 @@ import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The static entry point to the ComputerCraft API.
 | 
			
		||||
 * Members in this class must be called after mod_ComputerCraft has been initialised,
 | 
			
		||||
 * but may be called before it is fully loaded.
 | 
			
		||||
 *
 | 
			
		||||
 * Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is
 | 
			
		||||
 * fully loaded.
 | 
			
		||||
 */
 | 
			
		||||
public final class ComputerCraftAPI
 | 
			
		||||
{
 | 
			
		||||
@@ -189,7 +190,7 @@ public final class ComputerCraftAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers a media provider to provide {@link IMedia} implementations for Items
 | 
			
		||||
     * Registers a media provider to provide {@link IMedia} implementations for Items.
 | 
			
		||||
     *
 | 
			
		||||
     * @param provider The media provider to register.
 | 
			
		||||
     * @see IMediaProvider
 | 
			
		||||
@@ -220,7 +221,7 @@ public final class ComputerCraftAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a new wired node for a given wired element
 | 
			
		||||
     * Construct a new wired node for a given wired element.
 | 
			
		||||
     *
 | 
			
		||||
     * @param element The element to construct it for
 | 
			
		||||
     * @return The element's node
 | 
			
		||||
@@ -233,7 +234,7 @@ public final class ComputerCraftAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the wired network element for a block in world
 | 
			
		||||
     * Get the wired network element for a block in world.
 | 
			
		||||
     *
 | 
			
		||||
     * @param world The world the block exists in
 | 
			
		||||
     * @param pos   The position the block exists in
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a read only part of a virtual filesystem that can be mounted onto a computer using
 | 
			
		||||
 * {@link IComputerAccess#mount(String, IMount)}
 | 
			
		||||
 * {@link IComputerAccess#mount(String, IMount)}.
 | 
			
		||||
 *
 | 
			
		||||
 * Ready made implementations of this interface can be created using
 | 
			
		||||
 * {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or
 | 
			
		||||
@@ -60,7 +60,7 @@ public interface IMount
 | 
			
		||||
    void list( @Nonnull String path, @Nonnull List<String> contents ) throws IOException;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the size of a file with a given path, in bytes
 | 
			
		||||
     * Returns the size of a file with a given path, in bytes.
 | 
			
		||||
     *
 | 
			
		||||
     * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
 | 
			
		||||
     * @return The size of the file, in bytes.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										335
									
								
								src/main/java/dan200/computercraft/api/lua/ArgumentHelper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								src/main/java/dan200/computercraft/api/lua/ArgumentHelper.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,335 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * For help using the API, and posting your mods, visit the forums at computercraft.info.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.api.lua;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IComputerAccess;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides methods for extracting values and validating Lua arguments, such as those provided to
 | 
			
		||||
 * {@link ILuaObject#callMethod(ILuaContext, int, Object[])} or
 | 
			
		||||
 * {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}.
 | 
			
		||||
 *
 | 
			
		||||
 * This provides two sets of functions: the {@code get*} methods, which require an argument to be valid, and
 | 
			
		||||
 * {@code opt*}, which accept a default value and return that if the argument was not present or was {@code null}.
 | 
			
		||||
 * If the argument is of the wrong type, a suitable error message will be thrown, with a similar format to Lua's own
 | 
			
		||||
 * error messages.
 | 
			
		||||
 *
 | 
			
		||||
 * <h2>Example usage:</h2>
 | 
			
		||||
 * <pre>
 | 
			
		||||
 * {@code
 | 
			
		||||
 * int slot = getInt( args, 0 );
 | 
			
		||||
 * int amount = optInt( args, 1, 64 );
 | 
			
		||||
 * }
 | 
			
		||||
 * </pre>
 | 
			
		||||
 */
 | 
			
		||||
public final class ArgumentHelper
 | 
			
		||||
{
 | 
			
		||||
    private ArgumentHelper()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get a string representation of the given value's type.
 | 
			
		||||
     *
 | 
			
		||||
     * @param value The value whose type we are trying to compute.
 | 
			
		||||
     * @return A string representation of the given value's type, in a similar format to that provided by Lua's
 | 
			
		||||
     * {@code type} function.
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static String getType( @Nullable Object value )
 | 
			
		||||
    {
 | 
			
		||||
        if( value == null ) return "nil";
 | 
			
		||||
        if( value instanceof String ) return "string";
 | 
			
		||||
        if( value instanceof Boolean ) return "boolean";
 | 
			
		||||
        if( value instanceof Number ) return "number";
 | 
			
		||||
        if( value instanceof Map ) return "table";
 | 
			
		||||
        return "userdata";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a "bad argument" exception, from an expected type and the actual value provided.
 | 
			
		||||
     *
 | 
			
		||||
     * @param index    The argument number, starting from 0.
 | 
			
		||||
     * @param expected The expected type for this argument.
 | 
			
		||||
     * @param actual   The actual value provided for this argument.
 | 
			
		||||
     * @return The constructed exception, which should be thrown immediately.
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static LuaException badArgumentOf( int index, @Nonnull String expected, @Nullable Object actual )
 | 
			
		||||
    {
 | 
			
		||||
        return badArgument( index, expected, getType( actual ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a "bad argument" exception, from an expected and actual type.
 | 
			
		||||
     *
 | 
			
		||||
     * @param index    The argument number, starting from 0.
 | 
			
		||||
     * @param expected The expected type for this argument.
 | 
			
		||||
     * @param actual   The provided type for this argument.
 | 
			
		||||
     * @return The constructed exception, which should be thrown immediately.
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual )
 | 
			
		||||
    {
 | 
			
		||||
        return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a double.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not a number.
 | 
			
		||||
     * @see #getFiniteDouble(Object[], int) if you require this to be finite (i.e. not infinite or NaN).
 | 
			
		||||
     */
 | 
			
		||||
    public static double getDouble( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "number", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
 | 
			
		||||
        return ((Number) value).doubleValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as an integer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not an integer.
 | 
			
		||||
     */
 | 
			
		||||
    public static int getInt( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return (int) getLong( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a long.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not a long.
 | 
			
		||||
     */
 | 
			
		||||
    public static long getLong( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "number", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
 | 
			
		||||
        return checkFinite( index, (Number) value ).longValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a finite number (not infinite or NaN).
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not finite.
 | 
			
		||||
     */
 | 
			
		||||
    public static double getFiniteDouble( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return checkFinite( index, getDouble( args, index ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a boolean.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not a boolean.
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean getBoolean( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "boolean", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( !(value instanceof Boolean) ) throw badArgumentOf( index, "boolean", value );
 | 
			
		||||
        return (Boolean) value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a string.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not a string.
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static String getString( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "string", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( !(value instanceof String) ) throw badArgumentOf( index, "string", value );
 | 
			
		||||
        return (String) value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a table.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @return The argument's value.
 | 
			
		||||
     * @throws LuaException If the value is not a table.
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static Map<?, ?> getTable( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "table", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( !(value instanceof Map) ) throw badArgumentOf( index, "table", value );
 | 
			
		||||
        return (Map<?, ?>) value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a double.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not a number.
 | 
			
		||||
     */
 | 
			
		||||
    public static double optDouble( @Nonnull Object[] args, int index, double def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null ) return def;
 | 
			
		||||
        if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
 | 
			
		||||
        return ((Number) value).doubleValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as an int.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not a number.
 | 
			
		||||
     */
 | 
			
		||||
    public static int optInt( @Nonnull Object[] args, int index, int def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return (int) optLong( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a long.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not a number.
 | 
			
		||||
     */
 | 
			
		||||
    public static long optLong( @Nonnull Object[] args, int index, long def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null ) return def;
 | 
			
		||||
        if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
 | 
			
		||||
        return checkFinite( index, (Number) value ).longValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a finite number (not infinite or NaN).
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not finite.
 | 
			
		||||
     */
 | 
			
		||||
    public static double optFiniteDouble( @Nonnull Object[] args, int index, double def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return checkFinite( index, optDouble( args, index, def ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a boolean.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not a boolean.
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean optBoolean( @Nonnull Object[] args, int index, boolean def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null ) return def;
 | 
			
		||||
        if( !(value instanceof Boolean) ) throw badArgumentOf( index, "boolean", value );
 | 
			
		||||
        return (Boolean) value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a string.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not a string.
 | 
			
		||||
     */
 | 
			
		||||
    public static String optString( @Nonnull Object[] args, int index, String def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null ) return def;
 | 
			
		||||
        if( !(value instanceof String) ) throw badArgumentOf( index, "string", value );
 | 
			
		||||
        return (String) value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an argument as a table.
 | 
			
		||||
     *
 | 
			
		||||
     * @param args  The arguments to extract from.
 | 
			
		||||
     * @param index The index into the argument array to read from.
 | 
			
		||||
     * @param def   The default value, if this argument is not given.
 | 
			
		||||
     * @return The argument's value, or {@code def} if none was provided.
 | 
			
		||||
     * @throws LuaException If the value is not a table.
 | 
			
		||||
     */
 | 
			
		||||
    public static Map<?, ?> optTable( @Nonnull Object[] args, int index, Map<Object, Object> def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null ) return def;
 | 
			
		||||
        if( !(value instanceof Map) ) throw badArgumentOf( index, "table", value );
 | 
			
		||||
        return (Map<?, ?>) value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static Number checkFinite( int index, Number value ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        checkFinite( index, value.doubleValue() );
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static double checkFinite( int index, double value ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( !Double.isFinite( value ) ) throw badArgument( index, "number", getNumericType( value ) );
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a more detailed representation of this number's type. If this is finite, it will just return "number",
 | 
			
		||||
     * otherwise it returns whether it is infinite or NaN.
 | 
			
		||||
     *
 | 
			
		||||
     * @param value The value to extract the type for.
 | 
			
		||||
     * @return This value's numeric type.
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static String getNumericType( double value )
 | 
			
		||||
    {
 | 
			
		||||
        if( Double.isNaN( value ) ) return "nan";
 | 
			
		||||
        if( value == Double.POSITIVE_INFINITY ) return "inf";
 | 
			
		||||
        if( value == Double.NEGATIVE_INFINITY ) return "-inf";
 | 
			
		||||
        return "number";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,7 +26,7 @@ public interface IComputerSystem extends IComputerAccess
 | 
			
		||||
    IFileSystem getFileSystem();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the label for this computer
 | 
			
		||||
     * Get the label for this computer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return This computer's label, or {@code null} if it is not set.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.api.peripheral;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.lua.ArgumentHelper;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaContext;
 | 
			
		||||
import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
 | 
			
		||||
@@ -58,9 +59,11 @@ public interface IPeripheral
 | 
			
		||||
     *                  Lua values of type "table" will be represented by Object type Map.<br>
 | 
			
		||||
     *                  Lua values of any other type will be represented by a null object.<br>
 | 
			
		||||
     *                  This array will be empty if no arguments are passed.
 | 
			
		||||
     *
 | 
			
		||||
     *                  It is recommended you use {@link ArgumentHelper} in order to validate and process arguments.
 | 
			
		||||
     * @return An array of objects, representing values you wish to return to the lua program. Integers, Doubles, Floats,
 | 
			
		||||
     * Strings, Booleans, Maps and ILuaObject and null be converted to their corresponding lua type. All other types
 | 
			
		||||
     * will be converted to nil.
 | 
			
		||||
     * Strings, Booleans, Maps, ILuaObject and null be converted to their corresponding lua type. All other types will
 | 
			
		||||
     * be converted to nil.
 | 
			
		||||
     *
 | 
			
		||||
     * You may return null to indicate no values should be returned.
 | 
			
		||||
     * @throws LuaException         If you throw any exception from this function, a lua error will be raised with the
 | 
			
		||||
@@ -70,6 +73,7 @@ public interface IPeripheral
 | 
			
		||||
     *                              InterruptedException will be thrown. This exception must not be caught or
 | 
			
		||||
     *                              intercepted, or the computer will leak memory and end up in a broken state.
 | 
			
		||||
     * @see #getMethodNames
 | 
			
		||||
     * @see ArgumentHelper
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ import javax.annotation.Nullable;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Wrapper class for pocket computers
 | 
			
		||||
 * Wrapper class for pocket computers.
 | 
			
		||||
 */
 | 
			
		||||
public interface IPocketAccess
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -144,7 +144,9 @@ public interface ITurtleAccess
 | 
			
		||||
    GameProfile getOwningPlayer();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the inventory of this turtle
 | 
			
		||||
     * Get the inventory of this turtle.
 | 
			
		||||
     *
 | 
			
		||||
     * Note: this inventory should only be accessed and modified on the server thread.
 | 
			
		||||
     *
 | 
			
		||||
     * @return This turtle's inventory
 | 
			
		||||
     * @see #getItemHandler()
 | 
			
		||||
@@ -155,6 +157,8 @@ public interface ITurtleAccess
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
 | 
			
		||||
     *
 | 
			
		||||
     * Note: this inventory should only be accessed and modified on the server thread.
 | 
			
		||||
     *
 | 
			
		||||
     * @return This turtle's inventory
 | 
			
		||||
     * @see #getInventory()
 | 
			
		||||
     * @see IItemHandlerModifiable
 | 
			
		||||
 
 | 
			
		||||
@@ -98,8 +98,8 @@ public interface ITurtleUpgrade
 | 
			
		||||
     * Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
 | 
			
		||||
     * by the turtle, and the tool is required to do some work.
 | 
			
		||||
     *
 | 
			
		||||
     * Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
 | 
			
		||||
     * {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
 | 
			
		||||
     * Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig} for
 | 
			
		||||
     * digging, {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
 | 
			
		||||
     *
 | 
			
		||||
     * @param turtle    Access to the turtle that the tool resides on.
 | 
			
		||||
     * @param side      Which side of the turtle (left or right) the tool resides on.
 | 
			
		||||
 
 | 
			
		||||
@@ -12,12 +12,12 @@ package dan200.computercraft.api.turtle;
 | 
			
		||||
public enum TurtleSide
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle)
 | 
			
		||||
     * The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle).
 | 
			
		||||
     */
 | 
			
		||||
    Left,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The turtle's right side (where the modem usually is on a Wireless Mining Turtle)
 | 
			
		||||
     * The turtle's right side (where the modem usually is on a Wireless Mining Turtle).
 | 
			
		||||
     */
 | 
			
		||||
    Right,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,12 +18,12 @@ import net.minecraft.util.Direction;
 | 
			
		||||
public enum TurtleVerb
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}
 | 
			
		||||
     * The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}.
 | 
			
		||||
     */
 | 
			
		||||
    Dig,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}
 | 
			
		||||
     * The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}.
 | 
			
		||||
     */
 | 
			
		||||
    Attack,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ public enum TurtleAction
 | 
			
		||||
    EQUIP,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Inspect a block in world
 | 
			
		||||
     * Inspect a block in world.
 | 
			
		||||
     *
 | 
			
		||||
     * @see TurtleBlockEvent.Inspect
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -112,7 +112,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Get the upgrade doing the digging
 | 
			
		||||
         * Get the upgrade doing the digging.
 | 
			
		||||
         *
 | 
			
		||||
         * @return The upgrade doing the digging.
 | 
			
		||||
         */
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the inventory being interacted with
 | 
			
		||||
     * Get the inventory being interacted with.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ import dan200.computercraft.shared.common.IColouredItem;
 | 
			
		||||
import dan200.computercraft.shared.media.items.ItemDisk;
 | 
			
		||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
 | 
			
		||||
import dan200.computercraft.shared.util.Colour;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.model.IUnbakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
 | 
			
		||||
@@ -58,8 +59,8 @@ public final class ClientRegistry
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private static final String[] EXTRA_TEXTURES = new String[] {
 | 
			
		||||
        // TODO: Gather these automatically from the model. I'm unable to get this working with Forge's current
 | 
			
		||||
        //  model loading code.
 | 
			
		||||
        // TODO: Gather these automatically from the model. Sadly the model loader isn't available
 | 
			
		||||
        //  when stitching textures.
 | 
			
		||||
        "block/turtle_colour",
 | 
			
		||||
        "block/turtle_elf_overlay",
 | 
			
		||||
        "block/turtle_crafty_face",
 | 
			
		||||
@@ -77,13 +78,12 @@ public final class ClientRegistry
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
 | 
			
		||||
    {
 | 
			
		||||
        /*
 | 
			
		||||
        IResourceManager manager = Minecraft.getInstance().getResourceManager();
 | 
			
		||||
        if( event.getMap() != Minecraft.getInstance().getTextureMap() ) return;
 | 
			
		||||
 | 
			
		||||
        for( String extra : EXTRA_TEXTURES )
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: event.getMap().registerSprite( manager, new ResourceLocation( ComputerCraft.MOD_ID, extra ) );
 | 
			
		||||
            event.addSprite( new ResourceLocation( ComputerCraft.MOD_ID, extra ) );
 | 
			
		||||
        }
 | 
			
		||||
        */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,9 @@ package dan200.computercraft.client;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import net.minecraftforge.api.distmarker.Dist;
 | 
			
		||||
import net.minecraftforge.event.TickEvent;
 | 
			
		||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
 | 
			
		||||
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
 | 
			
		||||
public final class FrameInfo
 | 
			
		||||
 
 | 
			
		||||
@@ -176,11 +176,4 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
 | 
			
		||||
        return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
 | 
			
		||||
            || super.mouseDragged( x, y, button, deltaX, deltaY );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean mouseReleased( double x, double y, int button )
 | 
			
		||||
    {
 | 
			
		||||
        return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
 | 
			
		||||
            || super.mouseReleased( x, y, button );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -129,4 +129,11 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
 | 
			
		||||
        super.render( mouseX, mouseY, partialTicks );
 | 
			
		||||
        renderHoveredToolTip( mouseX, mouseY );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
 | 
			
		||||
    {
 | 
			
		||||
        return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
 | 
			
		||||
            || super.mouseDragged( x, y, button, deltaX, deltaY );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -241,11 +241,12 @@ public class WidgetTerminal implements IGuiEventListener
 | 
			
		||||
            charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
 | 
			
		||||
            charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
 | 
			
		||||
 | 
			
		||||
            computer.mouseDrag( button + 1, charX + 1, charY + 1 );
 | 
			
		||||
 | 
			
		||||
            lastMouseX = charX;
 | 
			
		||||
            lastMouseY = charY;
 | 
			
		||||
            lastMouseButton = button;
 | 
			
		||||
            if( button == lastMouseButton && (charX != lastMouseX || charY != lastMouseY) )
 | 
			
		||||
            {
 | 
			
		||||
                computer.mouseDrag( button + 1, charX + 1, charY + 1 );
 | 
			
		||||
                lastMouseX = charX;
 | 
			
		||||
                lastMouseY = charY;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -427,4 +428,10 @@ public class WidgetTerminal implements IGuiEventListener
 | 
			
		||||
        ClientComputer computer = this.computer.get();
 | 
			
		||||
        if( computer != null ) computer.queueEvent( event, args );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isMouseOver( double x, double y )
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -95,4 +95,11 @@ public class WidgetWrapper implements IGuiEventListener
 | 
			
		||||
    {
 | 
			
		||||
        return height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isMouseOver( double x, double y )
 | 
			
		||||
    {
 | 
			
		||||
        double dx = x - this.x, dy = y - this.y;
 | 
			
		||||
        return dx >= 0 && dx < width && dy >= 0 && dy < height;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,6 @@ import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.ActiveRenderInfo;
 | 
			
		||||
import net.minecraft.client.renderer.WorldRenderer;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.BlockRayTraceResult;
 | 
			
		||||
import net.minecraft.util.math.RayTraceResult;
 | 
			
		||||
@@ -39,7 +38,7 @@ public final class CableHighlightRenderer
 | 
			
		||||
     * Draw an outline for a specific part of a cable "Multipart".
 | 
			
		||||
     *
 | 
			
		||||
     * @param event The event to observe
 | 
			
		||||
     * @see WorldRenderer#drawSelectionBox(PlayerEntity, RayTraceResult, int, float)
 | 
			
		||||
     * @see WorldRenderer#drawSelectionBox(ActiveRenderInfo, RayTraceResult, int)
 | 
			
		||||
     */
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void drawHighlight( DrawBlockHighlightEvent event )
 | 
			
		||||
@@ -48,7 +47,7 @@ public final class CableHighlightRenderer
 | 
			
		||||
 | 
			
		||||
        BlockRayTraceResult hit = (BlockRayTraceResult) event.getTarget();
 | 
			
		||||
        BlockPos pos = hit.getPos();
 | 
			
		||||
        World world = event.getInfo().func_216773_g().getEntityWorld();
 | 
			
		||||
        World world = event.getInfo().getRenderViewEntity().getEntityWorld();
 | 
			
		||||
        ActiveRenderInfo info = event.getInfo();
 | 
			
		||||
 | 
			
		||||
        BlockState state = world.getBlockState( pos );
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ import net.minecraft.util.math.MathHelper;
 | 
			
		||||
public abstract class ItemMapLikeRenderer
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * The main rendering method for the item
 | 
			
		||||
     * The main rendering method for the item.
 | 
			
		||||
     *
 | 
			
		||||
     * @param stack The stack to render
 | 
			
		||||
     * @see FirstPersonRenderer#renderMapFirstPerson(ItemStack)
 | 
			
		||||
@@ -87,7 +87,7 @@ public abstract class ItemMapLikeRenderer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Render an item in the middle of the screen
 | 
			
		||||
     * Render an item in the middle of the screen.
 | 
			
		||||
     *
 | 
			
		||||
     * @param pitch         The pitch of the player
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
 | 
			
		||||
import static dan200.computercraft.client.gui.GuiComputer.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Emulates map rendering for pocket computers
 | 
			
		||||
 * Emulates map rendering for pocket computers.
 | 
			
		||||
 */
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
 | 
			
		||||
public final class ItemPocketRenderer extends ItemMapLikeRenderer
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
 | 
			
		||||
import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Emulates map and item-frame rendering for printouts
 | 
			
		||||
 * Emulates map and item-frame rendering for printouts.
 | 
			
		||||
 */
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
 | 
			
		||||
public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
 | 
			
		||||
 
 | 
			
		||||
@@ -42,12 +42,12 @@ public final class MonitorHighlightRenderer
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void drawHighlight( DrawBlockHighlightEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        if( event.getTarget().getType() != RayTraceResult.Type.BLOCK || event.getInfo().func_216773_g().isSneaking() )
 | 
			
		||||
        if( event.getTarget().getType() != RayTraceResult.Type.BLOCK || event.getInfo().getRenderViewEntity().isSneaking() )
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        World world = event.getInfo().func_216773_g().getEntityWorld();
 | 
			
		||||
        World world = event.getInfo().getRenderViewEntity().getEntityWorld();
 | 
			
		||||
        BlockPos pos = ((BlockRayTraceResult) event.getTarget()).getPos();
 | 
			
		||||
 | 
			
		||||
        TileEntity tile = world.getTileEntity( pos );
 | 
			
		||||
 
 | 
			
		||||
@@ -28,32 +28,32 @@ public final class PrintoutRenderer
 | 
			
		||||
    private static final double BG_SIZE = 256.0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Width of a page
 | 
			
		||||
     * Width of a page.
 | 
			
		||||
     */
 | 
			
		||||
    public static final int X_SIZE = 172;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Height of a page
 | 
			
		||||
     * Height of a page.
 | 
			
		||||
     */
 | 
			
		||||
    public static final int Y_SIZE = 209;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Padding between the left and right of a page and the text
 | 
			
		||||
     * Padding between the left and right of a page and the text.
 | 
			
		||||
     */
 | 
			
		||||
    public static final int X_TEXT_MARGIN = 13;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Padding between the top and bottom of a page and the text
 | 
			
		||||
     * Padding between the top and bottom of a page and the text.
 | 
			
		||||
     */
 | 
			
		||||
    public static final int Y_TEXT_MARGIN = 11;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Width of the extra page texture
 | 
			
		||||
     * Width of the extra page texture.
 | 
			
		||||
     */
 | 
			
		||||
    private static final int X_FOLD_SIZE = 12;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Size of the leather cover
 | 
			
		||||
     * Size of the leather cover.
 | 
			
		||||
     */
 | 
			
		||||
    public static final int COVER_SIZE = 12;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,8 @@ public class TileEntityCableRenderer extends TileEntityRenderer<TileCable>
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up the state for rendering block-breaking progress.
 | 
			
		||||
     *
 | 
			
		||||
     * @see WorldRenderer#preRenderDamagedBlocks()
 | 
			
		||||
     */
 | 
			
		||||
    private void preRenderDamagedBlocks()
 | 
			
		||||
@@ -123,6 +125,8 @@ public class TileEntityCableRenderer extends TileEntityRenderer<TileCable>
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tear down the state for rendering block-breaking progress.
 | 
			
		||||
     *
 | 
			
		||||
     * @see WorldRenderer#postRenderDamagedBlocks()
 | 
			
		||||
     */
 | 
			
		||||
    private void postRenderDamagedBlocks()
 | 
			
		||||
 
 | 
			
		||||
@@ -119,6 +119,7 @@ public class TurtleMultiModel implements IBakedModel
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public TextureAtlasSprite getParticleTexture()
 | 
			
		||||
    {
 | 
			
		||||
        return m_baseModel.getParticleTexture();
 | 
			
		||||
 
 | 
			
		||||
@@ -202,6 +202,7 @@ public class TurtleSmartItemModel implements IBakedModel
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public TextureAtlasSprite getParticleTexture()
 | 
			
		||||
    {
 | 
			
		||||
        return familyModel.getParticleTexture();
 | 
			
		||||
 
 | 
			
		||||
@@ -160,7 +160,7 @@ public class AddressPredicate
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Determine whether the given address matches a series of patterns
 | 
			
		||||
     * Determine whether the given address matches a series of patterns.
 | 
			
		||||
     *
 | 
			
		||||
     * @param address The address to check.
 | 
			
		||||
     * @return Whether it matches any of these patterns.
 | 
			
		||||
 
 | 
			
		||||
@@ -13,256 +13,106 @@ import javax.annotation.Nullable;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Various helpers for arguments
 | 
			
		||||
 * A stub for any mods which depended on this version of the argument helper.
 | 
			
		||||
 *
 | 
			
		||||
 * @deprecated Use {@link dan200.computercraft.api.lua.ArgumentHelper}.
 | 
			
		||||
 */
 | 
			
		||||
@Deprecated
 | 
			
		||||
public final class ArgumentHelper
 | 
			
		||||
{
 | 
			
		||||
    private ArgumentHelper()
 | 
			
		||||
    {
 | 
			
		||||
        throw new IllegalStateException( "Cannot instantiate singleton " + getClass().getName() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static String getType( @Nullable Object type )
 | 
			
		||||
    {
 | 
			
		||||
        if( type == null ) return "nil";
 | 
			
		||||
        if( type instanceof String ) return "string";
 | 
			
		||||
        if( type instanceof Boolean ) return "boolean";
 | 
			
		||||
        if( type instanceof Number ) return "number";
 | 
			
		||||
        if( type instanceof Map ) return "table";
 | 
			
		||||
 | 
			
		||||
        Class<?> klass = type.getClass();
 | 
			
		||||
        if( klass.isArray() )
 | 
			
		||||
        {
 | 
			
		||||
            StringBuilder name = new StringBuilder();
 | 
			
		||||
            while( klass.isArray() )
 | 
			
		||||
            {
 | 
			
		||||
                name.append( "[]" );
 | 
			
		||||
                klass = klass.getComponentType();
 | 
			
		||||
            }
 | 
			
		||||
            name.insert( 0, klass.getName() );
 | 
			
		||||
            return name.toString();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return klass.getName();
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getType( type );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static LuaException badArgument( int index, @Nonnull String expected, @Nullable Object actual )
 | 
			
		||||
    {
 | 
			
		||||
        return badArgument( index, expected, getType( actual ) );
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.badArgumentOf( index, expected, actual );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual )
 | 
			
		||||
    {
 | 
			
		||||
        return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.badArgument( index, expected, actual );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getNumber( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "number", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Number )
 | 
			
		||||
        {
 | 
			
		||||
            return ((Number) value).doubleValue();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getDouble( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int getInt( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return (int) getLong( args, index );
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getInt( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long getLong( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "number", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Number )
 | 
			
		||||
        {
 | 
			
		||||
            return checkReal( index, (Number) value ).longValue();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getLong( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getReal( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return checkReal( index, getNumber( args, index ) );
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getFiniteDouble( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean getBoolean( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "boolean", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Boolean )
 | 
			
		||||
        {
 | 
			
		||||
            return (Boolean) value;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "boolean", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getBoolean( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static String getString( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "string", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof String )
 | 
			
		||||
        {
 | 
			
		||||
            return (String) value;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "string", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.getString( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings( "unchecked" )
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @SuppressWarnings( "unchecked" )
 | 
			
		||||
    public static Map<Object, Object> getTable( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "table", "nil" );
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Map )
 | 
			
		||||
        {
 | 
			
		||||
            return (Map<Object, Object>) value;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "table", value );
 | 
			
		||||
        }
 | 
			
		||||
        return (Map<Object, Object>) dan200.computercraft.api.lua.ArgumentHelper.getTable( args, index );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double optNumber( @Nonnull Object[] args, int index, double def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
        }
 | 
			
		||||
        else if( value instanceof Number )
 | 
			
		||||
        {
 | 
			
		||||
            return ((Number) value).doubleValue();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.optDouble( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int optInt( @Nonnull Object[] args, int index, int def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return (int) optLong( args, index, def );
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.optInt( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long optLong( @Nonnull Object[] args, int index, long def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
        }
 | 
			
		||||
        else if( value instanceof Number )
 | 
			
		||||
        {
 | 
			
		||||
            return checkReal( index, (Number) value ).longValue();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.optLong( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double optReal( @Nonnull Object[] args, int index, double def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        return checkReal( index, optNumber( args, index, def ) );
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.optFiniteDouble( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean optBoolean( @Nonnull Object[] args, int index, boolean def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
        }
 | 
			
		||||
        else if( value instanceof Boolean )
 | 
			
		||||
        {
 | 
			
		||||
            return (Boolean) value;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "boolean", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.optBoolean( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String optString( @Nonnull Object[] args, int index, String def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
        }
 | 
			
		||||
        else if( value instanceof String )
 | 
			
		||||
        {
 | 
			
		||||
            return (String) value;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "string", value );
 | 
			
		||||
        }
 | 
			
		||||
        return dan200.computercraft.api.lua.ArgumentHelper.optString( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings( "unchecked" )
 | 
			
		||||
    public static Map<Object, Object> optTable( @Nonnull Object[] args, int index, Map<Object, Object> def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
        }
 | 
			
		||||
        else if( value instanceof Map )
 | 
			
		||||
        {
 | 
			
		||||
            return (Map<Object, Object>) value;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "table", value );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static Number checkReal( int index, Number value ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        checkReal( index, value.doubleValue() );
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static double checkReal( int index, double value ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( Double.isNaN( value ) )
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", "nan" );
 | 
			
		||||
        }
 | 
			
		||||
        else if( value == Double.POSITIVE_INFINITY )
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", "inf" );
 | 
			
		||||
        }
 | 
			
		||||
        else if( value == Double.NEGATIVE_INFINITY )
 | 
			
		||||
        {
 | 
			
		||||
            throw badArgument( index, "number", "-inf" );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
        return (Map<Object, Object>) dan200.computercraft.api.lua.ArgumentHelper.optTable( args, index, def );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
 | 
			
		||||
 | 
			
		||||
public class FSAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import java.util.Collections;
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.*;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.*;
 | 
			
		||||
import static dan200.computercraft.core.apis.TableHelper.*;
 | 
			
		||||
 | 
			
		||||
public class HTTPAPI implements ILuaAPI
 | 
			
		||||
@@ -89,7 +89,7 @@ public class HTTPAPI implements ILuaAPI
 | 
			
		||||
            case 0: // request
 | 
			
		||||
            {
 | 
			
		||||
                String address, postString, requestMethod;
 | 
			
		||||
                Map<Object, Object> headerTable;
 | 
			
		||||
                Map<?, ?> headerTable;
 | 
			
		||||
                boolean binary, redirect;
 | 
			
		||||
 | 
			
		||||
                if( args.length >= 1 && args[0] instanceof Map )
 | 
			
		||||
@@ -172,7 +172,7 @@ public class HTTPAPI implements ILuaAPI
 | 
			
		||||
            case 2: // websocket
 | 
			
		||||
            {
 | 
			
		||||
                String address = getString( args, 0 );
 | 
			
		||||
                Map<Object, Object> headerTbl = optTable( args, 1, Collections.emptyMap() );
 | 
			
		||||
                Map<?, ?> headerTbl = optTable( args, 1, Collections.emptyMap() );
 | 
			
		||||
 | 
			
		||||
                if( !ComputerCraft.http_websocket_enable )
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ import java.time.ZonedDateTime;
 | 
			
		||||
import java.time.format.DateTimeFormatterBuilder;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.*;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.*;
 | 
			
		||||
 | 
			
		||||
public class OSAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
@@ -229,7 +229,7 @@ public class OSAPI implements ILuaAPI
 | 
			
		||||
            case 1:
 | 
			
		||||
            {
 | 
			
		||||
                // startTimer
 | 
			
		||||
                double timer = getReal( args, 0 );
 | 
			
		||||
                double timer = getFiniteDouble( args, 0 );
 | 
			
		||||
                synchronized( m_timers )
 | 
			
		||||
                {
 | 
			
		||||
                    m_timers.put( m_nextTimerToken, new Timer( (int) Math.round( timer / 0.05 ) ) );
 | 
			
		||||
@@ -239,7 +239,7 @@ public class OSAPI implements ILuaAPI
 | 
			
		||||
            case 2:
 | 
			
		||||
            {
 | 
			
		||||
                // setAlarm
 | 
			
		||||
                double time = getReal( args, 0 );
 | 
			
		||||
                double time = getFiniteDouble( args, 0 );
 | 
			
		||||
                if( time < 0.0 || time >= 24.0 )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( "Number out of range" );
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ import java.util.Collections;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
 | 
			
		||||
 | 
			
		||||
public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.*;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.*;
 | 
			
		||||
 | 
			
		||||
public class RedstoneAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -6,14 +6,17 @@
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.core.apis;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.lua.ArgumentHelper;
 | 
			
		||||
import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getNumericType;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Various helpers for tables
 | 
			
		||||
 * Various helpers for tables.
 | 
			
		||||
 */
 | 
			
		||||
public final class TableHelper
 | 
			
		||||
{
 | 
			
		||||
@@ -200,21 +203,7 @@ public final class TableHelper
 | 
			
		||||
 | 
			
		||||
    private static double checkReal( @Nonnull String key, double value ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( Double.isNaN( value ) )
 | 
			
		||||
        {
 | 
			
		||||
            throw badKey( key, "number", "nan" );
 | 
			
		||||
        }
 | 
			
		||||
        else if( value == Double.POSITIVE_INFINITY )
 | 
			
		||||
        {
 | 
			
		||||
            throw badKey( key, "number", "inf" );
 | 
			
		||||
        }
 | 
			
		||||
        else if( value == Double.NEGATIVE_INFINITY )
 | 
			
		||||
        {
 | 
			
		||||
            throw badKey( key, "number", "-inf" );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
        if( !Double.isFinite( value ) ) throw badKey( key, "number", getNumericType( value ) );
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ import org.apache.commons.lang3.ArrayUtils;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.*;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.*;
 | 
			
		||||
 | 
			
		||||
public class TermAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
@@ -242,9 +242,9 @@ public class TermAPI implements ILuaAPI
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    double r = getReal( args, 1 );
 | 
			
		||||
                    double g = getReal( args, 2 );
 | 
			
		||||
                    double b = getReal( args, 3 );
 | 
			
		||||
                    double r = getFiniteDouble( args, 1 );
 | 
			
		||||
                    double g = getFiniteDouble( args, 2 );
 | 
			
		||||
                    double b = getFiniteDouble( args, 3 );
 | 
			
		||||
                    setColour( m_terminal, colour, r, g, b );
 | 
			
		||||
                }
 | 
			
		||||
                return null;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,8 @@ import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getInt;
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optBoolean;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getInt;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optBoolean;
 | 
			
		||||
 | 
			
		||||
public class BinaryReadableHandle extends HandleGeneric
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@
 | 
			
		||||
package dan200.computercraft.core.apis.handles;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ObjectArrays;
 | 
			
		||||
import dan200.computercraft.api.lua.ArgumentHelper;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaContext;
 | 
			
		||||
import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
import dan200.computercraft.core.apis.ArgumentHelper;
 | 
			
		||||
import dan200.computercraft.shared.util.StringUtil;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
@@ -73,7 +73,7 @@ public class BinaryWritableHandle extends HandleGeneric
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        throw ArgumentHelper.badArgument( 0, "string or number", args.length > 0 ? args[0] : null );
 | 
			
		||||
                        throw ArgumentHelper.badArgumentOf( 0, "string or number", args.length > 0 ? args[0] : null );
 | 
			
		||||
                    }
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@ import java.nio.charset.CharsetDecoder;
 | 
			
		||||
import java.nio.charset.CodingErrorAction;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optBoolean;
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optInt;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optBoolean;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optInt;
 | 
			
		||||
 | 
			
		||||
public class EncodedReadableHandle extends HandleGeneric
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,8 @@ import java.io.IOException;
 | 
			
		||||
import java.nio.channels.Channel;
 | 
			
		||||
import java.nio.channels.SeekableByteChannel;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optLong;
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optLong;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optString;
 | 
			
		||||
 | 
			
		||||
public abstract class HandleGeneric implements ILuaObject
 | 
			
		||||
{
 | 
			
		||||
@@ -47,7 +47,7 @@ public abstract class HandleGeneric implements ILuaObject
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shared implementation for various file handle types
 | 
			
		||||
     * Shared implementation for various file handle types.
 | 
			
		||||
     *
 | 
			
		||||
     * @param channel The channel to seek in
 | 
			
		||||
     * @param args    The Lua arguments to process, like Lua's {@code file:seek}.
 | 
			
		||||
 
 | 
			
		||||
@@ -99,7 +99,7 @@ public final class NetworkUtils
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks a host is allowed
 | 
			
		||||
     * Checks a host is allowed.
 | 
			
		||||
     *
 | 
			
		||||
     * @param host The domain to check against
 | 
			
		||||
     * @throws HTTPRequestException If the host is not permitted.
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,8 @@ import java.util.function.Consumer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A holder for one or more resources, with a lifetime.
 | 
			
		||||
 *
 | 
			
		||||
 * @param <T> The type of this resource. Should be the class extending from {@link Resource}.
 | 
			
		||||
 */
 | 
			
		||||
public abstract class Resource<T extends Resource<T>> implements Closeable
 | 
			
		||||
{
 | 
			
		||||
@@ -42,8 +44,9 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if this has been cancelled. If so, it'll clean up any
 | 
			
		||||
     * existing resources and cancel any pending futures.
 | 
			
		||||
     * Checks if this has been cancelled. If so, it'll clean up any existing resources and cancel any pending futures.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Whether this resource has been closed.
 | 
			
		||||
     */
 | 
			
		||||
    public final boolean checkClosed()
 | 
			
		||||
    {
 | 
			
		||||
@@ -80,6 +83,7 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a {@link WeakReference} which will close {@code this} when collected.
 | 
			
		||||
     *
 | 
			
		||||
     * @param <R>    The object we are wrapping in a reference.
 | 
			
		||||
     * @param object The object to reference to
 | 
			
		||||
     * @return The weak reference.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@ import java.util.function.Supplier;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A collection of {@link Resource}s, with an upper bound on capacity.
 | 
			
		||||
 *
 | 
			
		||||
 * @param <T> The type of the resource this group manages.
 | 
			
		||||
 */
 | 
			
		||||
public class ResourceGroup<T extends Resource<T>>
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,8 @@ import java.util.function.Supplier;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A {@link ResourceGroup} which will queue items when the group at capacity.
 | 
			
		||||
 *
 | 
			
		||||
 * @param <T> The type of the resource this queue manages.
 | 
			
		||||
 */
 | 
			
		||||
public class ResourceQueue<T extends Resource<T>> extends ResourceGroup<T>
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicInteger;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents one or more
 | 
			
		||||
 * Represents an in-progress HTTP request.
 | 
			
		||||
 */
 | 
			
		||||
public class HttpRequest extends Resource<HttpRequest>
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -226,7 +226,11 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Determine the redirect from this response
 | 
			
		||||
     * Determine the redirect from this response.
 | 
			
		||||
     *
 | 
			
		||||
     * @param status  The status of the HTTP response.
 | 
			
		||||
     * @param headers The headers of the HTTP response.
 | 
			
		||||
     * @return The URI to redirect to, or {@code null} if no redirect should occur.
 | 
			
		||||
     */
 | 
			
		||||
    private URI getRedirect( HttpResponseStatus status, HttpHeaders headers )
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import javax.annotation.Nullable;
 | 
			
		||||
import java.io.Closeable;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optBoolean;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optBoolean;
 | 
			
		||||
import static dan200.computercraft.core.apis.http.websocket.Websocket.CLOSE_EVENT;
 | 
			
		||||
import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -56,9 +56,6 @@ final class ComputerExecutor
 | 
			
		||||
{
 | 
			
		||||
    private static final int QUEUE_LIMIT = 256;
 | 
			
		||||
 | 
			
		||||
    private static IMount romMount;
 | 
			
		||||
    private static final Object romMountLock = new Object();
 | 
			
		||||
 | 
			
		||||
    private final Computer computer;
 | 
			
		||||
    private final List<ILuaAPI> apis = new ArrayList<>();
 | 
			
		||||
    final TimeoutState timeout = new TimeoutState();
 | 
			
		||||
@@ -268,7 +265,7 @@ final class ComputerExecutor
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Queue an event if the computer is on
 | 
			
		||||
     * Queue an event if the computer is on.
 | 
			
		||||
     *
 | 
			
		||||
     * @param event The event's name
 | 
			
		||||
     * @param args  The event's arguments
 | 
			
		||||
@@ -329,16 +326,10 @@ final class ComputerExecutor
 | 
			
		||||
 | 
			
		||||
    private IMount getRomMount()
 | 
			
		||||
    {
 | 
			
		||||
        if( romMount != null ) return romMount;
 | 
			
		||||
 | 
			
		||||
        synchronized( romMountLock )
 | 
			
		||||
        {
 | 
			
		||||
            if( romMount != null ) return romMount;
 | 
			
		||||
            return romMount = computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
 | 
			
		||||
        }
 | 
			
		||||
        return computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IWritableMount getRootMount()
 | 
			
		||||
    private IWritableMount getRootMount()
 | 
			
		||||
    {
 | 
			
		||||
        if( rootMount == null )
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ import static dan200.computercraft.core.computer.TimeoutState.TIMEOUT;
 | 
			
		||||
public final class ComputerThread
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * How often the computer thread monitor should run, in milliseconds
 | 
			
		||||
     * How often the computer thread monitor should run, in milliseconds.
 | 
			
		||||
     *
 | 
			
		||||
     * @see Monitor
 | 
			
		||||
     */
 | 
			
		||||
@@ -83,7 +83,7 @@ public final class ComputerThread
 | 
			
		||||
    private static final Object threadLock = new Object();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the computer thread system is currently running
 | 
			
		||||
     * Whether the computer thread system is currently running.
 | 
			
		||||
     */
 | 
			
		||||
    private static volatile boolean running = false;
 | 
			
		||||
 | 
			
		||||
@@ -105,7 +105,7 @@ public final class ComputerThread
 | 
			
		||||
    private static final Condition hasWork = computerLock.newCondition();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Active queues to execute
 | 
			
		||||
     * Active queues to execute.
 | 
			
		||||
     */
 | 
			
		||||
    private static final TreeSet<ComputerExecutor> computerQueue = new TreeSet<>( ( a, b ) -> {
 | 
			
		||||
        if( a == b ) return 0; // Should never happen, but let's be consistent here
 | 
			
		||||
@@ -126,7 +126,7 @@ public final class ComputerThread
 | 
			
		||||
    private ComputerThread() {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start the computer thread
 | 
			
		||||
     * Start the computer thread.
 | 
			
		||||
     */
 | 
			
		||||
    static void start()
 | 
			
		||||
    {
 | 
			
		||||
@@ -194,7 +194,7 @@ public final class ComputerThread
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Mark a computer as having work, enqueuing it on the thread
 | 
			
		||||
     * Mark a computer as having work, enqueuing it on the thread.
 | 
			
		||||
     *
 | 
			
		||||
     * You must be holding {@link ComputerExecutor}'s {@code queueLock} when calling this method - it should only
 | 
			
		||||
     * be called from {@code enqueue}.
 | 
			
		||||
@@ -244,6 +244,8 @@ public final class ComputerThread
 | 
			
		||||
     * {@link #minimumVirtualRuntime} based on the current tasks.
 | 
			
		||||
     *
 | 
			
		||||
     * This is called before queueing tasks, to ensure that {@link #minimumVirtualRuntime} is up-to-date.
 | 
			
		||||
     *
 | 
			
		||||
     * @param current The machine which we updating runtimes from.
 | 
			
		||||
     */
 | 
			
		||||
    private static void updateRuntimes( @Nullable ComputerExecutor current )
 | 
			
		||||
    {
 | 
			
		||||
@@ -321,7 +323,7 @@ public final class ComputerThread
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The scaled period for a single task
 | 
			
		||||
     * The scaled period for a single task.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The scaled period for the task
 | 
			
		||||
     * @see #DEFAULT_LATENCY
 | 
			
		||||
@@ -336,7 +338,7 @@ public final class ComputerThread
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Determine if the thread has computers queued up
 | 
			
		||||
     * Determine if the thread has computers queued up.
 | 
			
		||||
     *
 | 
			
		||||
     * @return If we have work queued up.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -36,12 +36,12 @@ import java.util.concurrent.TimeUnit;
 | 
			
		||||
public final class TimeoutState
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * The total time a task is allowed to run before aborting in nanoseconds
 | 
			
		||||
     * The total time a task is allowed to run before aborting in nanoseconds.
 | 
			
		||||
     */
 | 
			
		||||
    static final long TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 7000 );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The time the task is allowed to run after each abort in nanoseconds
 | 
			
		||||
     * The time the task is allowed to run after each abort in nanoseconds.
 | 
			
		||||
     */
 | 
			
		||||
    static final long ABORT_TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 1500 );
 | 
			
		||||
 | 
			
		||||
@@ -111,6 +111,8 @@ public final class TimeoutState
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If the machine should be passively aborted.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {@code true} if we should throw a timeout error.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isSoftAborted()
 | 
			
		||||
    {
 | 
			
		||||
@@ -118,7 +120,9 @@ public final class TimeoutState
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If the machine should be forcibly aborted.
 | 
			
		||||
     * Determine if the machine should be forcibly aborted.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {@code true} if the machine should be forcibly shut down.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isHardAborted()
 | 
			
		||||
    {
 | 
			
		||||
@@ -146,7 +150,7 @@ public final class TimeoutState
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Pauses the cumulative time, to be resumed by {@link #startTimer()}
 | 
			
		||||
     * Pauses the cumulative time, to be resumed by {@link #startTimer()}.
 | 
			
		||||
     *
 | 
			
		||||
     * @see #nanoCumulative()
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,16 @@ package dan200.computercraft.core.filesystem;
 | 
			
		||||
 | 
			
		||||
import com.google.common.cache.Cache;
 | 
			
		||||
import com.google.common.cache.CacheBuilder;
 | 
			
		||||
import com.google.common.collect.MapMaker;
 | 
			
		||||
import com.google.common.io.ByteStreams;
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.filesystem.IMount;
 | 
			
		||||
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
 | 
			
		||||
import net.minecraft.resources.IReloadableResourceManager;
 | 
			
		||||
import net.minecraft.resources.IResource;
 | 
			
		||||
import net.minecraft.resources.IResourceManager;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.util.ResourceLocationException;
 | 
			
		||||
import net.minecraftforge.resource.IResourceType;
 | 
			
		||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +32,7 @@ import java.util.*;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.function.Predicate;
 | 
			
		||||
 | 
			
		||||
public class ResourceMount implements IMount
 | 
			
		||||
public final class ResourceMount implements IMount
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Only cache files smaller than 1MiB.
 | 
			
		||||
@@ -55,6 +58,13 @@ public class ResourceMount implements IMount
 | 
			
		||||
        .<FileEntry, byte[]>weigher( ( k, v ) -> v.length )
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
    private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues().concurrencyLevel( 1 );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes.
 | 
			
		||||
     */
 | 
			
		||||
    private static final Map<IReloadableResourceManager, Map<ResourceLocation, ResourceMount>> MOUNT_CACHE = new WeakHashMap<>( 2 );
 | 
			
		||||
 | 
			
		||||
    private final String namespace;
 | 
			
		||||
    private final String subPath;
 | 
			
		||||
    private final IReloadableResourceManager manager;
 | 
			
		||||
@@ -62,7 +72,26 @@ public class ResourceMount implements IMount
 | 
			
		||||
    @Nullable
 | 
			
		||||
    private FileEntry root;
 | 
			
		||||
 | 
			
		||||
    public ResourceMount( String namespace, String subPath, IReloadableResourceManager manager )
 | 
			
		||||
    public static ResourceMount get( String namespace, String subPath, IReloadableResourceManager manager )
 | 
			
		||||
    {
 | 
			
		||||
        Map<ResourceLocation, ResourceMount> cache;
 | 
			
		||||
 | 
			
		||||
        synchronized( MOUNT_CACHE )
 | 
			
		||||
        {
 | 
			
		||||
            cache = MOUNT_CACHE.get( manager );
 | 
			
		||||
            if( cache == null ) MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ResourceLocation path = new ResourceLocation( namespace, subPath );
 | 
			
		||||
        synchronized( cache )
 | 
			
		||||
        {
 | 
			
		||||
            ResourceMount mount = cache.get( path );
 | 
			
		||||
            if( mount == null ) cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) );
 | 
			
		||||
            return mount;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ResourceMount( String namespace, String subPath, IReloadableResourceManager manager )
 | 
			
		||||
    {
 | 
			
		||||
        this.namespace = namespace;
 | 
			
		||||
        this.subPath = subPath;
 | 
			
		||||
@@ -119,7 +148,17 @@ public class ResourceMount implements IMount
 | 
			
		||||
            FileEntry nextEntry = lastEntry.children.get( part );
 | 
			
		||||
            if( nextEntry == null )
 | 
			
		||||
            {
 | 
			
		||||
                lastEntry.children.put( part, nextEntry = new FileEntry( new ResourceLocation( namespace, subPath + "/" + path ) ) );
 | 
			
		||||
                ResourceLocation childPath;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    childPath = new ResourceLocation( namespace, subPath + "/" + path );
 | 
			
		||||
                }
 | 
			
		||||
                catch( ResourceLocationException e )
 | 
			
		||||
                {
 | 
			
		||||
                    ComputerCraft.log.warn( "Cannot create resource location for {} ({})", part, e.getMessage() );
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                lastEntry.children.put( part, nextEntry = new FileEntry( childPath ) );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lastEntry = nextEntry;
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ public final class MachineResult
 | 
			
		||||
    public static final MachineResult TIMEOUT = new MachineResult( true, false, TimeoutState.ABORT_MESSAGE );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * An error with no user-friendly error message
 | 
			
		||||
     * An error with no user-friendly error message.
 | 
			
		||||
     */
 | 
			
		||||
    public static final MachineResult GENERIC_ERROR = new MachineResult( true, false, null );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -314,6 +314,9 @@ public class Terminal
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Determine whether this terminal has changed.
 | 
			
		||||
     *
 | 
			
		||||
     * @return If this terminal is dirty.
 | 
			
		||||
     * @deprecated All {@code *Changed()} methods are deprecated: one should pass in a callback
 | 
			
		||||
     * instead.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,8 @@ import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.text.ITextComponent;
 | 
			
		||||
import net.minecraft.util.text.StringTextComponent;
 | 
			
		||||
import net.minecraft.util.text.TranslationTextComponent;
 | 
			
		||||
import net.minecraft.world.ServerWorld;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraft.world.server.ServerWorld;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,10 @@ import com.mojang.brigadier.context.CommandContext;
 | 
			
		||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A {@link Command} which accepts an argument
 | 
			
		||||
 * A {@link Command} which accepts an argument.
 | 
			
		||||
 *
 | 
			
		||||
 * @param <S> The command source we consume.
 | 
			
		||||
 * @param <T> The argument given to this command when executed.
 | 
			
		||||
 */
 | 
			
		||||
@FunctionalInterface
 | 
			
		||||
public interface ArgCommand<S, T>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,10 @@ import static dan200.computercraft.shared.command.Exceptions.ARGUMENT_EXPECTED;
 | 
			
		||||
import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An alternative way of building command nodes, so one does not have to nest
 | 
			
		||||
 * An alternative way of building command nodes, so one does not have to nest.
 | 
			
		||||
 * {@link ArgumentBuilder#then(CommandNode)}s.
 | 
			
		||||
 *
 | 
			
		||||
 * @param <S> The command source we consume.
 | 
			
		||||
 */
 | 
			
		||||
public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,9 @@ import com.mojang.brigadier.tree.CommandNode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A builder which generates a {@link CommandNode} from the provided action.
 | 
			
		||||
 *
 | 
			
		||||
 * @param <S> The command source we consume.
 | 
			
		||||
 * @param <T> The type of action to execute when this command is run.
 | 
			
		||||
 */
 | 
			
		||||
@FunctionalInterface
 | 
			
		||||
public interface CommandNodeBuilder<S, T>
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ import net.minecraft.util.text.event.ClickEvent;
 | 
			
		||||
import net.minecraft.util.text.event.HoverEvent;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Various helpers for building chat messages
 | 
			
		||||
 * Various helpers for building chat messages.
 | 
			
		||||
 */
 | 
			
		||||
public final class ChatHelpers
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -107,7 +107,7 @@ public class TableBuilder
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Trim this table to a given height
 | 
			
		||||
     * Trim this table to a given height.
 | 
			
		||||
     *
 | 
			
		||||
     * @param height The desired height.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ public interface TableFormatter
 | 
			
		||||
    ITextComponent HEADER = coloured( "=", TextFormatting.GRAY );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get additional padding for the component
 | 
			
		||||
     * Get additional padding for the component.
 | 
			
		||||
     *
 | 
			
		||||
     * @param component The component to pad
 | 
			
		||||
     * @param width     The desired width for the component
 | 
			
		||||
@@ -32,7 +32,7 @@ public interface TableFormatter
 | 
			
		||||
    ITextComponent getPadding( ITextComponent component, int width );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the minimum padding between each column
 | 
			
		||||
     * Get the minimum padding between each column.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The minimum padding.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -89,4 +89,10 @@ public abstract class BlockGeneric extends Block
 | 
			
		||||
    {
 | 
			
		||||
        return type.create();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean canBeReplacedByLeaves( BlockState state, IWorldReader world, BlockPos pos )
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ package dan200.computercraft.shared.common;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.shared.network.container.ContainerData;
 | 
			
		||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
 | 
			
		||||
import dan200.computercraft.shared.util.InventoryUtil;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.inventory.container.Container;
 | 
			
		||||
@@ -33,7 +32,7 @@ public class ContainerHeldItem extends Container
 | 
			
		||||
        super( type, id );
 | 
			
		||||
 | 
			
		||||
        this.hand = hand;
 | 
			
		||||
        stack = InventoryUtil.copyItem( player.getHeldItem( hand ) );
 | 
			
		||||
        stack = player.getHeldItem( hand ).copy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, HeldItemContainerData data )
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,6 @@ public abstract class TileGeneric extends TileEntity
 | 
			
		||||
        markDirty();
 | 
			
		||||
        BlockPos pos = getPos();
 | 
			
		||||
        BlockState state = getBlockState();
 | 
			
		||||
        getWorld().markForRerender( pos );
 | 
			
		||||
        getWorld().notifyBlockUpdate( pos, state, state, 3 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,8 @@ import java.util.Collections;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getInt;
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getInt;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
 | 
			
		||||
 | 
			
		||||
public class CommandAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
@@ -85,7 +85,7 @@ public class CommandAPI implements ILuaAPI
 | 
			
		||||
        {
 | 
			
		||||
            receiver.clearOutput();
 | 
			
		||||
            int result = commandManager.handleCommand( m_computer.getSource(), command );
 | 
			
		||||
            return new Object[] { result > 0, receiver.copyOutput() };
 | 
			
		||||
            return new Object[] { result > 0, receiver.copyOutput(), result };
 | 
			
		||||
        }
 | 
			
		||||
        catch( Throwable t )
 | 
			
		||||
        {
 | 
			
		||||
@@ -194,7 +194,7 @@ public class CommandAPI implements ILuaAPI
 | 
			
		||||
                    );
 | 
			
		||||
                    if( !World.isValid( min ) || !World.isValid( max ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        throw new LuaException( "Co-ordinates out or range" );
 | 
			
		||||
                        throw new LuaException( "Co-ordinates out of range" );
 | 
			
		||||
                    }
 | 
			
		||||
                    if( (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1) > 4096 )
 | 
			
		||||
                    {
 | 
			
		||||
@@ -233,7 +233,7 @@ public class CommandAPI implements ILuaAPI
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        throw new LuaException( "co-ordinates out or range" );
 | 
			
		||||
                        throw new LuaException( "Co-ordinates out of range" );
 | 
			
		||||
                    }
 | 
			
		||||
                } );
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,8 @@ import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.RayTraceResult;
 | 
			
		||||
import net.minecraft.world.IBlockReader;
 | 
			
		||||
import net.minecraft.world.ServerWorld;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraft.world.server.ServerWorld;
 | 
			
		||||
import net.minecraft.world.storage.loot.LootContext;
 | 
			
		||||
import net.minecraft.world.storage.loot.LootParameters;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import net.minecraft.util.text.ITextComponent;
 | 
			
		||||
import net.minecraft.util.text.StringTextComponent;
 | 
			
		||||
import net.minecraft.util.text.TranslationTextComponent;
 | 
			
		||||
import net.minecraft.world.GameRules;
 | 
			
		||||
import net.minecraft.world.ServerWorld;
 | 
			
		||||
import net.minecraft.world.server.ServerWorld;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
 
 | 
			
		||||
@@ -230,7 +230,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the redstone input for an adjacent block
 | 
			
		||||
     * Gets the redstone input for an adjacent block.
 | 
			
		||||
     *
 | 
			
		||||
     * @param world The world we exist in
 | 
			
		||||
     * @param pos   The position of the neighbour
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
package dan200.computercraft.shared.computer.core;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Receives some input and forwards it to a computer
 | 
			
		||||
 * Receives some input and forwards it to a computer.
 | 
			
		||||
 *
 | 
			
		||||
 * @see InputState
 | 
			
		||||
 * @see IComputer
 | 
			
		||||
 
 | 
			
		||||
@@ -311,13 +311,13 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getTimeOfDay()
 | 
			
		||||
    {
 | 
			
		||||
        return (m_world.getGameTime() + 6000) % 24000 / 1000.0;
 | 
			
		||||
        return (m_world.getDayTime() + 6000) % 24000 / 1000.0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getDay()
 | 
			
		||||
    {
 | 
			
		||||
        return (int) ((m_world.getGameTime() + 6000) / 24000) + 1;
 | 
			
		||||
        return (int) ((m_world.getDayTime() + 6000) / 24000) + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -1,89 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
package dan200.computercraft.shared.integration.charset;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.shared.common.TileGeneric;
 | 
			
		||||
import net.minecraft.util.Direction;
 | 
			
		||||
import net.minecraftforge.common.capabilities.Capability;
 | 
			
		||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
 | 
			
		||||
import pl.asie.charset.api.wires.IBundledEmitter;
 | 
			
		||||
import pl.asie.charset.api.wires.IBundledReceiver;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.shared.integration.charset.IntegrationCharset.CAPABILITY_EMITTER;
 | 
			
		||||
import static dan200.computercraft.shared.integration.charset.IntegrationCharset.CAPABILITY_RECEIVER;
 | 
			
		||||
 | 
			
		||||
final class BundledCapabilityProvider implements ICapabilityProvider
 | 
			
		||||
{
 | 
			
		||||
    private final TileGeneric tile;
 | 
			
		||||
    private IBundledReceiver receiver;
 | 
			
		||||
    private IBundledEmitter[] emitters;
 | 
			
		||||
 | 
			
		||||
    BundledCapabilityProvider( TileGeneric tile )
 | 
			
		||||
    {
 | 
			
		||||
        this.tile = tile;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean hasCapability( @Nonnull Capability<?> capability, @Nullable Direction side )
 | 
			
		||||
    {
 | 
			
		||||
        return capability == CAPABILITY_EMITTER || capability == CAPABILITY_RECEIVER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public <T> T getCapability( @Nonnull Capability<T> capability, @Nullable Direction side )
 | 
			
		||||
    {
 | 
			
		||||
        if( capability == CAPABILITY_RECEIVER )
 | 
			
		||||
        {
 | 
			
		||||
            IBundledReceiver receiver = this.receiver;
 | 
			
		||||
            if( receiver == null )
 | 
			
		||||
            {
 | 
			
		||||
                receiver = this.receiver = () -> tile.onNeighbourChange( tile.getPos().offset( side ) );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return CAPABILITY_RECEIVER.cast( receiver );
 | 
			
		||||
        }
 | 
			
		||||
        else if( capability == CAPABILITY_EMITTER )
 | 
			
		||||
        {
 | 
			
		||||
            IBundledEmitter[] emitters = this.emitters;
 | 
			
		||||
            if( emitters == null ) emitters = this.emitters = new IBundledEmitter[7];
 | 
			
		||||
 | 
			
		||||
            int index = side == null ? 6 : side.getIndex();
 | 
			
		||||
            IBundledEmitter emitter = emitters[index];
 | 
			
		||||
            if( emitter == null )
 | 
			
		||||
            {
 | 
			
		||||
                if( side == null )
 | 
			
		||||
                {
 | 
			
		||||
                    emitter = emitters[index] = () -> {
 | 
			
		||||
                        int flags = 0;
 | 
			
		||||
                        for( Direction facing : Direction.VALUES ) flags |= tile.getBundledRedstoneOutput( facing );
 | 
			
		||||
                        return toBytes( flags );
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    emitter = emitters[index] = () -> toBytes( tile.getBundledRedstoneOutput( side ) );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return CAPABILITY_EMITTER.cast( emitter );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static byte[] toBytes( int flag )
 | 
			
		||||
    {
 | 
			
		||||
        byte[] channels = new byte[16];
 | 
			
		||||
        for( int i = 0; i < 16; i++ ) channels[i] = (flag & (1 << i)) == 0 ? (byte) 0 : 15;
 | 
			
		||||
        return channels;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
package dan200.computercraft.shared.integration.charset;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
 | 
			
		||||
import net.minecraft.tileentity.TileEntity;
 | 
			
		||||
import net.minecraft.util.Direction;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.shared.integration.charset.IntegrationCharset.CAPABILITY_EMITTER;
 | 
			
		||||
 | 
			
		||||
public class BundledRedstoneProvider implements IBundledRedstoneProvider
 | 
			
		||||
{
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
 | 
			
		||||
    {
 | 
			
		||||
        TileEntity tile = world.getTileEntity( pos );
 | 
			
		||||
        if( tile == null || !tile.hasCapability( CAPABILITY_EMITTER, side ) ) return -1;
 | 
			
		||||
 | 
			
		||||
        byte[] signal = tile.getCapability( CAPABILITY_EMITTER, side ).getBundledSignal();
 | 
			
		||||
        if( signal == null ) return -1;
 | 
			
		||||
 | 
			
		||||
        int flag = 0;
 | 
			
		||||
        for( int i = 0; i < signal.length; i++ ) flag |= signal[i] > 0 ? 1 << i : 0;
 | 
			
		||||
        return flag;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,52 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
package dan200.computercraft.shared.integration.charset;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.ComputerCraftAPI;
 | 
			
		||||
import dan200.computercraft.shared.common.TileGeneric;
 | 
			
		||||
import net.minecraft.tileentity.TileEntity;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraftforge.common.MinecraftForge;
 | 
			
		||||
import net.minecraftforge.common.capabilities.Capability;
 | 
			
		||||
import net.minecraftforge.common.capabilities.CapabilityInject;
 | 
			
		||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import pl.asie.charset.api.wires.IBundledEmitter;
 | 
			
		||||
import pl.asie.charset.api.wires.IBundledReceiver;
 | 
			
		||||
 | 
			
		||||
public final class IntegrationCharset
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation CAPABILITY_KEY = new ResourceLocation( ComputerCraft.MOD_ID, "charset" );
 | 
			
		||||
 | 
			
		||||
    @CapabilityInject( IBundledEmitter.class )
 | 
			
		||||
    static Capability<IBundledEmitter> CAPABILITY_EMITTER = null;
 | 
			
		||||
 | 
			
		||||
    @CapabilityInject( IBundledReceiver.class )
 | 
			
		||||
    static Capability<IBundledReceiver> CAPABILITY_RECEIVER = null;
 | 
			
		||||
 | 
			
		||||
    private IntegrationCharset()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void register()
 | 
			
		||||
    {
 | 
			
		||||
        if( CAPABILITY_EMITTER == null || CAPABILITY_RECEIVER == null ) return;
 | 
			
		||||
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( IntegrationCharset.class );
 | 
			
		||||
        ComputerCraftAPI.registerBundledRedstoneProvider( new BundledRedstoneProvider() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void attachGenericCapabilities( AttachCapabilitiesEvent<TileEntity> event )
 | 
			
		||||
    {
 | 
			
		||||
        TileEntity tile = event.getObject();
 | 
			
		||||
        if( tile instanceof TileGeneric )
 | 
			
		||||
        {
 | 
			
		||||
            event.addCapability( CAPABILITY_KEY, new BundledCapabilityProvider( (TileGeneric) tile ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -35,7 +35,6 @@ import net.minecraft.util.ResourceLocation;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.shared.integration.jei.RecipeResolver.MAIN_FAMILIES;
 | 
			
		||||
@@ -92,10 +91,6 @@ public class JEIComputerCraft implements IModPlugin
 | 
			
		||||
 | 
			
		||||
        runtime.getIngredientManager().addIngredientsAtRuntime( VanillaTypes.ITEM, upgradeItems );
 | 
			
		||||
 | 
			
		||||
        // Hide treasure disks
 | 
			
		||||
        runtime.getIngredientManager().removeIngredientsAtRuntime( VanillaTypes.ITEM,
 | 
			
		||||
            Collections.singletonList( new ItemStack( ComputerCraft.Items.treasureDisk ) ) );
 | 
			
		||||
 | 
			
		||||
        // Hide all upgrade recipes
 | 
			
		||||
        IRecipeCategory<?> category = (IRecipeCategory<?>) registry.getRecipeCategory( VanillaRecipeCategoryUid.CRAFTING );
 | 
			
		||||
        if( category != null )
 | 
			
		||||
@@ -114,7 +109,7 @@ public class JEIComputerCraft implements IModPlugin
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Distinguishes turtles by upgrades and family
 | 
			
		||||
     * Distinguishes turtles by upgrades and family.
 | 
			
		||||
     */
 | 
			
		||||
    private static final ISubtypeInterpreter turtleSubtype = stack -> {
 | 
			
		||||
        Item item = stack.getItem();
 | 
			
		||||
@@ -134,7 +129,7 @@ public class JEIComputerCraft implements IModPlugin
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Distinguishes pocket computers by upgrade and family
 | 
			
		||||
     * Distinguishes pocket computers by upgrade and family.
 | 
			
		||||
     */
 | 
			
		||||
    private static final ISubtypeInterpreter pocketSubtype = stack -> {
 | 
			
		||||
        Item item = stack.getItem();
 | 
			
		||||
@@ -150,7 +145,7 @@ public class JEIComputerCraft implements IModPlugin
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Distinguishes disks by colour
 | 
			
		||||
     * Distinguishes disks by colour.
 | 
			
		||||
     */
 | 
			
		||||
    private static final ISubtypeInterpreter diskSubtype = stack -> {
 | 
			
		||||
        Item item = stack.getItem();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,49 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.shared.integration.mcmp;
 | 
			
		||||
 | 
			
		||||
import mcmultipart.MCMultiPart;
 | 
			
		||||
import mcmultipart.api.item.ItemBlockMultipart;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.item.BlockItem;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.ActionResultType;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraftforge.fml.common.Loader;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public final class MCMPHooks
 | 
			
		||||
{
 | 
			
		||||
    private MCMPHooks()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ActionResultType onItemUse( BlockItem itemBlock, PlayerEntity player, World world, @Nonnull BlockPos pos, @Nonnull Hand hand, @Nonnull Direction facing, float hitX, float hitY, float hitZ )
 | 
			
		||||
    {
 | 
			
		||||
        if( !Loader.isModLoaded( MCMultiPart.MODID ) ) return ActionResultType.PASS;
 | 
			
		||||
 | 
			
		||||
        return ItemBlockMultipart.place(
 | 
			
		||||
            player, world, pos, hand, facing, hitX, hitY, hitZ, itemBlock,
 | 
			
		||||
            itemBlock.getBlock()::getStateForPlacement,
 | 
			
		||||
            MCMPIntegration.multipartMap.get( itemBlock.getBlock() ),
 | 
			
		||||
 | 
			
		||||
            (
 | 
			
		||||
                ItemStack stack, PlayerEntity thisPlayer, World thisWorld, BlockPos thisPos, Direction thisFacing,
 | 
			
		||||
                float thisX, float thisY, float thisZ, BlockState thisState
 | 
			
		||||
            ) ->
 | 
			
		||||
                thisPlayer.canPlayerEdit( thisPos, thisFacing, stack ) &&
 | 
			
		||||
                    thisWorld.getBlockState( thisPos ).getBlock().isReplaceable( thisWorld, thisPos ) &&
 | 
			
		||||
                    itemBlock.getBlock().canPlaceBlockAt( thisWorld, thisPos ) &&
 | 
			
		||||
                    itemBlock.getBlock().canPlaceBlockOnSide( thisWorld, thisPos, thisFacing ) &&
 | 
			
		||||
                    itemBlock.placeBlockAt( stack, thisPlayer, thisWorld, thisPos, thisFacing, thisX, thisY, thisZ, thisState ),
 | 
			
		||||
            ItemBlockMultipart::placePartAt
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,127 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.shared.integration.mcmp;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.ComputerCraftAPI;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.common.TilePeripheralBase;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wireless.TileAdvancedModem;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
 | 
			
		||||
import mcmultipart.api.addon.IMCMPAddon;
 | 
			
		||||
import mcmultipart.api.addon.MCMPAddon;
 | 
			
		||||
import mcmultipart.api.container.IMultipartContainer;
 | 
			
		||||
import mcmultipart.api.multipart.IMultipart;
 | 
			
		||||
import mcmultipart.api.multipart.IMultipartRegistry;
 | 
			
		||||
import mcmultipart.api.multipart.IMultipartTile;
 | 
			
		||||
import mcmultipart.api.ref.MCMPCapabilities;
 | 
			
		||||
import mcmultipart.api.slot.EnumFaceSlot;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.tileentity.TileEntity;
 | 
			
		||||
import net.minecraft.util.Direction;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraftforge.common.MinecraftForge;
 | 
			
		||||
import net.minecraftforge.common.capabilities.Capability;
 | 
			
		||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
 | 
			
		||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@MCMPAddon
 | 
			
		||||
public class MCMPIntegration implements IMCMPAddon
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation CAPABILITY_KEY = new ResourceLocation( ComputerCraft.MOD_ID, "mcmultipart" );
 | 
			
		||||
 | 
			
		||||
    static final Map<Block, IMultipart> multipartMap = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    private static void register( IMultipartRegistry registry, Block block, IMultipart multipart )
 | 
			
		||||
    {
 | 
			
		||||
        registry.registerPartWrapper( block, multipart );
 | 
			
		||||
        multipartMap.put( block, multipart );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void registerParts( IMultipartRegistry registry )
 | 
			
		||||
    {
 | 
			
		||||
        // Setup all parts
 | 
			
		||||
        register( registry, ComputerCraft.Blocks.peripheral, new PartPeripheral() );
 | 
			
		||||
        register( registry, ComputerCraft.Blocks.advancedModem, new PartAdvancedModem() );
 | 
			
		||||
 | 
			
		||||
        // Subscribe to capability events
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( MCMPIntegration.class );
 | 
			
		||||
 | 
			
		||||
        // Register a peripheral provider
 | 
			
		||||
        ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) ->
 | 
			
		||||
        {
 | 
			
		||||
            TileEntity tile = world.getTileEntity( pos );
 | 
			
		||||
            if( tile == null || !tile.hasCapability( MCMPCapabilities.MULTIPART_CONTAINER, null ) ) return null;
 | 
			
		||||
            IMultipartContainer container = tile.getCapability( MCMPCapabilities.MULTIPART_CONTAINER, null );
 | 
			
		||||
            if( container == null ) return null;
 | 
			
		||||
 | 
			
		||||
            IMultipartTile multipart = container.getPartTile( EnumFaceSlot.fromFace( side ) ).orElse( null );
 | 
			
		||||
            if( multipart == null ) return null;
 | 
			
		||||
            if( multipart instanceof IPeripheral ) return (IPeripheral) multipart;
 | 
			
		||||
            if( multipart instanceof IPeripheralTile ) return ((IPeripheralTile) multipart).getPeripheral( side );
 | 
			
		||||
 | 
			
		||||
            TileEntity underlying = multipart.getTileEntity();
 | 
			
		||||
            if( underlying instanceof IPeripheral ) return (IPeripheral) underlying;
 | 
			
		||||
            if( underlying instanceof IPeripheralTile ) return ((IPeripheralTile) underlying).getPeripheral( side );
 | 
			
		||||
 | 
			
		||||
            return null;
 | 
			
		||||
        } );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void attach( AttachCapabilitiesEvent<TileEntity> event )
 | 
			
		||||
    {
 | 
			
		||||
        TileEntity tile = event.getObject();
 | 
			
		||||
        if( tile instanceof TileAdvancedModem || tile instanceof TileWirelessModem
 | 
			
		||||
            || tile instanceof TilePeripheralBase || tile instanceof TileMonitor )
 | 
			
		||||
        {
 | 
			
		||||
            // We need to attach to modems (obviously), but also any other tile created by BlockPeripheral. Otherwise
 | 
			
		||||
            // IMultipart.convertToMultipartTile will error.
 | 
			
		||||
            event.addCapability( CAPABILITY_KEY, new BasicMultipart( tile ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final class BasicMultipart implements ICapabilityProvider
 | 
			
		||||
    {
 | 
			
		||||
        private final TileEntity tile;
 | 
			
		||||
        private IMultipartTile wrapped;
 | 
			
		||||
 | 
			
		||||
        private BasicMultipart( TileEntity tile )
 | 
			
		||||
        {
 | 
			
		||||
            this.tile = tile;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public boolean hasCapability( @Nonnull Capability<?> capability, @Nullable Direction facing )
 | 
			
		||||
        {
 | 
			
		||||
            return capability == MCMPCapabilities.MULTIPART_TILE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nullable
 | 
			
		||||
        @Override
 | 
			
		||||
        public <T> T getCapability( @Nonnull Capability<T> capability, @Nullable Direction facing )
 | 
			
		||||
        {
 | 
			
		||||
            if( capability == MCMPCapabilities.MULTIPART_TILE )
 | 
			
		||||
            {
 | 
			
		||||
                IMultipartTile wrapped = this.wrapped;
 | 
			
		||||
                if( wrapped == null ) wrapped = this.wrapped = IMultipartTile.wrap( tile );
 | 
			
		||||
                return MCMPCapabilities.MULTIPART_TILE.cast( wrapped );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,41 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.shared.integration.mcmp;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wireless.BlockAdvancedModem;
 | 
			
		||||
import mcmultipart.api.multipart.IMultipart;
 | 
			
		||||
import mcmultipart.api.slot.EnumFaceSlot;
 | 
			
		||||
import mcmultipart.api.slot.IPartSlot;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.entity.LivingEntity;
 | 
			
		||||
import net.minecraft.util.Direction;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.IBlockAccess;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
public class PartAdvancedModem implements IMultipart
 | 
			
		||||
{
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPartSlot getSlotForPlacement( World world, BlockPos pos, BlockState state, Direction facing, float hitX, float hitY, float hitZ, LivingEntity placer )
 | 
			
		||||
    {
 | 
			
		||||
        return EnumFaceSlot.fromFace( state.getValue( BlockAdvancedModem.FACING ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPartSlot getSlotFromWorld( IBlockAccess world, BlockPos pos, BlockState state )
 | 
			
		||||
    {
 | 
			
		||||
        return EnumFaceSlot.fromFace( state.getValue( BlockAdvancedModem.FACING ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Block getBlock()
 | 
			
		||||
    {
 | 
			
		||||
        return ComputerCraft.Blocks.advancedModem;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.shared.integration.mcmp;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.common.BlockPeripheral;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.common.BlockPeripheralVariant;
 | 
			
		||||
import mcmultipart.api.multipart.IMultipart;
 | 
			
		||||
import mcmultipart.api.slot.EnumCenterSlot;
 | 
			
		||||
import mcmultipart.api.slot.EnumFaceSlot;
 | 
			
		||||
import mcmultipart.api.slot.IPartSlot;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.entity.LivingEntity;
 | 
			
		||||
import net.minecraft.util.Direction;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.IBlockAccess;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public class PartPeripheral implements IMultipart
 | 
			
		||||
{
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPartSlot getSlotForPlacement( World world, BlockPos pos, BlockState state, Direction facing, float hitX, float hitY, float hitZ, LivingEntity placer )
 | 
			
		||||
    {
 | 
			
		||||
        return getSlot( state );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPartSlot getSlotFromWorld( IBlockAccess world, BlockPos pos, BlockState state )
 | 
			
		||||
    {
 | 
			
		||||
        return getSlot( state );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    private static IPartSlot getSlot( BlockState state )
 | 
			
		||||
    {
 | 
			
		||||
        BlockPeripheralVariant type = state.getValue( BlockPeripheral.VARIANT );
 | 
			
		||||
        if( type == BlockPeripheralVariant.WirelessModemUpOn || type == BlockPeripheralVariant.WirelessModemUpOff )
 | 
			
		||||
        {
 | 
			
		||||
            return EnumFaceSlot.UP;
 | 
			
		||||
        }
 | 
			
		||||
        else if( type == BlockPeripheralVariant.WirelessModemDownOn || type == BlockPeripheralVariant.WirelessModemDownOff )
 | 
			
		||||
        {
 | 
			
		||||
            return EnumFaceSlot.DOWN;
 | 
			
		||||
        }
 | 
			
		||||
        else if( type == BlockPeripheralVariant.WirelessModemOff || type == BlockPeripheralVariant.WirelessModemOn )
 | 
			
		||||
        {
 | 
			
		||||
            return EnumFaceSlot.fromFace( state.getValue( BlockPeripheral.FACING ) );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return EnumCenterSlot.CENTER;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Block getBlock()
 | 
			
		||||
    {
 | 
			
		||||
        return ComputerCraft.Blocks.peripheral;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -6,16 +6,21 @@
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.shared.media.items;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.media.IMedia;
 | 
			
		||||
import dan200.computercraft.shared.util.RecordUtil;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.item.MusicDiscItem;
 | 
			
		||||
import net.minecraft.util.SoundEvent;
 | 
			
		||||
import net.minecraft.util.text.TranslationTextComponent;
 | 
			
		||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
 | 
			
		||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper.UnableToAccessFieldException;
 | 
			
		||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper.UnableToFindFieldException;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An implementation of IMedia for ItemRecord's
 | 
			
		||||
 * An implementation of IMedia for ItemRecords.
 | 
			
		||||
 */
 | 
			
		||||
public final class RecordMedia implements IMedia
 | 
			
		||||
{
 | 
			
		||||
@@ -34,12 +39,26 @@ public final class RecordMedia implements IMedia
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getAudioTitle( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        return RecordUtil.getRecordInfo( stack );
 | 
			
		||||
        Item item = stack.getItem();
 | 
			
		||||
        if( !(item instanceof MusicDiscItem) ) return null;
 | 
			
		||||
 | 
			
		||||
        return new TranslationTextComponent( item.getTranslationKey() + ".desc" ).getString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public SoundEvent getAudio( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        return ((MusicDiscItem) stack.getItem()).getSound();
 | 
			
		||||
        Item item = stack.getItem();
 | 
			
		||||
        if( !(item instanceof MusicDiscItem) ) return null;
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return ObfuscationReflectionHelper.getPrivateValue( MusicDiscItem.class, (MusicDiscItem) item, "field_185076_b" );
 | 
			
		||||
        }
 | 
			
		||||
        catch( UnableToAccessFieldException | UnableToFindFieldException e )
 | 
			
		||||
        {
 | 
			
		||||
            ComputerCraft.log.error( "Cannot get disk sound", e );
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,7 @@ public final class NetworkHandler
 | 
			
		||||
     * /**
 | 
			
		||||
     * Register packet, and a thread-unsafe handler for it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param <T>     The type of the packet to send.
 | 
			
		||||
     * @param id      The identifier for this packet type
 | 
			
		||||
     * @param factory The factory for this type of packet.
 | 
			
		||||
     */
 | 
			
		||||
@@ -106,6 +107,8 @@ public final class NetworkHandler
 | 
			
		||||
     * /**
 | 
			
		||||
     * Register packet, and a thread-unsafe handler for it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param <T>     The type of the packet to send.
 | 
			
		||||
     * @param type    The class of the type of packet to send.
 | 
			
		||||
     * @param id      The identifier for this packet type
 | 
			
		||||
     * @param decoder The factory for this type of packet.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ import net.minecraft.util.Hand;
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Opens a printout GUI based on the currently held item
 | 
			
		||||
 * Opens a printout GUI based on the currently held item.
 | 
			
		||||
 *
 | 
			
		||||
 * @see ContainerHeldItem
 | 
			
		||||
 * @see dan200.computercraft.shared.media.items.ItemPrintout
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ import net.minecraft.tileentity.CommandBlockTileEntity;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
 | 
			
		||||
 | 
			
		||||
public class CommandBlockPeripheral implements IPeripheral
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -11,19 +11,20 @@ import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
import dan200.computercraft.api.media.IMedia;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IComputerAccess;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.shared.MediaProviders;
 | 
			
		||||
import dan200.computercraft.shared.media.items.ItemDisk;
 | 
			
		||||
import dan200.computercraft.shared.util.StringUtil;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.optString;
 | 
			
		||||
 | 
			
		||||
public class DiskDrivePeripheral implements IPeripheral
 | 
			
		||||
class DiskDrivePeripheral implements IPeripheral
 | 
			
		||||
{
 | 
			
		||||
    private final TileDiskDrive m_diskDrive;
 | 
			
		||||
 | 
			
		||||
    public DiskDrivePeripheral( TileDiskDrive diskDrive )
 | 
			
		||||
    DiskDrivePeripheral( TileDiskDrive diskDrive )
 | 
			
		||||
    {
 | 
			
		||||
        m_diskDrive = diskDrive;
 | 
			
		||||
    }
 | 
			
		||||
@@ -55,7 +56,7 @@ public class DiskDrivePeripheral implements IPeripheral
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException
 | 
			
		||||
    public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
 | 
			
		||||
    {
 | 
			
		||||
        switch( method )
 | 
			
		||||
        {
 | 
			
		||||
@@ -63,21 +64,26 @@ public class DiskDrivePeripheral implements IPeripheral
 | 
			
		||||
                return new Object[] { !m_diskDrive.getDiskStack().isEmpty() };
 | 
			
		||||
            case 1: // getDiskLabel
 | 
			
		||||
            {
 | 
			
		||||
                IMedia media = m_diskDrive.getDiskMedia();
 | 
			
		||||
                return media == null ? null : new Object[] { media.getLabel( m_diskDrive.getDiskStack() ) };
 | 
			
		||||
                ItemStack stack = m_diskDrive.getDiskStack();
 | 
			
		||||
                IMedia media = MediaProviders.get( stack );
 | 
			
		||||
                return media == null ? null : new Object[] { media.getLabel( stack ) };
 | 
			
		||||
            }
 | 
			
		||||
            case 2: // setDiskLabel
 | 
			
		||||
            {
 | 
			
		||||
                String label = optString( arguments, 0, null );
 | 
			
		||||
 | 
			
		||||
                IMedia media = m_diskDrive.getDiskMedia();
 | 
			
		||||
                if( media == null ) return null;
 | 
			
		||||
                return context.executeMainThreadTask( () -> {
 | 
			
		||||
                    ItemStack stack = m_diskDrive.getDiskStack();
 | 
			
		||||
                    IMedia media = MediaProviders.get( stack );
 | 
			
		||||
                    if( media == null ) return null;
 | 
			
		||||
 | 
			
		||||
                ItemStack disk = m_diskDrive.getDiskStack();
 | 
			
		||||
                label = StringUtil.normaliseLabel( label );
 | 
			
		||||
                if( !media.setLabel( disk, label ) ) throw new LuaException( "Disk label cannot be changed" );
 | 
			
		||||
                m_diskDrive.setDiskStack( disk );
 | 
			
		||||
                return null;
 | 
			
		||||
                    if( !media.setLabel( stack, StringUtil.normaliseLabel( label ) ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        throw new LuaException( "Disk label cannot be changed" );
 | 
			
		||||
                    }
 | 
			
		||||
                    m_diskDrive.setDiskStack( stack );
 | 
			
		||||
                    return null;
 | 
			
		||||
                } );
 | 
			
		||||
            }
 | 
			
		||||
            case 3: // hasData
 | 
			
		||||
                return new Object[] { m_diskDrive.getDiskMountPath( computer ) != null };
 | 
			
		||||
@@ -86,14 +92,16 @@ public class DiskDrivePeripheral implements IPeripheral
 | 
			
		||||
            case 5:
 | 
			
		||||
            {
 | 
			
		||||
                // hasAudio
 | 
			
		||||
                IMedia media = m_diskDrive.getDiskMedia();
 | 
			
		||||
                return new Object[] { media != null && media.getAudio( m_diskDrive.getDiskStack() ) != null };
 | 
			
		||||
                ItemStack stack = m_diskDrive.getDiskStack();
 | 
			
		||||
                IMedia media = MediaProviders.get( stack );
 | 
			
		||||
                return new Object[] { media != null && media.getAudio( stack ) != null };
 | 
			
		||||
            }
 | 
			
		||||
            case 6:
 | 
			
		||||
            {
 | 
			
		||||
                // getAudioTitle
 | 
			
		||||
                IMedia media = m_diskDrive.getDiskMedia();
 | 
			
		||||
                return new Object[] { media != null ? media.getAudioTitle( m_diskDrive.getDiskStack() ) : false };
 | 
			
		||||
                ItemStack stack = m_diskDrive.getDiskStack();
 | 
			
		||||
                IMedia media = MediaProviders.get( stack );
 | 
			
		||||
                return new Object[] { media != null ? media.getAudioTitle( stack ) : false };
 | 
			
		||||
            }
 | 
			
		||||
            case 7: // playAudio
 | 
			
		||||
                m_diskDrive.playDiskAudio();
 | 
			
		||||
@@ -129,8 +137,7 @@ public class DiskDrivePeripheral implements IPeripheral
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals( IPeripheral other )
 | 
			
		||||
    {
 | 
			
		||||
        if( this == other ) return true;
 | 
			
		||||
        return other instanceof DiskDrivePeripheral && ((DiskDrivePeripheral) other).m_diskDrive == m_diskDrive;
 | 
			
		||||
        return this == other || other instanceof DiskDrivePeripheral && ((DiskDrivePeripheral) other).m_diskDrive == m_diskDrive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
 
 | 
			
		||||
@@ -320,35 +320,31 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public ItemStack getDiskStack()
 | 
			
		||||
    ItemStack getDiskStack()
 | 
			
		||||
    {
 | 
			
		||||
        return getStackInSlot( 0 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setDiskStack( @Nonnull ItemStack stack )
 | 
			
		||||
    void setDiskStack( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        setInventorySlotContents( 0, stack );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public IMedia getDiskMedia()
 | 
			
		||||
    private IMedia getDiskMedia()
 | 
			
		||||
    {
 | 
			
		||||
        return MediaProviders.get( getDiskStack() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getDiskMountPath( IComputerAccess computer )
 | 
			
		||||
    String getDiskMountPath( IComputerAccess computer )
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
            if( m_computers.containsKey( computer ) )
 | 
			
		||||
            {
 | 
			
		||||
                MountInfo info = m_computers.get( computer );
 | 
			
		||||
                return info.mountPath;
 | 
			
		||||
            }
 | 
			
		||||
            MountInfo info = m_computers.get( computer );
 | 
			
		||||
            return info != null ? info.mountPath : null;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void mount( IComputerAccess computer )
 | 
			
		||||
    void mount( IComputerAccess computer )
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
@@ -357,7 +353,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void unmount( IComputerAccess computer )
 | 
			
		||||
    void unmount( IComputerAccess computer )
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
@@ -366,7 +362,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void playDiskAudio()
 | 
			
		||||
    void playDiskAudio()
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
@@ -379,7 +375,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void stopDiskAudio()
 | 
			
		||||
    void stopDiskAudio()
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
@@ -388,7 +384,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void ejectDisk()
 | 
			
		||||
    void ejectDisk()
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
@@ -509,28 +505,6 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
 | 
			
		||||
        if( !destroyed ) getWorld().playBroadcastSound( 1000, getPos(), 0 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void readDescription( @Nonnull CompoundNBT nbt )
 | 
			
		||||
    {
 | 
			
		||||
        super.readDescription( nbt );
 | 
			
		||||
        customName = nbt.contains( NBT_NAME ) ? ITextComponent.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null;
 | 
			
		||||
        m_diskStack = nbt.contains( NBT_ITEM ) ? ItemStack.read( nbt.getCompound( NBT_ITEM ) ) : ItemStack.EMPTY;
 | 
			
		||||
        updateBlock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void writeDescription( @Nonnull CompoundNBT nbt )
 | 
			
		||||
    {
 | 
			
		||||
        super.writeDescription( nbt );
 | 
			
		||||
        if( customName != null ) nbt.putString( NBT_NAME, ITextComponent.Serializer.toJson( customName ) );
 | 
			
		||||
        if( !m_diskStack.isEmpty() )
 | 
			
		||||
        {
 | 
			
		||||
            CompoundNBT item = new CompoundNBT();
 | 
			
		||||
            m_diskStack.write( item );
 | 
			
		||||
            nbt.put( NBT_ITEM, item );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Private methods
 | 
			
		||||
 | 
			
		||||
    private void playRecord()
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getInt;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getInt;
 | 
			
		||||
 | 
			
		||||
public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -210,7 +210,7 @@ public class BlockCable extends BlockGeneric implements IWaterLoggable
 | 
			
		||||
 | 
			
		||||
        BlockPos offsetPos = pos.offset( facing );
 | 
			
		||||
        BlockState offsetState = world.getBlockState( offsetPos );
 | 
			
		||||
        return Block.hasSolidSide( offsetState, world, offsetPos, facing.getOpposite() );
 | 
			
		||||
        return hasSolidSide( offsetState, world, offsetPos, facing.getOpposite() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
 
 | 
			
		||||
@@ -201,8 +201,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
 | 
			
		||||
    public void onNeighbourChange( @Nonnull BlockPos neighbour )
 | 
			
		||||
    {
 | 
			
		||||
        Direction dir = getDirection();
 | 
			
		||||
        if( neighbour.equals( getPos().offset( dir ) ) && hasModem()
 | 
			
		||||
            && getBlockState().isValidPosition( world, pos ) )
 | 
			
		||||
        if( neighbour.equals( getPos().offset( dir ) ) && hasModem() && !getBlockState().isValidPosition( getWorld(), getPos() ) )
 | 
			
		||||
        {
 | 
			
		||||
            if( hasCable() )
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import java.util.Collections;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a local peripheral exposed on the wired network
 | 
			
		||||
 * Represents a local peripheral exposed on the wired network.
 | 
			
		||||
 *
 | 
			
		||||
 * This is responsible for getting the peripheral in world, tracking id and type and determining whether
 | 
			
		||||
 * it has changed.
 | 
			
		||||
@@ -39,7 +39,7 @@ public final class WiredModemLocalPeripheral
 | 
			
		||||
    private IPeripheral peripheral;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Attach a new peripheral from the world
 | 
			
		||||
     * Attach a new peripheral from the world.
 | 
			
		||||
     *
 | 
			
		||||
     * @param world     The world to search in
 | 
			
		||||
     * @param origin    The position to search from
 | 
			
		||||
@@ -76,7 +76,7 @@ public final class WiredModemLocalPeripheral
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Detach the current peripheral
 | 
			
		||||
     * Detach the current peripheral.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Whether the peripheral changed
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ import java.util.Map;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.concurrent.ConcurrentMap;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
 | 
			
		||||
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
 | 
			
		||||
 | 
			
		||||
public abstract class WiredModemPeripheral extends ModemPeripheral implements IWiredSender
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,18 @@ public class BlockMonitor extends BlockGeneric
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockRenderLayer getRenderLayer()
 | 
			
		||||
    {
 | 
			
		||||
        // We use the CUTOUT layer, as otherwise monitor rendering will cause flickering.
 | 
			
		||||
        return BlockRenderLayer.CUTOUT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public boolean isSolid( BlockState state )
 | 
			
		||||
    {
 | 
			
		||||
        // We override isSolid, as our overriding of getRenderLayer means that it would otherwise return false.
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void fillStateContainer( StateContainer.Builder<Block, BlockState> builder )
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user