mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-11-04 07:32:59 +00:00 
			
		
		
		
	Compare commits
	
		
			95 Commits
		
	
	
		
			v1.80pr1.1
			...
			v1.12.2-1.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e2bfaafe28 | ||
| 
						 | 
					1fb3d16b89 | ||
| 
						 | 
					35645b3d93 | ||
| 
						 | 
					a4cd1fe77d | ||
| 
						 | 
					4145914024 | ||
| 
						 | 
					6bd11a5e4a | ||
| 
						 | 
					46fa798797 | ||
| 
						 | 
					70a226207e | ||
| 
						 | 
					257a35f3ed | ||
| 
						 | 
					af01b9514b | ||
| 
						 | 
					070fd1f2ff | ||
| 
						 | 
					fb59da2b06 | ||
| 
						 | 
					11e4d0de82 | ||
| 
						 | 
					e46ab1e267 | ||
| 
						 | 
					d6e0f368df | ||
| 
						 | 
					9f2884bc0f | ||
| 
						 | 
					18d468e887 | ||
| 
						 | 
					63f6735bb8 | ||
| 
						 | 
					ab6f0ccd16 | ||
| 
						 | 
					ae0f093e73 | ||
| 
						 | 
					e5f988e3fe | ||
| 
						 | 
					12e82afad2 | ||
| 
						 | 
					6c2db93cbd | ||
| 
						 | 
					d5edbe700b | ||
| 
						 | 
					86ad43c3ab | ||
| 
						 | 
					f450c0156b | ||
| 
						 | 
					8abcfcb4ac | ||
| 
						 | 
					f3cace1d03 | ||
| 
						 | 
					e1e5e898ab | ||
| 
						 | 
					3aa3852ff6 | ||
| 
						 | 
					709a6329c7 | ||
| 
						 | 
					c9f05a2939 | ||
| 
						 | 
					e41377f862 | ||
| 
						 | 
					d173787a94 | ||
| 
						 | 
					d5aea26f3a | ||
| 
						 | 
					2681e578c4 | ||
| 
						 | 
					1f498dcc73 | ||
| 
						 | 
					83b01d35eb | ||
| 
						 | 
					8a7e651c99 | ||
| 
						 | 
					80a5759bae | ||
| 
						 | 
					e8a4fbb4e3 | ||
| 
						 | 
					0ce67afcc1 | ||
| 
						 | 
					a8dad23fa3 | ||
| 
						 | 
					443e0f8f76 | ||
| 
						 | 
					a838595e1e | ||
| 
						 | 
					61daab910e | ||
| 
						 | 
					7fd19c43e9 | ||
| 
						 | 
					ce0685c31f | ||
| 
						 | 
					e33f852baa | ||
| 
						 | 
					227d5e9e69 | ||
| 
						 | 
					1c648850ab | ||
| 
						 | 
					63691707fc | ||
| 
						 | 
					5d97b9c8f3 | ||
| 
						 | 
					77666d7399 | ||
| 
						 | 
					ed69495b03 | ||
| 
						 | 
					66b61d4e9e | ||
| 
						 | 
					8dd084ac5c | ||
| 
						 | 
					932f8a44fc | ||
| 
						 | 
					101b3500cc | ||
| 
						 | 
					a777801e15 | ||
| 
						 | 
					0d6787641a | ||
| 
						 | 
					744bba300e | ||
| 
						 | 
					34d43d8273 | ||
| 
						 | 
					7bc9745c7a | ||
| 
						 | 
					b414cba681 | ||
| 
						 | 
					1c9110b927 | ||
| 
						 | 
					325459e336 | ||
| 
						 | 
					ee3347afbd | ||
| 
						 | 
					27aaec9a82 | ||
| 
						 | 
					929f23fd2d | ||
| 
						 | 
					8422a40c69 | ||
| 
						 | 
					ca334e7e5c | ||
| 
						 | 
					54acf1d087 | ||
| 
						 | 
					42d3901ee3 | ||
| 
						 | 
					f8b328a048 | ||
| 
						 | 
					41a320e9a4 | ||
| 
						 | 
					57fb77d7fe | ||
| 
						 | 
					b59dcbfc0e | ||
| 
						 | 
					618c534d81 | ||
| 
						 | 
					26ba61097b | ||
| 
						 | 
					2c87e66db8 | ||
| 
						 | 
					f61f7df2d8 | ||
| 
						 | 
					364d31465e | ||
| 
						 | 
					4c7ac50dd8 | ||
| 
						 | 
					37e25136ed | ||
| 
						 | 
					d9f03f3ec7 | ||
| 
						 | 
					4d5c52bc63 | ||
| 
						 | 
					a1c4a9fb58 | ||
| 
						 | 
					031f17c98e | ||
| 
						 | 
					4ead319092 | ||
| 
						 | 
					dd6bab5413 | ||
| 
						 | 
					5b48a0fa5f | ||
| 
						 | 
					2032e7a83a | ||
| 
						 | 
					72b9d3d802 | ||
| 
						 | 
					70cb8ae16c | 
							
								
								
									
										5
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							@@ -6,11 +6,10 @@ about: Report some misbehaviour in the mod
 | 
			
		||||
 | 
			
		||||
<!--
 | 
			
		||||
## Before reporting
 | 
			
		||||
 - Search for the bug both here and [on the ComputerCraft issues page](https://github.com/dan200/ComputerCraft/issues?utf8=%E2%9C%93&q=is%3Aissue+)
 | 
			
		||||
 - If possible, try to reproduce on vanilla ComputerCraft. If it still occurs, [report on the ComputerCraft repo](https://github.com/dan200/ComputerCraft/issues/new) instead.
 | 
			
		||||
 - Search for the bug on the issue tracker. Make sure to look at closed issues too!
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
## Useful information to include:
 | 
			
		||||
 - Minecraft version
 | 
			
		||||
 - CC: Tweaked version
 | 
			
		||||
 - Detailed reproduction steps!** Sometimes I can spot a bug pretty easily, but often it's much more obscure. Anything you can give which will help reproduce it means it'll get fixed quicker.
 | 
			
		||||
 - Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
								
							@@ -6,10 +6,9 @@ about: Suggest an idea or improvement
 | 
			
		||||
 | 
			
		||||
<!--
 | 
			
		||||
## Before reporting
 | 
			
		||||
 - Search for the suggestion both here and [on the ComputerCraft issues page](https://github.com/dan200/ComputerCraft/issues?utf8=%E2%9C%93&q=is%3Aissue+). It's possible someone's suggested it before!
 | 
			
		||||
 - Unless something is specific to CC:Tweaked, try to [suggest them on the ComputerCraft repo](https://github.com/dan200/ComputerCraft/issues/new). There's a lot more people watching it, so it allows the wider community to contribute.
 | 
			
		||||
 - Search for the suggestion here. It's possible someone's suggested it before!
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
## Useful information to include:
 | 
			
		||||
 - Explanation of how the feature/change chould work.
 | 
			
		||||
 - Some rationale/use case for a feature. I'd like to keep CC:T as minimal
 | 
			
		||||
 - Explanation of how the feature/change should work.
 | 
			
		||||
 - Some rationale/use case for a feature. I'd like to keep CC:T as minimal as possible, so I like have a solid justification for each feature.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +0,0 @@
 | 
			
		||||
<!--
 | 
			
		||||
Unless this feature is specific to CC:Tweaked, try to [target the original ComputerCraft repo](https://github.com/dan200/ComputerCraft/) instead. There's a lot more people watching it, so it allows the wider community to contribute.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
## Useful information to include:
 | 
			
		||||
 - Brief explanation of the changes you've made.
 | 
			
		||||
 - Rationale of why this change has been made/reasoning behind it.
 | 
			
		||||
 | 
			
		||||
The more information you can provide, the easier it is to review something now _and_ to see why a change was made, when the code needs updating in the future.
 | 
			
		||||
							
								
								
									
										11
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,17 @@
 | 
			
		||||
# Build directories
 | 
			
		||||
/classes
 | 
			
		||||
/logs
 | 
			
		||||
/build
 | 
			
		||||
/out
 | 
			
		||||
 | 
			
		||||
# Runtime directories
 | 
			
		||||
/run
 | 
			
		||||
/run-*
 | 
			
		||||
/test-files
 | 
			
		||||
 | 
			
		||||
*.ipr
 | 
			
		||||
*.iws
 | 
			
		||||
*.iml
 | 
			
		||||
.idea
 | 
			
		||||
.gradle
 | 
			
		||||
/luaj-2.0.3/lib
 | 
			
		||||
/luaj-2.0.3/*.jar
 | 
			
		||||
*.DS_Store
 | 
			
		||||
/test-files
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								LICENSE-luaj
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								LICENSE-luaj
									
									
									
									
									
								
							@@ -1,19 +0,0 @@
 | 
			
		||||
Copyright (c) 2007 LuaJ. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										50
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								README.md
									
									
									
									
									
								
							@@ -1,35 +1,35 @@
 | 
			
		||||
# 
 | 
			
		||||
[](https://travis-ci.org/SquidDev-CC/CC-Tweaked)
 | 
			
		||||
 | 
			
		||||
CC: Tweaked is a fork of ComputerCraft which aims to provide earlier access to the more experimental and in-development
 | 
			
		||||
features of the mod. For a more stable experience, I recommend checking out the
 | 
			
		||||
[original mod](https://github.com/dan200/ComputerCraft).
 | 
			
		||||
CC: Tweaked is a fork of [ComputerCraft](https://github.com/dan200/ComputerCraft), adding programmable computers,
 | 
			
		||||
turtles and more to Minecraft.
 | 
			
		||||
 | 
			
		||||
## What?
 | 
			
		||||
CC: Tweaked (or CC:T for short) does not aim to create a competing fork of ComputerCraft, nor am I planning to take it
 | 
			
		||||
in in a vastly different direction to the original mod. In fact, CC:T aims to be a nurturing ground for various
 | 
			
		||||
features, with a pull request against the original mod being the end goal.
 | 
			
		||||
ComputerCraft has always held a fond place in my heart: it's the mod which really got me into Minecraft, and it's the
 | 
			
		||||
mod which has kept me playing it for many years. However, development of the original mod has slowed, as the original 
 | 
			
		||||
developers have had less time to work on the mod, and moved onto other projects and commitments. 
 | 
			
		||||
 | 
			
		||||
CC:T also includes many pull requests from the community which have not yet been merged, offering a large number
 | 
			
		||||
of additional bug fixes and features over the original mod.
 | 
			
		||||
CC:Tweaked (or CC:T for short) is an attempt to continue ComputerCraft's legacy. It's not intended to be a competitor
 | 
			
		||||
to CC, nor do I want to take it in a vastly different direction to the original mod. Instead, CC:T focuses on making the
 | 
			
		||||
ComputerCraft experience as _solid_ as possible, ironing out any wrinkles that may have developed over time.
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
CC: Tweaked contains all the features of the latest alpha, as well as numerous fixes, performance improvements and
 | 
			
		||||
several additional features. I'd recommend checking out [the releases page](https://github.com/SquidDev-CC/CC-Tweaked/releases)
 | 
			
		||||
to see the full changes, but here's a couple of the more interesting changes:
 | 
			
		||||
CC: Tweaked contains all the features of the latest version of ComputerCraft, as well as numerous fixes, performance 
 | 
			
		||||
improvements and several nifty additions. I'd recommend checking out [the releases page](https://github.com/SquidDev-CC/CC-Tweaked/releases)
 | 
			
		||||
to see the full set of changes, but here's a couple of the more interesting additions:
 | 
			
		||||
 | 
			
		||||
 - Replace LuaJ with Cobalt.
 | 
			
		||||
 - Allow running multiple computers at the same time.
 | 
			
		||||
 - Websocket support in the HTTP library.
 | 
			
		||||
 - Wired modems and cables act more like multiparts.
 | 
			
		||||
 - Add map-like rendering for pocket computers and printed pages/books.
 | 
			
		||||
 - Adds the `/computercraft` command, offering various diagnostic tools for server owners. This allows operators to
 | 
			
		||||
   track which computers are hogging resources, turn on and shutdown multiple computers at once and interact with
 | 
			
		||||
 - Improvements to the `http` library, including websockets, support for other HTTP methods (`PUT`, `DELETE`, etc...) 
 | 
			
		||||
   and configurable limits on HTTP usage.
 | 
			
		||||
 - Full-block wired modems, allowing one to wrap non-solid peripherals (such as turtles, or chests if Plethora is
 | 
			
		||||
   installed).   
 | 
			
		||||
 - Pocket computers can be held like maps, allowing you to view the screen without entering a GUI.
 | 
			
		||||
 - Printed pages and books can be placed in item frames and held like maps.
 | 
			
		||||
 - Several profiling and administration tools for server owners, via the `/computercraft` command. This allows operators 
 | 
			
		||||
   to track which computers are hogging resources, turn on and shutdown multiple computers at once and interact with
 | 
			
		||||
   computers remotely.
 | 
			
		||||
 - Add full-block wired modems, allowing one to wrap non-solid peripherals (such as turtles, or chests if Plethora is
 | 
			
		||||
   installed).
 | 
			
		||||
 - Extended binary file handles. They support file seeking, and reading new lines, allowing full (and accurate)
 | 
			
		||||
   emulation of the standard Lua `io` library.
 | 
			
		||||
 - Closer emulation of standard Lua, adding the `debug` and `io` libraries. This also enables seeking within binary
 | 
			
		||||
   files, meaning you don't need to read large files into memory.
 | 
			
		||||
 - Allow running multiple computers on multiple threads, reducing latency on worlds with many computers.
 | 
			
		||||
 | 
			
		||||
## Relation to CCTweaks?
 | 
			
		||||
This mod has nothing to do with CCTweaks, though there is no denying the name is a throwback to it. That being said,
 | 
			
		||||
@@ -37,10 +37,8 @@ several features have been included, such as full block modems, the Cobalt runti
 | 
			
		||||
computers.
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you do wish to contribute
 | 
			
		||||
code, do consider submitting it to the ComputerCraft repository first.
 | 
			
		||||
 | 
			
		||||
That being said, in order to start helping develop CC:T, you'll need to follow these steps:
 | 
			
		||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping
 | 
			
		||||
develop CC:T, you'll need to follow these steps:
 | 
			
		||||
 | 
			
		||||
 - **Clone the repository:** `git clone https://github.com/SquidDev-CC/CC-Tweaked.git && cd CC-Tweaked`
 | 
			
		||||
 - **Setup Forge:** `./gradlew setupDecompWorkspace`
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										146
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										146
									
								
								build.gradle
									
									
									
									
									
								
							@@ -9,8 +9,10 @@ buildscript {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    dependencies {
 | 
			
		||||
        classpath 'com.google.code.gson:gson:2.8.1'
 | 
			
		||||
        classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
 | 
			
		||||
        classpath 'org.ajoberstar:gradle-git:1.6.0'
 | 
			
		||||
        classpath 'net.sf.proguard:proguard-gradle:6.1.0beta1'
 | 
			
		||||
        classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -23,14 +25,17 @@ apply plugin: 'org.ajoberstar.grgit'
 | 
			
		||||
apply plugin: 'maven-publish'
 | 
			
		||||
apply plugin: 'maven'
 | 
			
		||||
 | 
			
		||||
version = "1.80pr1.12"
 | 
			
		||||
def mc_version = "1.12.2"
 | 
			
		||||
def main_version = "1.81.1"
 | 
			
		||||
version = "${mc_version}-${main_version}"
 | 
			
		||||
 | 
			
		||||
group = "org.squiddev"
 | 
			
		||||
archivesBaseName = "cc-tweaked"
 | 
			
		||||
 | 
			
		||||
minecraft {
 | 
			
		||||
    version = "1.12.2-14.23.4.2749"
 | 
			
		||||
    version = "${mc_version}-14.23.4.2749"
 | 
			
		||||
    runDir = "run"
 | 
			
		||||
    replace '${version}', project.version
 | 
			
		||||
    replace '${version}', main_version
 | 
			
		||||
 | 
			
		||||
    // the mappings can be changed at any time, and must be in the following format.
 | 
			
		||||
    // snapshot_YYYYMMDD   snapshot are built nightly.
 | 
			
		||||
@@ -48,7 +53,7 @@ repositories {
 | 
			
		||||
    }
 | 
			
		||||
    maven {
 | 
			
		||||
        name = "squiddev"
 | 
			
		||||
        url = "https://dl.bintray.com/squiddev/maven"
 | 
			
		||||
        url = "https://squiddev.cc/maven"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ivy { artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]" }
 | 
			
		||||
@@ -66,7 +71,7 @@ dependencies {
 | 
			
		||||
 | 
			
		||||
    runtime "mezz.jei:jei_1.12.2:4.8.5.159"
 | 
			
		||||
 | 
			
		||||
    shade 'org.squiddev:Cobalt:0.4.0'
 | 
			
		||||
    shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT'
 | 
			
		||||
 | 
			
		||||
    testCompile 'junit:junit:4.11'
 | 
			
		||||
 | 
			
		||||
@@ -84,39 +89,91 @@ jar {
 | 
			
		||||
        attributes('FMLAT': 'computercraft_at.cfg')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    into("docs", { from (javadoc.destinationDir) })
 | 
			
		||||
 | 
			
		||||
    into("api", { from (sourceSets.main.allSource) {
 | 
			
		||||
    from (sourceSets.main.allSource) {
 | 
			
		||||
        include "dan200/computercraft/api/**/*.java"
 | 
			
		||||
    }})
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
import java.nio.file.*
 | 
			
		||||
import java.util.zip.*
 | 
			
		||||
 | 
			
		||||
import com.google.gson.GsonBuilder
 | 
			
		||||
import com.google.gson.JsonElement
 | 
			
		||||
import org.ajoberstar.grgit.Grgit
 | 
			
		||||
import proguard.gradle.ProGuardTask
 | 
			
		||||
 | 
			
		||||
task proguard(type: ProGuardTask, dependsOn: jar) {
 | 
			
		||||
    description "Removes unused shadowed classes from the jar"
 | 
			
		||||
    group "compact"
 | 
			
		||||
 | 
			
		||||
    injars jar.archivePath
 | 
			
		||||
    outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"
 | 
			
		||||
 | 
			
		||||
    // Add the main runtime jar and all non-shadowed dependencies
 | 
			
		||||
    libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
 | 
			
		||||
    doFirst {
 | 
			
		||||
        sourceSets.main.compileClasspath
 | 
			
		||||
            .filter { !it.name.contains("Cobalt") }
 | 
			
		||||
            .each { libraryjars it }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We want to avoid as much obfuscation as possible. We're only doing this to shrink code size.
 | 
			
		||||
    dontobfuscate; dontoptimize; keepattributes; keepparameternames
 | 
			
		||||
 | 
			
		||||
    // Proguard will remove directories by default, but that breaks JarMount.
 | 
			
		||||
    keepdirectories 'assets/computercraft/lua**'
 | 
			
		||||
 | 
			
		||||
    // Preserve ComputerCraft classes - we only want to strip shadowed files.
 | 
			
		||||
    keep 'class dan200.computercraft.** { *; }'
 | 
			
		||||
 | 
			
		||||
    // Preserve the constructors in Cobalt library class, as we init them via reflection
 | 
			
		||||
    keepclassmembers 'class org.squiddev.cobalt.lib.** { <init>(...); }'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
task proguardMove(dependsOn: proguard) {
 | 
			
		||||
    description "Replace the original jar with the minified version"
 | 
			
		||||
    group "compact"
 | 
			
		||||
 | 
			
		||||
    doLast {
 | 
			
		||||
        Files.move(
 | 
			
		||||
            file("${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar").toPath(),
 | 
			
		||||
            file(jar.archivePath).toPath(),
 | 
			
		||||
            StandardCopyOption.REPLACE_EXISTING
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
reobfJar.dependsOn proguardMove
 | 
			
		||||
 | 
			
		||||
processResources {
 | 
			
		||||
    inputs.property "version", project.version
 | 
			
		||||
    inputs.property "mcversion", project.minecraft.version
 | 
			
		||||
    inputs.property "version", main_version
 | 
			
		||||
    inputs.property "mcversion", mc_version
 | 
			
		||||
 | 
			
		||||
    def grgit = Grgit.open(dir: '.')
 | 
			
		||||
    inputs.property "commithash", grgit.head().id
 | 
			
		||||
 | 
			
		||||
    def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
 | 
			
		||||
    def hash = 'none'
 | 
			
		||||
    Set<String> contributors = []
 | 
			
		||||
    try {
 | 
			
		||||
        def grgit = Grgit.open(dir: '.')
 | 
			
		||||
        hash = grgit.head().id
 | 
			
		||||
 | 
			
		||||
    grgit.log().each {
 | 
			
		||||
        if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
 | 
			
		||||
        if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
 | 
			
		||||
    }
 | 
			
		||||
        def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
 | 
			
		||||
        grgit.log().each {
 | 
			
		||||
            if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
 | 
			
		||||
            if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
 | 
			
		||||
        }
 | 
			
		||||
    } catch(Exception ignored) { }
 | 
			
		||||
 | 
			
		||||
    inputs.property "commithash", hash
 | 
			
		||||
 | 
			
		||||
    from(sourceSets.main.resources.srcDirs) {
 | 
			
		||||
        include 'mcmod.info'
 | 
			
		||||
        include 'assets/computercraft/lua/rom/help/credits.txt'
 | 
			
		||||
 | 
			
		||||
        expand 'version':project.version,
 | 
			
		||||
               'mcversion':project.minecraft.version,
 | 
			
		||||
               'gitcontributors':contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
 | 
			
		||||
        expand 'version': main_version,
 | 
			
		||||
               'mcversion': mc_version,
 | 
			
		||||
               'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    from(sourceSets.main.resources.srcDirs) {
 | 
			
		||||
@@ -125,12 +182,53 @@ processResources {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
task compressJson(dependsOn: extractAnnotationsJar) {
 | 
			
		||||
    group "compact"
 | 
			
		||||
    description "Minifies all JSON files, stripping whitespace"
 | 
			
		||||
 | 
			
		||||
    def jarPath = file(jar.archivePath)
 | 
			
		||||
 | 
			
		||||
    def tempPath = File.createTempFile("input", ".jar", temporaryDir)
 | 
			
		||||
    tempPath.deleteOnExit()
 | 
			
		||||
 | 
			
		||||
    def gson = new GsonBuilder().create()
 | 
			
		||||
 | 
			
		||||
    doLast {
 | 
			
		||||
        // Copy over all files in the current jar to the new one, running json files from GSON. As pretty printing
 | 
			
		||||
        // is turned off, they should be minified.
 | 
			
		||||
        new ZipFile(jarPath).withCloseable { inJar ->
 | 
			
		||||
            new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(tempPath))).withCloseable { outJar ->
 | 
			
		||||
                inJar.entries().each { entry ->
 | 
			
		||||
                    if(entry.directory) {
 | 
			
		||||
                        outJar.putNextEntry(entry)
 | 
			
		||||
                    } else if(!entry.name.endsWith(".json")) {
 | 
			
		||||
                        outJar.putNextEntry(entry)
 | 
			
		||||
                        inJar.getInputStream(entry).withCloseable { outJar << it }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        ZipEntry newEntry = new ZipEntry(entry.name)
 | 
			
		||||
                        newEntry.setTime(entry.time)
 | 
			
		||||
                        outJar.putNextEntry(newEntry)
 | 
			
		||||
 | 
			
		||||
                        def element = inJar.getInputStream(entry).withCloseable { gson.fromJson(it.newReader("UTF8"), JsonElement.class) }
 | 
			
		||||
                        outJar.write(gson.toJson(element).getBytes(StandardCharsets.UTF_8))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // And replace the original jar again
 | 
			
		||||
        Files.move(tempPath.toPath(), jarPath.toPath(), StandardCopyOption.REPLACE_EXISTING)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
assemble.dependsOn compressJson
 | 
			
		||||
 | 
			
		||||
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${project.version})."
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								codeStyleSettings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								codeStyleSettings.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
<code_scheme name="Project" version="173">
 | 
			
		||||
  <JSON>
 | 
			
		||||
    <option name="OBJECT_WRAPPING" value="1" />
 | 
			
		||||
    <option name="ARRAY_WRAPPING" value="1" />
 | 
			
		||||
  </JSON>
 | 
			
		||||
  <JavaCodeStyleSettings>
 | 
			
		||||
    <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
 | 
			
		||||
      <value />
 | 
			
		||||
    </option>
 | 
			
		||||
    <option name="JD_P_AT_EMPTY_LINES" value="false" />
 | 
			
		||||
    <option name="JD_PRESERVE_LINE_FEEDS" value="true" />
 | 
			
		||||
  </JavaCodeStyleSettings>
 | 
			
		||||
  <codeStyleSettings language="JAVA">
 | 
			
		||||
    <option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
 | 
			
		||||
    <option name="BRACE_STYLE" value="2" />
 | 
			
		||||
    <option name="CLASS_BRACE_STYLE" value="2" />
 | 
			
		||||
    <option name="METHOD_BRACE_STYLE" value="2" />
 | 
			
		||||
    <option name="LAMBDA_BRACE_STYLE" value="5" />
 | 
			
		||||
    <option name="ELSE_ON_NEW_LINE" value="true" />
 | 
			
		||||
    <option name="CATCH_ON_NEW_LINE" value="true" />
 | 
			
		||||
    <option name="FINALLY_ON_NEW_LINE" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_METHOD_CALL_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_METHOD_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_IF_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_WHILE_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_FOR_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_TRY_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_CATCH_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_SWITCH_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_SYNCHRONIZED_PARENTHESES" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
 | 
			
		||||
    <option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_TRY_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
 | 
			
		||||
    <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
 | 
			
		||||
    <option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
 | 
			
		||||
    <option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
 | 
			
		||||
    <option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
 | 
			
		||||
    <option name="IF_BRACE_FORCE" value="1" />
 | 
			
		||||
    <option name="DOWHILE_BRACE_FORCE" value="1" />
 | 
			
		||||
    <option name="WHILE_BRACE_FORCE" value="1" />
 | 
			
		||||
    <option name="FOR_BRACE_FORCE" value="1" />
 | 
			
		||||
    <option name="SPACE_WITHIN_ANNOTATION_PARENTHESES" value="true" />
 | 
			
		||||
    <indentOptions>
 | 
			
		||||
      <option name="CONTINUATION_INDENT_SIZE" value="4" />
 | 
			
		||||
    </indentOptions>
 | 
			
		||||
  </codeStyleSettings>
 | 
			
		||||
  <codeStyleSettings language="JSON">
 | 
			
		||||
    <option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
 | 
			
		||||
    <option name="SPACE_WITHIN_BRACKETS" value="true" />
 | 
			
		||||
    <option name="SPACE_WITHIN_BRACES" value="true" />
 | 
			
		||||
    <indentOptions>
 | 
			
		||||
      <option name="INDENT_SIZE" value="4" />
 | 
			
		||||
      <option name="CONTINUATION_INDENT_SIZE" value="4" />
 | 
			
		||||
    </indentOptions>
 | 
			
		||||
  </codeStyleSettings>
 | 
			
		||||
</code_scheme>
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -49,9 +49,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_getVersion != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                return (String)computerCraft_getVersion.invoke( null );
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (String) computerCraft_getVersion.invoke( null );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -82,9 +85,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_createUniqueNumberedSaveDir != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                return (Integer)computerCraft_createUniqueNumberedSaveDir.invoke( null, world, parentSubPath );
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (Integer) computerCraft_createUniqueNumberedSaveDir.invoke( null, world, parentSubPath );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -115,9 +121,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_createSaveDirMount != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                return (IWritableMount)computerCraft_createSaveDirMount.invoke( null, world, subPath, capacity );
 | 
			
		||||
            } catch (Exception e){
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (IWritableMount) computerCraft_createSaveDirMount.invoke( null, world, subPath, capacity );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -148,9 +157,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_createResourceMount != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                return (IMount)computerCraft_createResourceMount.invoke( null, modClass, domain, subPath );
 | 
			
		||||
            } catch (Exception e){
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (IMount) computerCraft_createResourceMount.invoke( null, modClass, domain, subPath );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -158,20 +170,23 @@ public final class ComputerCraftAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers a peripheral handler to convert blocks into {@link IPeripheral} implementations.
 | 
			
		||||
     * Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
 | 
			
		||||
     *
 | 
			
		||||
     * @param handler The peripheral provider to register.
 | 
			
		||||
     * @param provider The peripheral provider to register.
 | 
			
		||||
     * @see dan200.computercraft.api.peripheral.IPeripheral
 | 
			
		||||
     * @see dan200.computercraft.api.peripheral.IPeripheralProvider
 | 
			
		||||
     */
 | 
			
		||||
    public static void registerPeripheralProvider( @Nonnull IPeripheralProvider handler )
 | 
			
		||||
    public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
 | 
			
		||||
    {
 | 
			
		||||
        findCC();
 | 
			
		||||
        if ( computerCraft_registerPeripheralProvider != null)
 | 
			
		||||
        if( computerCraft_registerPeripheralProvider != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                computerCraft_registerPeripheralProvider.invoke( null, handler );
 | 
			
		||||
            } catch (Exception e){
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                computerCraft_registerPeripheralProvider.invoke( null, provider );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -192,9 +207,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
            findCC();
 | 
			
		||||
            if( computerCraft_registerTurtleUpgrade != null )
 | 
			
		||||
            {
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    computerCraft_registerTurtleUpgrade.invoke( null, upgrade );
 | 
			
		||||
                } catch( Exception e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( Exception e )
 | 
			
		||||
                {
 | 
			
		||||
                    // It failed
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -202,19 +220,22 @@ public final class ComputerCraftAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers a bundled redstone handler to provide bundled redstone output for blocks.
 | 
			
		||||
     * Registers a bundled redstone provider to provide bundled redstone output for blocks.
 | 
			
		||||
     *
 | 
			
		||||
     * @param handler The bundled redstone provider to register.
 | 
			
		||||
     * @param provider The bundled redstone provider to register.
 | 
			
		||||
     * @see dan200.computercraft.api.redstone.IBundledRedstoneProvider
 | 
			
		||||
     */
 | 
			
		||||
    public static void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider handler )
 | 
			
		||||
    public static void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
 | 
			
		||||
    {
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_registerBundledRedstoneProvider != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                computerCraft_registerBundledRedstoneProvider.invoke( null, handler );
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                computerCraft_registerBundledRedstoneProvider.invoke( null, provider );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -235,9 +256,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_getDefaultBundledRedstoneOutput != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                return (Integer)computerCraft_getDefaultBundledRedstoneOutput.invoke( null, world, pos, side );
 | 
			
		||||
            } catch (Exception e){
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (Integer) computerCraft_getDefaultBundledRedstoneOutput.invoke( null, world, pos, side );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -245,40 +269,46 @@ public final class ComputerCraftAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers a media handler to provide {@link IMedia} implementations for Items
 | 
			
		||||
     * Registers a media provider to provide {@link IMedia} implementations for Items
 | 
			
		||||
     *
 | 
			
		||||
     * @param handler The media provider to register.
 | 
			
		||||
     * @param provider The media provider to register.
 | 
			
		||||
     * @see dan200.computercraft.api.media.IMediaProvider
 | 
			
		||||
     */
 | 
			
		||||
    public static void registerMediaProvider( @Nonnull IMediaProvider handler )
 | 
			
		||||
    public static void registerMediaProvider( @Nonnull IMediaProvider provider )
 | 
			
		||||
    {
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_registerMediaProvider != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                computerCraft_registerMediaProvider.invoke( null, handler );
 | 
			
		||||
            } catch (Exception e){
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                computerCraft_registerMediaProvider.invoke( null, provider );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers a permission handler to restrict where turtles can move or build.
 | 
			
		||||
     * Registers a permission provider to restrict where turtles can move or build.
 | 
			
		||||
     *
 | 
			
		||||
     * @param handler The turtle permission provider to register.
 | 
			
		||||
     * @param provider The turtle permission provider to register.
 | 
			
		||||
     * @see dan200.computercraft.api.permissions.ITurtlePermissionProvider
 | 
			
		||||
     * @deprecated Prefer using {@link dan200.computercraft.api.turtle.event.TurtleBlockEvent} or the standard Forge events.
 | 
			
		||||
     */
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public static void registerPermissionProvider( @Nonnull ITurtlePermissionProvider handler )
 | 
			
		||||
    public static void registerPermissionProvider( @Nonnull ITurtlePermissionProvider provider )
 | 
			
		||||
    {
 | 
			
		||||
        findCC();
 | 
			
		||||
        if( computerCraft_registerPermissionProvider != null )
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                computerCraft_registerPermissionProvider.invoke( null, handler );
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                computerCraft_registerPermissionProvider.invoke( null, provider );
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -287,10 +317,14 @@ public final class ComputerCraftAPI
 | 
			
		||||
    public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
 | 
			
		||||
    {
 | 
			
		||||
        findCC();
 | 
			
		||||
        if(computerCraft_registerPocketUpgrade != null) {
 | 
			
		||||
            try {
 | 
			
		||||
        if( computerCraft_registerPocketUpgrade != null )
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                computerCraft_registerPocketUpgrade.invoke( null, upgrade );
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -309,7 +343,9 @@ public final class ComputerCraftAPI
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return (IPacketNetwork) computerCraft_getWirelessNetwork.invoke( null );
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                // It failed;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -394,12 +430,14 @@ public final class ComputerCraftAPI
 | 
			
		||||
 | 
			
		||||
    private static void findCC()
 | 
			
		||||
    {
 | 
			
		||||
        if( !ccSearched ) {
 | 
			
		||||
            try {
 | 
			
		||||
        if( !ccSearched )
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                computerCraft = Class.forName( "dan200.computercraft.ComputerCraft" );
 | 
			
		||||
                computerCraft_getVersion = findCCMethod( "getVersion", new Class<?>[]{
 | 
			
		||||
                computerCraft_getVersion = findCCMethod( "getVersion", new Class<?>[] {
 | 
			
		||||
                } );
 | 
			
		||||
                computerCraft_createUniqueNumberedSaveDir = findCCMethod( "createUniqueNumberedSaveDir", new Class<?>[]{
 | 
			
		||||
                computerCraft_createUniqueNumberedSaveDir = findCCMethod( "createUniqueNumberedSaveDir", new Class<?>[] {
 | 
			
		||||
                    World.class, String.class
 | 
			
		||||
                } );
 | 
			
		||||
                computerCraft_createSaveDirMount = findCCMethod( "createSaveDirMount", new Class<?>[] {
 | 
			
		||||
@@ -437,12 +475,16 @@ public final class ComputerCraftAPI
 | 
			
		||||
                computerCraft_createWiredNodeForElement = findCCMethod( "createWiredNodeForElement", new Class<?>[] {
 | 
			
		||||
                    IWiredElement.class
 | 
			
		||||
                } );
 | 
			
		||||
                computerCraft_getWiredElementAt = findCCMethod( "getWiredElementAt", new Class<?>[]{
 | 
			
		||||
                computerCraft_getWiredElementAt = findCCMethod( "getWiredElementAt", new Class<?>[] {
 | 
			
		||||
                    IBlockAccess.class, BlockPos.class, EnumFacing.class
 | 
			
		||||
                } );
 | 
			
		||||
            } catch( Exception e ) {
 | 
			
		||||
            }
 | 
			
		||||
            catch( Exception e )
 | 
			
		||||
            {
 | 
			
		||||
                System.out.println( "ComputerCraftAPI: ComputerCraft not found." );
 | 
			
		||||
            } finally {
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ccSearched = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -450,13 +492,12 @@ public final class ComputerCraftAPI
 | 
			
		||||
 | 
			
		||||
    private static Method findCCMethod( String name, Class<?>[] args )
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            if( computerCraft != null )
 | 
			
		||||
            {
 | 
			
		||||
                return computerCraft.getMethod( name, args );
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        } catch( NoSuchMethodException e ) {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return computerCraft != null ? computerCraft.getMethod( name, args ) : null;
 | 
			
		||||
        }
 | 
			
		||||
        catch( NoSuchMethodException e )
 | 
			
		||||
        {
 | 
			
		||||
            System.out.println( "ComputerCraftAPI: ComputerCraft method " + name + " not found." );
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.filesystem;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.filesystem.IFileSystem;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 * 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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.ComputerCraftAPI;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 * 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.network;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 * 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.network;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 * 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.network;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 * 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.network;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.network.wired;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.ComputerCraftAPI;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.network.wired;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.network.wired;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.network.wired;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.network.IPacketNetwork;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.network.wired;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.network.IPacketSender;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +39,10 @@ public interface IComputerAccess
 | 
			
		||||
     * @see IMount
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    String mount( @Nonnull String desiredLocation, @Nonnull IMount mount );
 | 
			
		||||
    default String mount( @Nonnull String desiredLocation, @Nonnull IMount mount )
 | 
			
		||||
    {
 | 
			
		||||
        return mount( desiredLocation, mount, getAttachmentName() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Mount a mount onto the computer's file system in a read only mode.
 | 
			
		||||
@@ -75,7 +78,10 @@ public interface IComputerAccess
 | 
			
		||||
     * @see IMount
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount );
 | 
			
		||||
    default String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount )
 | 
			
		||||
    {
 | 
			
		||||
        return mountWritable( desiredLocation, mount, getAttachmentName() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Mount a mount onto the computer's file system in a writable mode.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.ComputerCraftAPI;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.turtle.event;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.turtle.ITurtleAccess;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.turtle.event;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.turtle.ITurtleAccess;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the public ComputerCraft API - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								src/main/java/dan200/computercraft/client/ClientRegistry.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								src/main/java/dan200/computercraft/client/ClientRegistry.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.render.TurtleModelLoader;
 | 
			
		||||
import dan200.computercraft.shared.media.items.ItemDiskLegacy;
 | 
			
		||||
import dan200.computercraft.shared.turtle.items.ItemTurtleBase;
 | 
			
		||||
import dan200.computercraft.shared.util.Colour;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.ItemMeshDefinition;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelBakery;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureMap;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraftforge.client.event.ColorHandlerEvent;
 | 
			
		||||
import net.minecraftforge.client.event.ModelBakeEvent;
 | 
			
		||||
import net.minecraftforge.client.event.ModelRegistryEvent;
 | 
			
		||||
import net.minecraftforge.client.event.TextureStitchEvent;
 | 
			
		||||
import net.minecraftforge.client.model.IModel;
 | 
			
		||||
import net.minecraftforge.client.model.ModelLoader;
 | 
			
		||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.Side;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Registers textures and models for items.
 | 
			
		||||
 */
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
 | 
			
		||||
public class ClientRegistry
 | 
			
		||||
{
 | 
			
		||||
    private static final String[] EXTRA_MODELS = {
 | 
			
		||||
        "turtle_modem_off_left",
 | 
			
		||||
        "turtle_modem_on_left",
 | 
			
		||||
        "turtle_modem_off_right",
 | 
			
		||||
        "turtle_modem_on_right",
 | 
			
		||||
        "turtle_crafting_table_left",
 | 
			
		||||
        "turtle_crafting_table_right",
 | 
			
		||||
        "advanced_turtle_modem_off_left",
 | 
			
		||||
        "advanced_turtle_modem_on_left",
 | 
			
		||||
        "advanced_turtle_modem_off_right",
 | 
			
		||||
        "advanced_turtle_modem_on_right",
 | 
			
		||||
        "turtle_speaker_upgrade_left",
 | 
			
		||||
        "turtle_speaker_upgrade_right",
 | 
			
		||||
 | 
			
		||||
        "turtle_white",
 | 
			
		||||
        "turtle_elf_overlay",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void registerModels( ModelRegistryEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        ModelLoaderRegistry.registerLoader( TurtleModelLoader.INSTANCE );
 | 
			
		||||
 | 
			
		||||
        // Register item models
 | 
			
		||||
        registerUniversalItemModel( ComputerCraft.Items.computer, "computer" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.commandComputer, 0, "command_computer" );
 | 
			
		||||
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.pocketComputer, 0, "pocket_computer" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.pocketComputer, 1, "advanced_pocket_computer" );
 | 
			
		||||
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.peripheral, 0, "peripheral" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.peripheral, 1, "wireless_modem" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.peripheral, 2, "monitor" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.peripheral, 3, "printer" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.peripheral, 4, "advanced_monitor" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.cable, 0, "cable" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.cable, 1, "wired_modem" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.advancedModem, 0, "advanced_modem" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.peripheral, 5, "speaker" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.wiredModemFull, 0, "wired_modem_full" );
 | 
			
		||||
 | 
			
		||||
        registerUniversalItemModel( ComputerCraft.Items.disk, "disk" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.diskExpanded, 0, "disk_expanded" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.treasureDisk, 0, "treasure_disk" );
 | 
			
		||||
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.printout, 0, "printout" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.printout, 1, "pages" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.printout, 2, "book" );
 | 
			
		||||
 | 
			
		||||
        registerUniversalItemModel( ComputerCraft.Items.turtle, "turtle" );
 | 
			
		||||
        registerUniversalItemModel( ComputerCraft.Items.turtleExpanded, "turtle" );
 | 
			
		||||
        registerUniversalItemModel( ComputerCraft.Items.turtleAdvanced, "turtle_advanced" );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
 | 
			
		||||
    {
 | 
			
		||||
        // Load all textures for the extra models
 | 
			
		||||
        TextureMap map = event.getMap();
 | 
			
		||||
        for( String upgrade : EXTRA_MODELS )
 | 
			
		||||
        {
 | 
			
		||||
            IModel model = ModelLoaderRegistry.getModelOrMissing( new ResourceLocation( "computercraft", "block/" + upgrade ) );
 | 
			
		||||
            for( ResourceLocation texture : model.getTextures() ) map.registerSprite( texture );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void onModelBakeEvent( ModelBakeEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        // Load all extra models
 | 
			
		||||
        for( String model : EXTRA_MODELS ) loadBlockModel( event, model );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void onItemColours( ColorHandlerEvent.Item event )
 | 
			
		||||
    {
 | 
			
		||||
        event.getItemColors().registerItemColorHandler(
 | 
			
		||||
            ( stack, layer ) -> layer == 0 ? 0xFFFFFF : ((ItemDiskLegacy) stack.getItem()).getColour( stack ),
 | 
			
		||||
            ComputerCraft.Items.disk, ComputerCraft.Items.diskExpanded
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        event.getItemColors().registerItemColorHandler( ( stack, layer ) -> {
 | 
			
		||||
            switch( layer )
 | 
			
		||||
            {
 | 
			
		||||
                case 0:
 | 
			
		||||
                default:
 | 
			
		||||
                    return 0xFFFFFF;
 | 
			
		||||
                case 1:
 | 
			
		||||
                {
 | 
			
		||||
                    // Frame colour
 | 
			
		||||
                    int colour = ComputerCraft.Items.pocketComputer.getColour( stack );
 | 
			
		||||
                    return colour == -1 ? 0xFFFFFF : colour;
 | 
			
		||||
                }
 | 
			
		||||
                case 2:
 | 
			
		||||
                {
 | 
			
		||||
                    // Light colour
 | 
			
		||||
                    int colour = ComputerCraft.Items.pocketComputer.getLightState( stack );
 | 
			
		||||
                    return colour == -1 ? Colour.Black.getHex() : colour;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, ComputerCraft.Items.pocketComputer );
 | 
			
		||||
 | 
			
		||||
        // Setup turtle colours
 | 
			
		||||
        event.getItemColors().registerItemColorHandler( ( stack, tintIndex ) -> {
 | 
			
		||||
            if( tintIndex == 0 )
 | 
			
		||||
            {
 | 
			
		||||
                ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
 | 
			
		||||
                int colour = turtle.getColour( stack );
 | 
			
		||||
                if( colour != -1 ) return colour;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return 0xFFFFFF;
 | 
			
		||||
        }, ComputerCraft.Blocks.turtle, ComputerCraft.Blocks.turtleExpanded, ComputerCraft.Blocks.turtleAdvanced );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void registerItemModel( Item item, int damage, String name )
 | 
			
		||||
    {
 | 
			
		||||
        ResourceLocation location = new ResourceLocation( ComputerCraft.MOD_ID, name );
 | 
			
		||||
        final ModelResourceLocation res = new ModelResourceLocation( location, "inventory" );
 | 
			
		||||
        ModelBakery.registerItemVariants( item, location );
 | 
			
		||||
        ModelLoader.setCustomModelResourceLocation( item, damage, res );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void registerUniversalItemModel( Item item, String mainModel )
 | 
			
		||||
    {
 | 
			
		||||
        ResourceLocation mainLocation = new ResourceLocation( ComputerCraft.MOD_ID, mainModel );
 | 
			
		||||
        ModelBakery.registerItemVariants( item, mainLocation );
 | 
			
		||||
 | 
			
		||||
        final ModelResourceLocation mainModelLocation = new ModelResourceLocation( mainLocation, "inventory" );
 | 
			
		||||
        ModelLoader.setCustomMeshDefinition( item, new ItemMeshDefinition()
 | 
			
		||||
        {
 | 
			
		||||
            @Nonnull
 | 
			
		||||
            @Override
 | 
			
		||||
            public ModelResourceLocation getModelLocation( @Nonnull ItemStack stack )
 | 
			
		||||
            {
 | 
			
		||||
                return mainModelLocation;
 | 
			
		||||
            }
 | 
			
		||||
        } );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void loadBlockModel( ModelBakeEvent event, String name )
 | 
			
		||||
    {
 | 
			
		||||
        IModel model = ModelLoaderRegistry.getModelOrMissing( new ResourceLocation( ComputerCraft.MOD_ID, "block/" + name ) );
 | 
			
		||||
        IBakedModel bakedModel = model.bake(
 | 
			
		||||
            model.getDefaultState(), DefaultVertexFormats.ITEM,
 | 
			
		||||
            location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( location.toString() )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        event.getModelRegistry().putObject( new ModelResourceLocation( ComputerCraft.MOD_ID + ":" + name, "inventory" ), bakedModel );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,89 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.shared.command.text.ChatHelpers;
 | 
			
		||||
import dan200.computercraft.shared.command.text.TableBuilder;
 | 
			
		||||
import dan200.computercraft.shared.command.text.TableFormatter;
 | 
			
		||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.gui.FontRenderer;
 | 
			
		||||
import net.minecraft.client.gui.GuiNewChat;
 | 
			
		||||
import net.minecraft.client.gui.GuiUtilRenderComponents;
 | 
			
		||||
import net.minecraft.util.math.MathHelper;
 | 
			
		||||
import net.minecraft.util.text.ITextComponent;
 | 
			
		||||
import net.minecraft.util.text.TextFormatting;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class ClientTableFormatter implements TableFormatter
 | 
			
		||||
{
 | 
			
		||||
    public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
 | 
			
		||||
 | 
			
		||||
    private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
 | 
			
		||||
 | 
			
		||||
    private FontRenderer renderer()
 | 
			
		||||
    {
 | 
			
		||||
        return Minecraft.getMinecraft().fontRenderer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public ITextComponent getPadding( ITextComponent component, int width )
 | 
			
		||||
    {
 | 
			
		||||
        int extraWidth = width - getWidth( component );
 | 
			
		||||
        if( extraWidth <= 0 ) return null;
 | 
			
		||||
 | 
			
		||||
        FontRenderer renderer = renderer();
 | 
			
		||||
 | 
			
		||||
        float spaceWidth = renderer.getCharWidth( ' ' );
 | 
			
		||||
        int spaces = MathHelper.floor( extraWidth / spaceWidth );
 | 
			
		||||
        int extra = extraWidth - (int) (spaces * spaceWidth);
 | 
			
		||||
 | 
			
		||||
        return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), TextFormatting.GRAY );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getColumnPadding()
 | 
			
		||||
    {
 | 
			
		||||
        return 3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getWidth( ITextComponent component )
 | 
			
		||||
    {
 | 
			
		||||
        return renderer().getStringWidth( component.getFormattedText() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeLine( int id, ITextComponent component )
 | 
			
		||||
    {
 | 
			
		||||
        Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
        GuiNewChat chat = mc.ingameGUI.getChatGUI();
 | 
			
		||||
 | 
			
		||||
        // Trim the text if it goes over the allowed length
 | 
			
		||||
        int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getChatScale() );
 | 
			
		||||
        List<ITextComponent> list = GuiUtilRenderComponents.splitText( component, maxWidth, mc.fontRenderer, false, false );
 | 
			
		||||
        if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int display( TableBuilder table )
 | 
			
		||||
    {
 | 
			
		||||
        GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
 | 
			
		||||
 | 
			
		||||
        int lastHeight = lastHeights.get( table.getId() );
 | 
			
		||||
 | 
			
		||||
        int height = TableFormatter.super.display( table );
 | 
			
		||||
        lastHeights.put( table.getId(), height );
 | 
			
		||||
 | 
			
		||||
        for( int i = height; i < lastHeight; i++ ) chat.deleteChatLine( i + table.getId() );
 | 
			
		||||
        return height;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/main/java/dan200/computercraft/client/FrameInfo.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main/java/dan200/computercraft/client/FrameInfo.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.Side;
 | 
			
		||||
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
 | 
			
		||||
public final class FrameInfo
 | 
			
		||||
{
 | 
			
		||||
    private static int tick;
 | 
			
		||||
    private static long renderFrame;
 | 
			
		||||
 | 
			
		||||
    private FrameInfo()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean getGlobalCursorBlink()
 | 
			
		||||
    {
 | 
			
		||||
        return (tick / 8) % 2 == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long getRenderFrame()
 | 
			
		||||
    {
 | 
			
		||||
        return renderFrame;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void onTick( TickEvent.ClientTickEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        if( event.phase == TickEvent.Phase.START ) tick++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public static void onRenderTick( TickEvent.RenderTickEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        if( event.phase == TickEvent.Phase.START ) renderFrame++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -8,6 +8,7 @@ package dan200.computercraft.client.gui;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.core.terminal.TextBuffer;
 | 
			
		||||
import dan200.computercraft.shared.util.Palette;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.BufferBuilder;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.renderer.Tessellator;
 | 
			
		||||
@@ -20,22 +21,30 @@ import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
public class FixedWidthFontRenderer
 | 
			
		||||
{
 | 
			
		||||
    private static ResourceLocation font = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
 | 
			
		||||
    public static ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/term_background.png" );
 | 
			
		||||
    private static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
 | 
			
		||||
    public static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/term_background.png" );
 | 
			
		||||
 | 
			
		||||
    public static int FONT_HEIGHT = 9;
 | 
			
		||||
    public static int FONT_WIDTH = 6;
 | 
			
		||||
    public static final int FONT_HEIGHT = 9;
 | 
			
		||||
    public static final int FONT_WIDTH = 6;
 | 
			
		||||
 | 
			
		||||
    private TextureManager m_textureManager;
 | 
			
		||||
    private static FixedWidthFontRenderer instance;
 | 
			
		||||
 | 
			
		||||
    public FixedWidthFontRenderer( TextureManager textureManager )
 | 
			
		||||
    public static FixedWidthFontRenderer instance()
 | 
			
		||||
    {
 | 
			
		||||
        m_textureManager = textureManager;
 | 
			
		||||
        if( instance != null ) return instance;
 | 
			
		||||
        return instance = new FixedWidthFontRenderer();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final TextureManager m_textureManager;
 | 
			
		||||
 | 
			
		||||
    private FixedWidthFontRenderer()
 | 
			
		||||
    {
 | 
			
		||||
        m_textureManager = Minecraft.getMinecraft().getTextureManager();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void greyscaleify( double[] rgb )
 | 
			
		||||
    {
 | 
			
		||||
        Arrays.fill( rgb, ( rgb[0] + rgb[1] + rgb[2] ) / 3.0f );
 | 
			
		||||
        Arrays.fill( rgb, (rgb[0] + rgb[1] + rgb[2]) / 3.0f );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void drawChar( BufferBuilder renderer, double x, double y, int index, int color, Palette p, boolean greyscale )
 | 
			
		||||
@@ -44,13 +53,13 @@ public class FixedWidthFontRenderer
 | 
			
		||||
        int row = index / 16;
 | 
			
		||||
 | 
			
		||||
        double[] colour = p.getColour( 15 - color );
 | 
			
		||||
        if(greyscale)
 | 
			
		||||
        if( greyscale )
 | 
			
		||||
        {
 | 
			
		||||
            greyscaleify( colour );
 | 
			
		||||
        }
 | 
			
		||||
        float r = (float)colour[0];
 | 
			
		||||
        float g = (float)colour[1];
 | 
			
		||||
        float b = (float)colour[2];
 | 
			
		||||
        float r = (float) colour[0];
 | 
			
		||||
        float g = (float) colour[1];
 | 
			
		||||
        float b = (float) colour[2];
 | 
			
		||||
 | 
			
		||||
        int xStart = 1 + column * (FONT_WIDTH + 2);
 | 
			
		||||
        int yStart = 1 + row * (FONT_HEIGHT + 2);
 | 
			
		||||
@@ -66,13 +75,13 @@ public class FixedWidthFontRenderer
 | 
			
		||||
    private void drawQuad( BufferBuilder renderer, double x, double y, int color, double width, Palette p, boolean greyscale )
 | 
			
		||||
    {
 | 
			
		||||
        double[] colour = p.getColour( 15 - color );
 | 
			
		||||
        if(greyscale)
 | 
			
		||||
        if( greyscale )
 | 
			
		||||
        {
 | 
			
		||||
            greyscaleify( colour );
 | 
			
		||||
        }
 | 
			
		||||
        float r = (float)colour[0];
 | 
			
		||||
        float g = (float)colour[1];
 | 
			
		||||
        float b = (float)colour[2];
 | 
			
		||||
        float r = (float) colour[0];
 | 
			
		||||
        float g = (float) colour[1];
 | 
			
		||||
        float b = (float) colour[2];
 | 
			
		||||
 | 
			
		||||
        renderer.pos( x, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
 | 
			
		||||
        renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
 | 
			
		||||
@@ -96,7 +105,7 @@ public class FixedWidthFontRenderer
 | 
			
		||||
        if( leftMarginSize > 0.0 )
 | 
			
		||||
        {
 | 
			
		||||
            int colour1 = "0123456789abcdef".indexOf( backgroundColour.charAt( 0 ) );
 | 
			
		||||
            if( colour1 < 0 || (greyScale && !isGreyScale(colour1)) )
 | 
			
		||||
            if( colour1 < 0 || (greyScale && !isGreyScale( colour1 )) )
 | 
			
		||||
            {
 | 
			
		||||
                colour1 = 15;
 | 
			
		||||
            }
 | 
			
		||||
@@ -105,7 +114,7 @@ public class FixedWidthFontRenderer
 | 
			
		||||
        if( rightMarginSize > 0.0 )
 | 
			
		||||
        {
 | 
			
		||||
            int colour2 = "0123456789abcdef".indexOf( backgroundColour.charAt( backgroundColour.length() - 1 ) );
 | 
			
		||||
            if( colour2 < 0 || (greyScale && !isGreyScale(colour2)) )
 | 
			
		||||
            if( colour2 < 0 || (greyScale && !isGreyScale( colour2 )) )
 | 
			
		||||
            {
 | 
			
		||||
                colour2 = 15;
 | 
			
		||||
            }
 | 
			
		||||
@@ -114,7 +123,7 @@ public class FixedWidthFontRenderer
 | 
			
		||||
        for( int i = 0; i < backgroundColour.length(); i++ )
 | 
			
		||||
        {
 | 
			
		||||
            int colour = "0123456789abcdef".indexOf( backgroundColour.charAt( i ) );
 | 
			
		||||
            if( colour < 0 || ( greyScale && !isGreyScale( colour ) ) )
 | 
			
		||||
            if( colour < 0 || (greyScale && !isGreyScale( colour )) )
 | 
			
		||||
            {
 | 
			
		||||
                colour = 15;
 | 
			
		||||
            }
 | 
			
		||||
@@ -135,7 +144,7 @@ public class FixedWidthFontRenderer
 | 
			
		||||
        {
 | 
			
		||||
            // Switch colour
 | 
			
		||||
            int colour = "0123456789abcdef".indexOf( textColour.charAt( i ) );
 | 
			
		||||
            if( colour < 0 || ( greyScale && !isGreyScale( colour ) ) )
 | 
			
		||||
            if( colour < 0 || (greyScale && !isGreyScale( colour )) )
 | 
			
		||||
            {
 | 
			
		||||
                colour = 0;
 | 
			
		||||
            }
 | 
			
		||||
@@ -157,26 +166,26 @@ public class FixedWidthFontRenderer
 | 
			
		||||
        if( backgroundColour != null )
 | 
			
		||||
        {
 | 
			
		||||
            // Bind the background texture
 | 
			
		||||
            m_textureManager.bindTexture( background );
 | 
			
		||||
            m_textureManager.bindTexture( BACKGROUND );
 | 
			
		||||
 | 
			
		||||
            // Draw the quads
 | 
			
		||||
            drawStringBackgroundPart( x, y, backgroundColour, leftMarginSize, rightMarginSize, greyScale, p );
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
        // Draw text
 | 
			
		||||
        if( s != null && textColour != null )
 | 
			
		||||
        {
 | 
			
		||||
            // Bind the font texture
 | 
			
		||||
            bindFont();
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            // Draw the quads
 | 
			
		||||
            drawStringTextPart( x, y, s, textColour, greyScale, p );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getStringWidth(String s)
 | 
			
		||||
    public int getStringWidth( String s )
 | 
			
		||||
    {
 | 
			
		||||
        if(s == null)
 | 
			
		||||
        if( s == null )
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
@@ -185,7 +194,7 @@ public class FixedWidthFontRenderer
 | 
			
		||||
 | 
			
		||||
    public void bindFont()
 | 
			
		||||
    {
 | 
			
		||||
        m_textureManager.bindTexture( font );
 | 
			
		||||
        m_textureManager.bindTexture( FONT );
 | 
			
		||||
        GlStateManager.glTexParameteri( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -9,6 +9,7 @@ package dan200.computercraft.client.gui;
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
 | 
			
		||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ClientComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.IComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
 | 
			
		||||
@@ -23,17 +24,17 @@ import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public class GuiComputer extends GuiContainer
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/corners.png" );
 | 
			
		||||
    private static final ResourceLocation backgroundAdvanced = new ResourceLocation( "computercraft", "textures/gui/corners_advanced.png" );
 | 
			
		||||
    private static final ResourceLocation backgroundCommand = new ResourceLocation( "computercraft", "textures/gui/corners_command.png" );
 | 
			
		||||
    private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/corners.png" );
 | 
			
		||||
    private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/corners_advanced.png" );
 | 
			
		||||
    private static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( "computercraft", "textures/gui/corners_command.png" );
 | 
			
		||||
 | 
			
		||||
    private final ComputerFamily m_family;
 | 
			
		||||
    private final IComputer m_computer;
 | 
			
		||||
    private final ClientComputer m_computer;
 | 
			
		||||
    private final int m_termWidth;
 | 
			
		||||
    private final int m_termHeight;
 | 
			
		||||
    private WidgetTerminal m_terminal;
 | 
			
		||||
 | 
			
		||||
    public GuiComputer( Container container, ComputerFamily family, IComputer computer, int termWidth, int termHeight )
 | 
			
		||||
    public GuiComputer( Container container, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight )
 | 
			
		||||
    {
 | 
			
		||||
        super( container );
 | 
			
		||||
        m_family = family;
 | 
			
		||||
@@ -43,12 +44,18 @@ public class GuiComputer extends GuiContainer
 | 
			
		||||
        m_terminal = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public GuiComputer( Container container, ComputerFamily family, IComputer computer, int termWidth, int termHeight )
 | 
			
		||||
    {
 | 
			
		||||
        this( container, family, (ClientComputer) computer, termWidth, termHeight );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public GuiComputer( TileComputer computer )
 | 
			
		||||
    {
 | 
			
		||||
        this(
 | 
			
		||||
            new ContainerComputer( computer ),
 | 
			
		||||
            computer.getFamily(),
 | 
			
		||||
            computer.createComputer(),
 | 
			
		||||
            computer.createClientComputer(),
 | 
			
		||||
            ComputerCraft.terminalWidth_computer,
 | 
			
		||||
            ComputerCraft.terminalHeight_computer
 | 
			
		||||
        );
 | 
			
		||||
@@ -87,7 +94,7 @@ public class GuiComputer extends GuiContainer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void keyTyped(char c, int k) throws IOException
 | 
			
		||||
    protected void keyTyped( char c, int k ) throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        if( k == 1 )
 | 
			
		||||
        {
 | 
			
		||||
@@ -95,7 +102,7 @@ public class GuiComputer extends GuiContainer
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if( m_terminal.keyTyped( c, k ) ) keyHandled = true;
 | 
			
		||||
            if( m_terminal.onKeyTyped( c, k ) ) keyHandled = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -123,11 +130,11 @@ public class GuiComputer extends GuiContainer
 | 
			
		||||
    public void handleKeyboardInput() throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        super.handleKeyboardInput();
 | 
			
		||||
        if( m_terminal.handleKeyboardInput() ) keyHandled = true;
 | 
			
		||||
        if( m_terminal.onKeyboardInput() ) keyHandled = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void drawGuiContainerForegroundLayer(int par1, int par2)
 | 
			
		||||
    protected void drawGuiContainerForegroundLayer( int par1, int par2 )
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -148,9 +155,9 @@ public class GuiComputer extends GuiContainer
 | 
			
		||||
        // Draw background
 | 
			
		||||
        drawDefaultBackground();
 | 
			
		||||
 | 
			
		||||
           // Draw terminal
 | 
			
		||||
        // Draw terminal
 | 
			
		||||
        m_terminal.draw( this.mc, startX, startY, mouseX, mouseY );
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // Draw a border around the terminal
 | 
			
		||||
        GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f );
 | 
			
		||||
        switch( m_family )
 | 
			
		||||
@@ -158,30 +165,30 @@ public class GuiComputer extends GuiContainer
 | 
			
		||||
            case Normal:
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                this.mc.getTextureManager().bindTexture( background );
 | 
			
		||||
                this.mc.getTextureManager().bindTexture( BACKGROUND );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case Advanced:
 | 
			
		||||
            {
 | 
			
		||||
                this.mc.getTextureManager().bindTexture( backgroundAdvanced );
 | 
			
		||||
                this.mc.getTextureManager().bindTexture( BACKGROUND_ADVANCED );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case Command:
 | 
			
		||||
            {
 | 
			
		||||
                this.mc.getTextureManager().bindTexture( backgroundCommand );
 | 
			
		||||
                this.mc.getTextureManager().bindTexture( BACKGROUND_COMMAND );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        drawTexturedModalRect(startX - 12, startY - 12, 12, 28, 12, 12);
 | 
			
		||||
        drawTexturedModalRect(startX - 12, endY, 12, 40, 12, 16);
 | 
			
		||||
        drawTexturedModalRect(endX, startY - 12, 24, 28, 12, 12);
 | 
			
		||||
        drawTexturedModalRect(endX, endY, 24, 40, 12, 16);
 | 
			
		||||
        drawTexturedModalRect( startX - 12, startY - 12, 12, 28, 12, 12 );
 | 
			
		||||
        drawTexturedModalRect( startX - 12, endY, 12, 40, 12, 16 );
 | 
			
		||||
        drawTexturedModalRect( endX, startY - 12, 24, 28, 12, 12 );
 | 
			
		||||
        drawTexturedModalRect( endX, endY, 24, 40, 12, 16 );
 | 
			
		||||
 | 
			
		||||
        drawTexturedModalRect(startX, startY-12, 0, 0, endX - startX, 12);
 | 
			
		||||
        drawTexturedModalRect(startX, endY, 0, 12, endX - startX, 16);
 | 
			
		||||
        drawTexturedModalRect( startX, startY - 12, 0, 0, endX - startX, 12 );
 | 
			
		||||
        drawTexturedModalRect( startX, endY, 0, 12, endX - startX, 16 );
 | 
			
		||||
 | 
			
		||||
        drawTexturedModalRect(startX-12, startY, 0, 28, 12, endY - startY);
 | 
			
		||||
        drawTexturedModalRect(endX, startY, 36, 28, 12, endY - startY);
 | 
			
		||||
        drawTexturedModalRect( startX - 12, startY, 0, 28, 12, endY - startY );
 | 
			
		||||
        drawTexturedModalRect( endX, startY, 36, 28, 12, endY - startY );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,34 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.gui;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.shared.Config;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.gui.GuiScreen;
 | 
			
		||||
import net.minecraftforge.common.config.ConfigElement;
 | 
			
		||||
import net.minecraftforge.common.config.Configuration;
 | 
			
		||||
import net.minecraftforge.common.config.Property;
 | 
			
		||||
import net.minecraftforge.fml.client.IModGuiFactory;
 | 
			
		||||
import net.minecraftforge.fml.client.config.GuiConfig;
 | 
			
		||||
import net.minecraftforge.fml.client.config.IConfigElement;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public class GuiConfigCC extends GuiConfig
 | 
			
		||||
{
 | 
			
		||||
    public GuiConfigCC( GuiScreen parentScreen )
 | 
			
		||||
    {
 | 
			
		||||
        super( parentScreen, getConfigElements(), ComputerCraft.MOD_ID, false, false, "CC: Tweaked" );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static List<IConfigElement> getConfigElements()
 | 
			
		||||
    {
 | 
			
		||||
        ArrayList<IConfigElement> elements = new ArrayList<>();
 | 
			
		||||
        for (Property property : ComputerCraft.Config.config.getCategory( Configuration.CATEGORY_GENERAL ).getOrderedValues())
 | 
			
		||||
        {
 | 
			
		||||
            elements.add( new ConfigElement( property ) );
 | 
			
		||||
        }
 | 
			
		||||
        return elements;
 | 
			
		||||
        super( parentScreen, Config.getConfigElements(), ComputerCraft.MOD_ID, false, false, "CC: Tweaked" );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Factory
 | 
			
		||||
 
 | 
			
		||||
@@ -1,54 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.gui;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
 | 
			
		||||
import net.minecraft.client.gui.inventory.GuiContainer;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.resources.I18n;
 | 
			
		||||
import net.minecraft.entity.player.InventoryPlayer;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
 | 
			
		||||
public class GuiDiskDrive extends GuiContainer
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/diskdrive.png" );
 | 
			
		||||
    private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/diskdrive.png" );
 | 
			
		||||
 | 
			
		||||
    private TileDiskDrive m_diskDrive;
 | 
			
		||||
    private final ContainerDiskDrive m_container;
 | 
			
		||||
 | 
			
		||||
    public GuiDiskDrive( InventoryPlayer inventoryplayer, TileDiskDrive diskDrive )
 | 
			
		||||
    public GuiDiskDrive( ContainerDiskDrive container )
 | 
			
		||||
    {
 | 
			
		||||
        super( new ContainerDiskDrive(inventoryplayer, diskDrive) );
 | 
			
		||||
        m_diskDrive = diskDrive;
 | 
			
		||||
        super( container );
 | 
			
		||||
        m_container = container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void drawGuiContainerForegroundLayer(int par1, int par2)
 | 
			
		||||
    protected void drawGuiContainerForegroundLayer( int par1, int par2 )
 | 
			
		||||
    {
 | 
			
		||||
        String title = m_diskDrive.getDisplayName().getUnformattedText();
 | 
			
		||||
        fontRenderer.drawString( title, (xSize - fontRenderer.getStringWidth(title)) / 2, 6, 0x404040 );
 | 
			
		||||
        fontRenderer.drawString( I18n.format("container.inventory"), 8, (ySize - 96) + 2, 0x404040 );
 | 
			
		||||
        String title = m_container.getDiskDrive().getDisplayName().getUnformattedText();
 | 
			
		||||
        fontRenderer.drawString( title, (xSize - fontRenderer.getStringWidth( title )) / 2, 6, 0x404040 );
 | 
			
		||||
        fontRenderer.drawString( I18n.format( "container.inventory" ), 8, (ySize - 96) + 2, 0x404040 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void drawGuiContainerBackgroundLayer(float f, int i, int j)
 | 
			
		||||
    protected void drawGuiContainerBackgroundLayer( float f, int i, int j )
 | 
			
		||||
    {
 | 
			
		||||
        GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
 | 
			
		||||
        this.mc.getTextureManager().bindTexture( background );
 | 
			
		||||
        this.mc.getTextureManager().bindTexture( BACKGROUND );
 | 
			
		||||
        int l = (width - xSize) / 2;
 | 
			
		||||
        int i1 = (height - ySize) / 2;
 | 
			
		||||
        drawTexturedModalRect(l, i1, 0, 0, xSize, ySize);
 | 
			
		||||
        drawTexturedModalRect( l, i1, 0, 0, xSize, ySize );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void drawScreen( int mouseX, int mouseY, float partialTicks)
 | 
			
		||||
    public void drawScreen( int mouseX, int mouseY, float partialTicks )
 | 
			
		||||
    {
 | 
			
		||||
        drawDefaultBackground();
 | 
			
		||||
        super.drawScreen(mouseX, mouseY, partialTicks);
 | 
			
		||||
        renderHoveredToolTip(mouseX, mouseY);
 | 
			
		||||
        super.drawScreen( mouseX, mouseY, partialTicks );
 | 
			
		||||
        renderHoveredToolTip( mouseX, mouseY );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,62 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.gui;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
 | 
			
		||||
import net.minecraft.client.gui.inventory.GuiContainer;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.resources.I18n;
 | 
			
		||||
import net.minecraft.entity.player.InventoryPlayer;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
 | 
			
		||||
public class GuiPrinter extends GuiContainer
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/printer.png" );
 | 
			
		||||
    
 | 
			
		||||
    private TilePrinter m_printer;
 | 
			
		||||
    private ContainerPrinter m_container;
 | 
			
		||||
    private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printer.png" );
 | 
			
		||||
 | 
			
		||||
    public GuiPrinter(InventoryPlayer inventoryplayer, TilePrinter printer)
 | 
			
		||||
    private final ContainerPrinter m_container;
 | 
			
		||||
 | 
			
		||||
    public GuiPrinter( ContainerPrinter container )
 | 
			
		||||
    {
 | 
			
		||||
        super(new ContainerPrinter(inventoryplayer, printer));
 | 
			
		||||
        m_printer = printer;
 | 
			
		||||
        m_container = (ContainerPrinter)inventorySlots;
 | 
			
		||||
        super( container );
 | 
			
		||||
        m_container = container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void drawGuiContainerForegroundLayer(int par1, int par2)
 | 
			
		||||
    protected void drawGuiContainerForegroundLayer( int par1, int par2 )
 | 
			
		||||
    {
 | 
			
		||||
        String title = m_printer.getDisplayName().getUnformattedText();
 | 
			
		||||
        fontRenderer.drawString( title, (xSize - fontRenderer.getStringWidth(title)) / 2, 6, 0x404040 );
 | 
			
		||||
        fontRenderer.drawString( I18n.format("container.inventory"), 8, (ySize - 96) + 2, 0x404040 );
 | 
			
		||||
        String title = m_container.getPrinter().getDisplayName().getUnformattedText();
 | 
			
		||||
        fontRenderer.drawString( title, (xSize - fontRenderer.getStringWidth( title )) / 2, 6, 0x404040 );
 | 
			
		||||
        fontRenderer.drawString( I18n.format( "container.inventory" ), 8, (ySize - 96) + 2, 0x404040 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void drawGuiContainerBackgroundLayer(float f, int i, int j)
 | 
			
		||||
    protected void drawGuiContainerBackgroundLayer( float f, int i, int j )
 | 
			
		||||
    {
 | 
			
		||||
        GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
 | 
			
		||||
        this.mc.getTextureManager().bindTexture( background );
 | 
			
		||||
        this.mc.getTextureManager().bindTexture( BACKGROUND );
 | 
			
		||||
        int startX = (width - xSize) / 2;
 | 
			
		||||
        int startY = (height - ySize) / 2;
 | 
			
		||||
        drawTexturedModalRect(startX, startY, 0, 0, xSize, ySize);
 | 
			
		||||
        
 | 
			
		||||
        drawTexturedModalRect( startX, startY, 0, 0, xSize, ySize );
 | 
			
		||||
 | 
			
		||||
        boolean printing = m_container.isPrinting();
 | 
			
		||||
        if( printing )
 | 
			
		||||
        {
 | 
			
		||||
            drawTexturedModalRect(startX + 34, startY + 21, 176, 0, 25, 45);
 | 
			
		||||
            drawTexturedModalRect( startX + 34, startY + 21, 176, 0, 25, 45 );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void drawScreen( int mouseX, int mouseY, float partialTicks)
 | 
			
		||||
    public void drawScreen( int mouseX, int mouseY, float partialTicks )
 | 
			
		||||
    {
 | 
			
		||||
        drawDefaultBackground();
 | 
			
		||||
        super.drawScreen(mouseX, mouseY, partialTicks);
 | 
			
		||||
        renderHoveredToolTip(mouseX, mouseY);
 | 
			
		||||
        super.drawScreen( mouseX, mouseY, partialTicks );
 | 
			
		||||
        renderHoveredToolTip( mouseX, mouseY );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -30,42 +30,24 @@ public class GuiPrintout extends GuiContainer
 | 
			
		||||
        super( container );
 | 
			
		||||
 | 
			
		||||
        String[] text = ItemPrintout.getText( container.getStack() );
 | 
			
		||||
        m_text = new TextBuffer[ text.length ];
 | 
			
		||||
        for( int i = 0; i < m_text.length; ++i ) m_text[ i ] = new TextBuffer( text[ i ] );
 | 
			
		||||
        m_text = new TextBuffer[text.length];
 | 
			
		||||
        for( int i = 0; i < m_text.length; i++ ) m_text[i] = new TextBuffer( text[i] );
 | 
			
		||||
 | 
			
		||||
        String[] colours = ItemPrintout.getColours( container.getStack() );
 | 
			
		||||
        m_colours = new TextBuffer[ colours.length ];
 | 
			
		||||
        for( int i = 0; i < m_colours.length; ++i ) m_colours[ i ] = new TextBuffer( colours[ i ] );
 | 
			
		||||
        m_colours = new TextBuffer[colours.length];
 | 
			
		||||
        for( int i = 0; i < m_colours.length; i++ ) m_colours[i] = new TextBuffer( colours[i] );
 | 
			
		||||
 | 
			
		||||
        m_page = 0;
 | 
			
		||||
        m_pages = Math.max( m_text.length / ItemPrintout.LINES_PER_PAGE, 1 );
 | 
			
		||||
        m_book = ItemPrintout.getType( container.getStack() ) == ItemPrintout.Type.Book;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void initGui()
 | 
			
		||||
    {
 | 
			
		||||
        super.initGui();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onGuiClosed()
 | 
			
		||||
    {
 | 
			
		||||
        super.onGuiClosed();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean doesGuiPauseGame()
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateScreen()
 | 
			
		||||
    {
 | 
			
		||||
        super.updateScreen();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void keyTyped( char c, int k ) throws IOException
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,21 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.gui;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.turtle.ITurtleAccess;
 | 
			
		||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ClientComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.IComputer;
 | 
			
		||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
 | 
			
		||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.gui.inventory.GuiContainer;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.entity.player.InventoryPlayer;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import org.lwjgl.input.Keyboard;
 | 
			
		||||
import org.lwjgl.input.Mouse;
 | 
			
		||||
 | 
			
		||||
@@ -26,32 +23,23 @@ import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public class GuiTurtle extends GuiContainer
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/turtle.png" );
 | 
			
		||||
    private static final ResourceLocation backgroundAdvanced = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.png" );
 | 
			
		||||
    
 | 
			
		||||
    protected World m_world;
 | 
			
		||||
    protected ContainerTurtle m_container;
 | 
			
		||||
    private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/turtle.png" );
 | 
			
		||||
    private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.png" );
 | 
			
		||||
 | 
			
		||||
    protected final ComputerFamily m_family;
 | 
			
		||||
    protected final ITurtleAccess m_turtle;
 | 
			
		||||
    protected final IComputer m_computer;
 | 
			
		||||
    protected WidgetTerminal m_terminalGui;
 | 
			
		||||
    
 | 
			
		||||
    public GuiTurtle( World world, InventoryPlayer inventoryplayer, TileTurtle turtle )
 | 
			
		||||
    {
 | 
			
		||||
        this( world, turtle, new ContainerTurtle( inventoryplayer, turtle.getAccess() ) );
 | 
			
		||||
    }
 | 
			
		||||
    private ContainerTurtle m_container;
 | 
			
		||||
 | 
			
		||||
    protected GuiTurtle( World world, TileTurtle turtle, ContainerTurtle container )
 | 
			
		||||
    private final ComputerFamily m_family;
 | 
			
		||||
    private final ClientComputer m_computer;
 | 
			
		||||
    private WidgetTerminal m_terminalGui;
 | 
			
		||||
 | 
			
		||||
    public GuiTurtle( TileTurtle turtle, ContainerTurtle container )
 | 
			
		||||
    {
 | 
			
		||||
        super( container );
 | 
			
		||||
 | 
			
		||||
        m_world = world;
 | 
			
		||||
        m_container = container;
 | 
			
		||||
        m_family = turtle.getFamily();
 | 
			
		||||
        m_turtle = turtle.getAccess();
 | 
			
		||||
        m_computer = turtle.createComputer();
 | 
			
		||||
        
 | 
			
		||||
        m_computer = turtle.getClientComputer();
 | 
			
		||||
 | 
			
		||||
        xSize = 254;
 | 
			
		||||
        ySize = 217;
 | 
			
		||||
    }
 | 
			
		||||
@@ -60,10 +48,10 @@ public class GuiTurtle extends GuiContainer
 | 
			
		||||
    public void initGui()
 | 
			
		||||
    {
 | 
			
		||||
        super.initGui();
 | 
			
		||||
        Keyboard.enableRepeatEvents(true);
 | 
			
		||||
        Keyboard.enableRepeatEvents( true );
 | 
			
		||||
        m_terminalGui = new WidgetTerminal(
 | 
			
		||||
            ( width - xSize ) / 2 + 8,
 | 
			
		||||
            ( height - ySize ) / 2 + 8,
 | 
			
		||||
            (width - xSize) / 2 + 8,
 | 
			
		||||
            (height - ySize) / 2 + 8,
 | 
			
		||||
            ComputerCraft.terminalWidth_turtle,
 | 
			
		||||
            ComputerCraft.terminalHeight_turtle,
 | 
			
		||||
            () -> m_computer,
 | 
			
		||||
@@ -76,7 +64,7 @@ public class GuiTurtle extends GuiContainer
 | 
			
		||||
    public void onGuiClosed()
 | 
			
		||||
    {
 | 
			
		||||
        super.onGuiClosed();
 | 
			
		||||
        Keyboard.enableRepeatEvents(false);
 | 
			
		||||
        Keyboard.enableRepeatEvents( false );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -87,7 +75,7 @@ public class GuiTurtle extends GuiContainer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void keyTyped(char c, int k) throws IOException
 | 
			
		||||
    protected void keyTyped( char c, int k ) throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        if( k == 1 )
 | 
			
		||||
        {
 | 
			
		||||
@@ -95,17 +83,17 @@ public class GuiTurtle extends GuiContainer
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if( m_terminalGui.keyTyped( c, k ) ) keyHandled = true;
 | 
			
		||||
            if( m_terminalGui.onKeyTyped( c, k ) ) keyHandled = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void mouseClicked(int x, int y, int button) throws IOException
 | 
			
		||||
    protected void mouseClicked( int x, int y, int button ) throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        super.mouseClicked( x, y, button );
 | 
			
		||||
        m_terminalGui.mouseClicked( x, y, button );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleMouseInput() throws IOException
 | 
			
		||||
    {
 | 
			
		||||
@@ -119,23 +107,23 @@ public class GuiTurtle extends GuiContainer
 | 
			
		||||
    public void handleKeyboardInput() throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        super.handleKeyboardInput();
 | 
			
		||||
        if( m_terminalGui.handleKeyboardInput() ) keyHandled = true;
 | 
			
		||||
        if( m_terminalGui.onKeyboardInput() ) keyHandled = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void drawSelectionSlot( boolean advanced )
 | 
			
		||||
    {
 | 
			
		||||
        int x = (width - xSize) / 2;
 | 
			
		||||
        int y = (height - ySize) / 2;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // Draw selection slot
 | 
			
		||||
        int slot = m_container.getSelectedSlot();
 | 
			
		||||
        if( slot >= 0 )
 | 
			
		||||
        {
 | 
			
		||||
            GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
 | 
			
		||||
            int slotX = (slot%4);
 | 
			
		||||
            int slotY = (slot/4);
 | 
			
		||||
            this.mc.getTextureManager().bindTexture( advanced ? backgroundAdvanced : background );
 | 
			
		||||
            drawTexturedModalRect(x + m_container.m_turtleInvStartX - 2 + slotX * 18, y + m_container.m_playerInvStartY - 2 + slotY * 18, 0, 217, 24, 24);
 | 
			
		||||
            int slotX = (slot % 4);
 | 
			
		||||
            int slotY = (slot / 4);
 | 
			
		||||
            this.mc.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND );
 | 
			
		||||
            drawTexturedModalRect( x + m_container.m_turtleInvStartX - 2 + slotX * 18, y + m_container.m_playerInvStartY - 2 + slotY * 18, 0, 217, 24, 24 );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -145,22 +133,22 @@ public class GuiTurtle extends GuiContainer
 | 
			
		||||
        // Draw term
 | 
			
		||||
        boolean advanced = (m_family == ComputerFamily.Advanced);
 | 
			
		||||
        m_terminalGui.draw( Minecraft.getMinecraft(), 0, 0, mouseX, mouseY );
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // Draw border/inventory
 | 
			
		||||
        GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
 | 
			
		||||
        this.mc.getTextureManager().bindTexture( advanced ? backgroundAdvanced : background );
 | 
			
		||||
        this.mc.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND );
 | 
			
		||||
        int x = (width - xSize) / 2;
 | 
			
		||||
        int y = (height - ySize) / 2;
 | 
			
		||||
        drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
 | 
			
		||||
        
 | 
			
		||||
        drawTexturedModalRect( x, y, 0, 0, xSize, ySize );
 | 
			
		||||
 | 
			
		||||
        drawSelectionSlot( advanced );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void drawScreen( int mouseX, int mouseY, float partialTicks)
 | 
			
		||||
    public void drawScreen( int mouseX, int mouseY, float partialTicks )
 | 
			
		||||
    {
 | 
			
		||||
        drawDefaultBackground();
 | 
			
		||||
        super.drawScreen(mouseX, mouseY, partialTicks);
 | 
			
		||||
        renderHoveredToolTip(mouseX, mouseY);
 | 
			
		||||
        super.drawScreen( mouseX, mouseY, partialTicks );
 | 
			
		||||
        renderHoveredToolTip( mouseX, mouseY );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,13 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.gui.widgets;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.audio.PositionedSoundRecord;
 | 
			
		||||
import net.minecraft.client.gui.FontRenderer;
 | 
			
		||||
import net.minecraft.client.gui.Gui;
 | 
			
		||||
import net.minecraft.client.renderer.*;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
 | 
			
		||||
import net.minecraft.init.SoundEvents;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import org.lwjgl.opengl.GL11;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public abstract class Widget extends Gui
 | 
			
		||||
{
 | 
			
		||||
@@ -65,17 +56,29 @@ public abstract class Widget extends Gui
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean handleKeyboardInput()
 | 
			
		||||
    public boolean onKeyboardInput()
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public void handleKeyboardInput()
 | 
			
		||||
    {
 | 
			
		||||
        onKeyboardInput();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void mouseClicked( int mouseX, int mouseY, int mouseButton )
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean keyTyped( char c, int k )
 | 
			
		||||
    public boolean onKeyTyped( char c, int k )
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public void keyTyped( char c, int k )
 | 
			
		||||
    {
 | 
			
		||||
        onKeyTyped( c, k );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.gui.widgets;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.FrameInfo;
 | 
			
		||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
 | 
			
		||||
import dan200.computercraft.core.terminal.Terminal;
 | 
			
		||||
import dan200.computercraft.core.terminal.TextBuffer;
 | 
			
		||||
@@ -18,15 +18,15 @@ import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.gui.GuiScreen;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.util.ChatAllowedCharacters;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import org.lwjgl.input.Keyboard;
 | 
			
		||||
import org.lwjgl.input.Mouse;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.BACKGROUND;
 | 
			
		||||
 | 
			
		||||
public class WidgetTerminal extends Widget
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/term_background.png" );
 | 
			
		||||
    private static final float TERMINATE_TIME = 0.5f;
 | 
			
		||||
 | 
			
		||||
    private final IComputerContainer m_computer;
 | 
			
		||||
@@ -84,7 +84,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean keyTyped( char ch, int key )
 | 
			
		||||
    public boolean onKeyTyped( char ch, int key )
 | 
			
		||||
    {
 | 
			
		||||
        if( m_focus )
 | 
			
		||||
        {
 | 
			
		||||
@@ -122,8 +122,8 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        // Queue the "paste" event
 | 
			
		||||
                        queueEvent( "paste", new Object[]{
 | 
			
		||||
                                clipboard
 | 
			
		||||
                        queueEvent( "paste", new Object[] {
 | 
			
		||||
                            clipboard
 | 
			
		||||
                        } );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -143,7 +143,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Queue the "key" event
 | 
			
		||||
                    queueEvent( "key", new Object[]{
 | 
			
		||||
                    queueEvent( "key", new Object[] {
 | 
			
		||||
                        key, repeat
 | 
			
		||||
                    } );
 | 
			
		||||
                    handled = true;
 | 
			
		||||
@@ -152,7 +152,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                if( (ch >= 32 && ch <= 126) || (ch >= 160 && ch <= 255) ) // printable chars in byte range
 | 
			
		||||
                {
 | 
			
		||||
                    // Queue the "char" event
 | 
			
		||||
                    queueEvent( "char", new Object[]{
 | 
			
		||||
                    queueEvent( "char", new Object[] {
 | 
			
		||||
                        Character.toString( ch )
 | 
			
		||||
                    } );
 | 
			
		||||
                    handled = true;
 | 
			
		||||
@@ -161,7 +161,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                return handled;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -171,7 +171,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
        if( mouseX >= getXPosition() && mouseX < getXPosition() + getWidth() &&
 | 
			
		||||
            mouseY >= getYPosition() && mouseY < getYPosition() + getHeight() )
 | 
			
		||||
        {
 | 
			
		||||
            if( !m_focus && button == 0)
 | 
			
		||||
            if( !m_focus && button == 0 )
 | 
			
		||||
            {
 | 
			
		||||
                m_focus = true;
 | 
			
		||||
            }
 | 
			
		||||
@@ -184,12 +184,12 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                    Terminal term = computer.getTerminal();
 | 
			
		||||
                    if( term != null )
 | 
			
		||||
                    {
 | 
			
		||||
                        int charX = ( mouseX - ( getXPosition() + m_leftMargin ) ) / FixedWidthFontRenderer.FONT_WIDTH;
 | 
			
		||||
                        int charY = ( mouseY - ( getYPosition() + m_topMargin ) ) / FixedWidthFontRenderer.FONT_HEIGHT;
 | 
			
		||||
                        int charX = (mouseX - (getXPosition() + m_leftMargin)) / FixedWidthFontRenderer.FONT_WIDTH;
 | 
			
		||||
                        int charY = (mouseY - (getYPosition() + m_topMargin)) / FixedWidthFontRenderer.FONT_HEIGHT;
 | 
			
		||||
                        charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
 | 
			
		||||
                        charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
 | 
			
		||||
 | 
			
		||||
                        computer.queueEvent( "mouse_click", new Object[]{
 | 
			
		||||
                        computer.queueEvent( "mouse_click", new Object[] {
 | 
			
		||||
                            button + 1, charX + 1, charY + 1
 | 
			
		||||
                        } );
 | 
			
		||||
 | 
			
		||||
@@ -210,7 +210,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean handleKeyboardInput()
 | 
			
		||||
    public boolean onKeyboardInput()
 | 
			
		||||
    {
 | 
			
		||||
        boolean handled = false;
 | 
			
		||||
        for( int i = m_keysDown.size() - 1; i >= 0; --i )
 | 
			
		||||
@@ -222,7 +222,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                if( m_focus )
 | 
			
		||||
                {
 | 
			
		||||
                    // Queue the "key_up" event
 | 
			
		||||
                    queueEvent( "key_up", new Object[]{
 | 
			
		||||
                    queueEvent( "key_up", new Object[] {
 | 
			
		||||
                        key
 | 
			
		||||
                    } );
 | 
			
		||||
                    handled = true;
 | 
			
		||||
@@ -244,8 +244,8 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
            Terminal term = computer.getTerminal();
 | 
			
		||||
            if( term != null )
 | 
			
		||||
            {
 | 
			
		||||
                int charX = ( mouseX - (getXPosition() + m_leftMargin)) / FixedWidthFontRenderer.FONT_WIDTH;
 | 
			
		||||
                int charY = ( mouseY - (getYPosition() + m_topMargin)) / FixedWidthFontRenderer.FONT_HEIGHT;
 | 
			
		||||
                int charX = (mouseX - (getXPosition() + m_leftMargin)) / FixedWidthFontRenderer.FONT_WIDTH;
 | 
			
		||||
                int charY = (mouseY - (getYPosition() + m_topMargin)) / FixedWidthFontRenderer.FONT_HEIGHT;
 | 
			
		||||
                charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
 | 
			
		||||
                charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
 | 
			
		||||
 | 
			
		||||
@@ -253,7 +253,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                {
 | 
			
		||||
                    if( m_focus )
 | 
			
		||||
                    {
 | 
			
		||||
                        computer.queueEvent( "mouse_up", new Object[]{
 | 
			
		||||
                        computer.queueEvent( "mouse_up", new Object[] {
 | 
			
		||||
                            m_lastClickButton + 1, charX + 1, charY + 1
 | 
			
		||||
                        } );
 | 
			
		||||
                    }
 | 
			
		||||
@@ -270,20 +270,20 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                {
 | 
			
		||||
                    if( wheelChange < 0 )
 | 
			
		||||
                    {
 | 
			
		||||
                        computer.queueEvent( "mouse_scroll", new Object[]{
 | 
			
		||||
                                1, charX + 1, charY + 1
 | 
			
		||||
                        computer.queueEvent( "mouse_scroll", new Object[] {
 | 
			
		||||
                            1, charX + 1, charY + 1
 | 
			
		||||
                        } );
 | 
			
		||||
                    }
 | 
			
		||||
                    else if( wheelChange > 0 )
 | 
			
		||||
                    {
 | 
			
		||||
                        computer.queueEvent( "mouse_scroll", new Object[]{
 | 
			
		||||
                                -1, charX + 1, charY + 1
 | 
			
		||||
                        computer.queueEvent( "mouse_scroll", new Object[] {
 | 
			
		||||
                            -1, charX + 1, charY + 1
 | 
			
		||||
                        } );
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if( m_lastClickButton >= 0 && ( charX != m_lastClickX || charY != m_lastClickY ) )
 | 
			
		||||
                    if( m_lastClickButton >= 0 && (charX != m_lastClickX || charY != m_lastClickY) )
 | 
			
		||||
                    {
 | 
			
		||||
                        computer.queueEvent( "mouse_drag", new Object[]{
 | 
			
		||||
                        computer.queueEvent( "mouse_drag", new Object[] {
 | 
			
		||||
                            m_lastClickButton + 1, charX + 1, charY + 1
 | 
			
		||||
                        } );
 | 
			
		||||
                        m_lastClickX = charX;
 | 
			
		||||
@@ -296,10 +296,10 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update()
 | 
			
		||||
    {                
 | 
			
		||||
    {
 | 
			
		||||
        // Handle special keys
 | 
			
		||||
        if( m_focus && (Keyboard.isKeyDown( 29 ) || Keyboard.isKeyDown( 157 )) )
 | 
			
		||||
        {            
 | 
			
		||||
        {
 | 
			
		||||
            // Ctrl+T for terminate
 | 
			
		||||
            if( Keyboard.isKeyDown( 20 ) )
 | 
			
		||||
            {
 | 
			
		||||
@@ -316,9 +316,9 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
            {
 | 
			
		||||
                m_terminateTimer = 0.0f;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            // Ctrl+R for reboot
 | 
			
		||||
            if( Keyboard.isKeyDown(19) )
 | 
			
		||||
            if( Keyboard.isKeyDown( 19 ) )
 | 
			
		||||
            {
 | 
			
		||||
                if( m_rebootTimer < TERMINATE_TIME )
 | 
			
		||||
                {
 | 
			
		||||
@@ -339,7 +339,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Ctrl+S for shutdown
 | 
			
		||||
            if( Keyboard.isKeyDown(31) )
 | 
			
		||||
            if( Keyboard.isKeyDown( 31 ) )
 | 
			
		||||
            {
 | 
			
		||||
                if( m_shutdownTimer < TERMINATE_TIME )
 | 
			
		||||
                {
 | 
			
		||||
@@ -377,7 +377,7 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
        {
 | 
			
		||||
            // Draw the screen contents
 | 
			
		||||
            IComputer computer = m_computer.getComputer();
 | 
			
		||||
            Terminal terminal = ( computer != null ) ? computer.getTerminal() : null;
 | 
			
		||||
            Terminal terminal = (computer != null) ? computer.getTerminal() : null;
 | 
			
		||||
            if( terminal != null )
 | 
			
		||||
            {
 | 
			
		||||
                // Draw the terminal
 | 
			
		||||
@@ -387,8 +387,8 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
 | 
			
		||||
                // Get the data from the terminal first
 | 
			
		||||
                // Unfortunately we have to keep the lock for the whole of drawing, so the text doesn't change under us.
 | 
			
		||||
                FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
 | 
			
		||||
                boolean tblink = m_focus && terminal.getCursorBlink() && ComputerCraft.getGlobalCursorBlink();
 | 
			
		||||
                FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance();
 | 
			
		||||
                boolean tblink = m_focus && terminal.getCursorBlink() && FrameInfo.getGlobalCursorBlink();
 | 
			
		||||
                int tw = terminal.getWidth();
 | 
			
		||||
                int th = terminal.getHeight();
 | 
			
		||||
                int tx = terminal.getCursorX();
 | 
			
		||||
@@ -405,11 +405,11 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                }
 | 
			
		||||
                if( m_bottomMargin > 0 )
 | 
			
		||||
                {
 | 
			
		||||
                    fontRenderer.drawString( emptyLine, x, startY + 2 * m_bottomMargin + ( th - 1 ) * FixedWidthFontRenderer.FONT_HEIGHT, terminal.getTextColourLine( th - 1 ), terminal.getBackgroundColourLine( th - 1 ), m_leftMargin, m_rightMargin, greyscale, palette );
 | 
			
		||||
                    fontRenderer.drawString( emptyLine, x, startY + 2 * m_bottomMargin + (th - 1) * FixedWidthFontRenderer.FONT_HEIGHT, terminal.getTextColourLine( th - 1 ), terminal.getBackgroundColourLine( th - 1 ), m_leftMargin, m_rightMargin, greyscale, palette );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Draw lines
 | 
			
		||||
                for( int line = 0; line < th; ++line )
 | 
			
		||||
                for( int line = 0; line < th; line++ )
 | 
			
		||||
                {
 | 
			
		||||
                    TextBuffer text = terminal.getLine( line );
 | 
			
		||||
                    TextBuffer colour = terminal.getTextColourLine( line );
 | 
			
		||||
@@ -424,25 +424,27 @@ public class WidgetTerminal extends Widget
 | 
			
		||||
                    TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 );
 | 
			
		||||
 | 
			
		||||
                    fontRenderer.drawString(
 | 
			
		||||
                            cursor,
 | 
			
		||||
                            x + FixedWidthFontRenderer.FONT_WIDTH * tx,
 | 
			
		||||
                            startY + m_topMargin + FixedWidthFontRenderer.FONT_HEIGHT * ty,
 | 
			
		||||
                            cursorColour, null,
 | 
			
		||||
                            0, 0,
 | 
			
		||||
                            greyscale,
 | 
			
		||||
                            palette
 | 
			
		||||
                        cursor,
 | 
			
		||||
                        x + FixedWidthFontRenderer.FONT_WIDTH * tx,
 | 
			
		||||
                        startY + m_topMargin + FixedWidthFontRenderer.FONT_HEIGHT * ty,
 | 
			
		||||
                        cursorColour, null,
 | 
			
		||||
                        0, 0,
 | 
			
		||||
                        greyscale,
 | 
			
		||||
                        palette
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            } else
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // Draw a black background
 | 
			
		||||
                mc.getTextureManager().bindTexture( background );
 | 
			
		||||
                mc.getTextureManager().bindTexture( BACKGROUND );
 | 
			
		||||
                Colour black = Colour.Black;
 | 
			
		||||
                GlStateManager.color( black.getR(), black.getG(), black.getB(), 1.0f );
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    drawTexturedModalRect( startX, startY, 0, 0, getWidth(), getHeight() );
 | 
			
		||||
                } finally
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f );
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,225 +1,24 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.proxy;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
 | 
			
		||||
import dan200.computercraft.client.render.TurtleSmartItemModel;
 | 
			
		||||
import dan200.computercraft.shared.proxy.CCTurtleProxyCommon;
 | 
			
		||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
 | 
			
		||||
import dan200.computercraft.shared.turtle.core.TurtleBrain;
 | 
			
		||||
import dan200.computercraft.shared.turtle.items.ItemTurtleBase;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.ItemMeshDefinition;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelBakery;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
 | 
			
		||||
import net.minecraft.client.renderer.color.IItemColor;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureMap;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
 | 
			
		||||
import net.minecraft.client.resources.IResourceManager;
 | 
			
		||||
import net.minecraft.client.resources.SimpleReloadableResourceManager;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraftforge.client.event.ModelBakeEvent;
 | 
			
		||||
import net.minecraftforge.client.event.ModelRegistryEvent;
 | 
			
		||||
import net.minecraftforge.client.event.TextureStitchEvent;
 | 
			
		||||
import net.minecraftforge.client.model.IModel;
 | 
			
		||||
import net.minecraftforge.client.model.ModelLoader;
 | 
			
		||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
 | 
			
		||||
import net.minecraftforge.common.MinecraftForge;
 | 
			
		||||
import net.minecraftforge.fml.client.registry.ClientRegistry;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public class CCTurtleProxyClient extends CCTurtleProxyCommon
 | 
			
		||||
{
 | 
			
		||||
    // IComputerCraftProxy implementation
 | 
			
		||||
    
 | 
			
		||||
    @Override        
 | 
			
		||||
    public void preInit()
 | 
			
		||||
    {    
 | 
			
		||||
        super.preInit();
 | 
			
		||||
 | 
			
		||||
        // Setup client forge handlers
 | 
			
		||||
        registerForgeHandlers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public void registerModels( ModelRegistryEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        // Register item models
 | 
			
		||||
        ItemMeshDefinition turtleMeshDefinition = new ItemMeshDefinition()
 | 
			
		||||
        {
 | 
			
		||||
            private ModelResourceLocation turtle_dynamic = new ModelResourceLocation( "computercraft:turtle_dynamic", "inventory" );
 | 
			
		||||
 | 
			
		||||
            @Nonnull
 | 
			
		||||
            @Override
 | 
			
		||||
            public ModelResourceLocation getModelLocation( @Nonnull ItemStack stack )
 | 
			
		||||
            {
 | 
			
		||||
                return turtle_dynamic;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        String[] turtleModelNames = new String[] {
 | 
			
		||||
            "turtle_dynamic",
 | 
			
		||||
            "turtle", "turtle_advanced",
 | 
			
		||||
            "turtle_white",
 | 
			
		||||
            "turtle_elf_overlay"
 | 
			
		||||
        };
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.turtle, turtleMeshDefinition, turtleModelNames );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.turtleExpanded, turtleMeshDefinition, turtleModelNames );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.turtleAdvanced, turtleMeshDefinition, turtleModelNames );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void init()
 | 
			
		||||
    {
 | 
			
		||||
        super.init();
 | 
			
		||||
 | 
			
		||||
        // Setup turtle colours
 | 
			
		||||
        Minecraft.getMinecraft().getItemColors().registerItemColorHandler(
 | 
			
		||||
            new TurtleItemColour(),
 | 
			
		||||
            ComputerCraft.Blocks.turtle, ComputerCraft.Blocks.turtleExpanded, ComputerCraft.Blocks.turtleAdvanced
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Setup renderers
 | 
			
		||||
        ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Block block, ItemMeshDefinition definition, String[] names )
 | 
			
		||||
    {
 | 
			
		||||
        registerItemModel( Item.getItemFromBlock( block ), definition, names );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Item item, ItemMeshDefinition definition, String[] names )
 | 
			
		||||
    {
 | 
			
		||||
        ResourceLocation[] resources = new ResourceLocation[names.length];
 | 
			
		||||
        for( int i=0; i<names.length; ++i )
 | 
			
		||||
        {
 | 
			
		||||
            resources[i] = new ResourceLocation( "computercraft:" + names[i] );
 | 
			
		||||
        }
 | 
			
		||||
        ModelBakery.registerItemVariants( item, resources );
 | 
			
		||||
        ModelLoader.setCustomMeshDefinition( item, definition );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerForgeHandlers()
 | 
			
		||||
    {
 | 
			
		||||
        ForgeHandlers handlers = new ForgeHandlers();
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( handlers );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ForgeHandlers
 | 
			
		||||
    {
 | 
			
		||||
        private static final String[] TURTLE_UPGRADES = {
 | 
			
		||||
            "turtle_modem_off_left",
 | 
			
		||||
            "turtle_modem_on_left",
 | 
			
		||||
            "turtle_modem_off_right",
 | 
			
		||||
            "turtle_modem_on_right",
 | 
			
		||||
            "turtle_crafting_table_left",
 | 
			
		||||
            "turtle_crafting_table_right",
 | 
			
		||||
            "advanced_turtle_modem_off_left",
 | 
			
		||||
            "advanced_turtle_modem_on_left",
 | 
			
		||||
            "advanced_turtle_modem_off_right",
 | 
			
		||||
            "advanced_turtle_modem_on_right",
 | 
			
		||||
            "turtle_speaker_upgrade_left",
 | 
			
		||||
            "turtle_speaker_upgrade_right",
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        private TurtleSmartItemModel m_turtleSmartItemModel;
 | 
			
		||||
 | 
			
		||||
        public ForgeHandlers()
 | 
			
		||||
        {
 | 
			
		||||
            m_turtleSmartItemModel = new TurtleSmartItemModel();
 | 
			
		||||
            IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
 | 
			
		||||
            if( resourceManager instanceof SimpleReloadableResourceManager )
 | 
			
		||||
            {
 | 
			
		||||
                SimpleReloadableResourceManager reloadableResourceManager = (SimpleReloadableResourceManager)resourceManager;
 | 
			
		||||
                reloadableResourceManager.registerReloadListener( m_turtleSmartItemModel );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onTick( TickEvent.ClientTickEvent event )
 | 
			
		||||
        {
 | 
			
		||||
            if( event.phase == TickEvent.Phase.END )
 | 
			
		||||
            {
 | 
			
		||||
                TurtleBrain.cleanupBrains();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onTextureStitchEvent( TextureStitchEvent.Pre event )
 | 
			
		||||
        {
 | 
			
		||||
            // Load all textures for upgrades
 | 
			
		||||
            TextureMap map = event.getMap();
 | 
			
		||||
            for( String upgrade : TURTLE_UPGRADES )
 | 
			
		||||
            {
 | 
			
		||||
                IModel model = ModelLoaderRegistry.getModelOrMissing( new ResourceLocation( "computercraft", "block/" + upgrade ) );
 | 
			
		||||
                for( ResourceLocation texture : model.getTextures() )
 | 
			
		||||
                {
 | 
			
		||||
                    map.registerSprite( texture );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onModelBakeEvent( ModelBakeEvent event )
 | 
			
		||||
        {
 | 
			
		||||
            // Load all upgrade models
 | 
			
		||||
            for( String upgrade : TURTLE_UPGRADES )
 | 
			
		||||
            {
 | 
			
		||||
                loadModel( event, upgrade );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            loadSmartModel( event, "turtle_dynamic", m_turtleSmartItemModel );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void loadModel( ModelBakeEvent event, String name )
 | 
			
		||||
        {
 | 
			
		||||
            IModel model = ModelLoaderRegistry.getModelOrMissing(
 | 
			
		||||
                new ResourceLocation( "computercraft", "block/" + name )
 | 
			
		||||
            );
 | 
			
		||||
            IBakedModel bakedModel = model.bake(
 | 
			
		||||
                model.getDefaultState(),
 | 
			
		||||
                DefaultVertexFormats.ITEM,
 | 
			
		||||
                location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( location.toString() )
 | 
			
		||||
            );
 | 
			
		||||
            event.getModelRegistry().putObject(
 | 
			
		||||
                new ModelResourceLocation( "computercraft:" + name, "inventory" ),
 | 
			
		||||
                bakedModel
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void loadSmartModel( ModelBakeEvent event, String name, IBakedModel smartModel )
 | 
			
		||||
        {
 | 
			
		||||
            event.getModelRegistry().putObject(
 | 
			
		||||
                new ModelResourceLocation( "computercraft:" + name, "inventory" ),
 | 
			
		||||
                smartModel
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class TurtleItemColour implements IItemColor
 | 
			
		||||
    {
 | 
			
		||||
        @Override
 | 
			
		||||
        public int colorMultiplier( @Nonnull ItemStack stack, int tintIndex )
 | 
			
		||||
        {
 | 
			
		||||
            if( tintIndex == 0 )
 | 
			
		||||
            {
 | 
			
		||||
                ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
 | 
			
		||||
                int colour = turtle.getColour( stack );
 | 
			
		||||
                if( colour != -1 ) return colour;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return 0xFFFFFF;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,594 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.proxy;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.gui.*;
 | 
			
		||||
import dan200.computercraft.client.render.*;
 | 
			
		||||
import dan200.computercraft.client.render.TileEntityCableRenderer;
 | 
			
		||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
 | 
			
		||||
import dan200.computercraft.shared.command.CommandCopy;
 | 
			
		||||
import dan200.computercraft.shared.command.ContainerViewComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.blocks.ComputerState;
 | 
			
		||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ClientComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.IComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.items.ItemComputer;
 | 
			
		||||
import dan200.computercraft.shared.media.inventory.ContainerHeldItem;
 | 
			
		||||
import dan200.computercraft.shared.media.items.ItemDiskLegacy;
 | 
			
		||||
import dan200.computercraft.shared.media.items.ItemPrintout;
 | 
			
		||||
import dan200.computercraft.shared.network.ComputerCraftPacket;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.TileCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
 | 
			
		||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
 | 
			
		||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
 | 
			
		||||
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
 | 
			
		||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
 | 
			
		||||
import dan200.computercraft.shared.turtle.entity.TurtleVisionCamera;
 | 
			
		||||
import dan200.computercraft.shared.util.Colour;
 | 
			
		||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.gui.GuiNewChat;
 | 
			
		||||
import net.minecraft.client.renderer.ItemMeshDefinition;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelBakery;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
 | 
			
		||||
import net.minecraft.client.renderer.color.IItemColor;
 | 
			
		||||
import net.minecraft.client.util.ITooltipFlag;
 | 
			
		||||
import net.minecraft.entity.player.EntityPlayer;
 | 
			
		||||
import net.minecraft.entity.player.InventoryPlayer;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.EnumHand;
 | 
			
		||||
import net.minecraft.util.IThreadListener;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.util.SoundEvent;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.text.ITextComponent;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraftforge.client.ClientCommandHandler;
 | 
			
		||||
import net.minecraftforge.client.event.ModelRegistryEvent;
 | 
			
		||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
 | 
			
		||||
import net.minecraftforge.client.event.RenderHandEvent;
 | 
			
		||||
import net.minecraftforge.client.event.RenderPlayerEvent;
 | 
			
		||||
import net.minecraftforge.client.model.ModelLoader;
 | 
			
		||||
import net.minecraftforge.common.MinecraftForge;
 | 
			
		||||
import net.minecraftforge.event.world.WorldEvent;
 | 
			
		||||
import net.minecraftforge.fml.client.registry.ClientRegistry;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.Side;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.SideOnly;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class ComputerCraftProxyClient extends ComputerCraftProxyCommon
 | 
			
		||||
{
 | 
			
		||||
    private static Int2IntOpenHashMap lastCounts = new Int2IntOpenHashMap();
 | 
			
		||||
 | 
			
		||||
    private long m_tick;
 | 
			
		||||
    private long m_renderFrame;
 | 
			
		||||
    private FixedWidthFontRenderer m_fixedWidthFontRenderer;
 | 
			
		||||
 | 
			
		||||
    // IComputerCraftProxy implementation
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void preInit()
 | 
			
		||||
    {
 | 
			
		||||
        super.preInit();
 | 
			
		||||
        m_tick = 0;
 | 
			
		||||
        m_renderFrame = 0;
 | 
			
		||||
 | 
			
		||||
        // Setup client forge handlers
 | 
			
		||||
        registerForgeHandlers();
 | 
			
		||||
 | 
			
		||||
        // Register any client-specific commands
 | 
			
		||||
        ClientCommandHandler.instance.registerCommand( CommandCopy.INSTANCE );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public void registerModels( ModelRegistryEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        // Register item models
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.computer, new ItemMeshDefinition()
 | 
			
		||||
        {
 | 
			
		||||
            private ModelResourceLocation computer = new ModelResourceLocation( "computercraft:computer", "inventory" );
 | 
			
		||||
            private ModelResourceLocation advanced_computer = new ModelResourceLocation( "computercraft:advanced_computer", "inventory" );
 | 
			
		||||
 | 
			
		||||
            @Nonnull
 | 
			
		||||
            @Override
 | 
			
		||||
            public ModelResourceLocation getModelLocation( @Nonnull ItemStack stack )
 | 
			
		||||
            {
 | 
			
		||||
                ItemComputer itemComputer = (ItemComputer) stack.getItem();
 | 
			
		||||
                ComputerFamily family = itemComputer.getFamily( stack.getItemDamage() );
 | 
			
		||||
                return ( family == ComputerFamily.Advanced ) ? advanced_computer : computer;
 | 
			
		||||
            }
 | 
			
		||||
        }, new String[]{ "computer", "advanced_computer" } );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.peripheral, 0, "peripheral" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.peripheral, 1, "wireless_modem" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.peripheral, 2, "monitor" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.peripheral, 3, "printer" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.peripheral, 4, "advanced_monitor" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.cable, 0, "cable" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.cable, 1, "wired_modem" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.commandComputer, "command_computer" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.advancedModem, "advanced_modem" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.peripheral, 5, "speaker" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Blocks.wiredModemFull, "wired_modem_full" );
 | 
			
		||||
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.disk, "disk" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.diskExpanded, "disk_expanded" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.treasureDisk, "treasure_disk" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.printout, 0, "printout" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.printout, 1, "pages" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.printout, 2, "book" );
 | 
			
		||||
        registerItemModel( ComputerCraft.Items.pocketComputer, new ItemMeshDefinition()
 | 
			
		||||
        {
 | 
			
		||||
            private ModelResourceLocation pocket_computer_off = new ModelResourceLocation( "computercraft:pocket_computer", "inventory" );
 | 
			
		||||
            private ModelResourceLocation pocket_computer_on = new ModelResourceLocation( "computercraft:pocket_computer_on", "inventory" );
 | 
			
		||||
            private ModelResourceLocation pocket_computer_blinking = new ModelResourceLocation( "computercraft:pocket_computer_blinking", "inventory" );
 | 
			
		||||
            private ModelResourceLocation advanced_pocket_computer_off = new ModelResourceLocation( "computercraft:advanced_pocket_computer", "inventory" );
 | 
			
		||||
            private ModelResourceLocation advanced_pocket_computer_on = new ModelResourceLocation( "computercraft:advanced_pocket_computer_on", "inventory" );
 | 
			
		||||
            private ModelResourceLocation advanced_pocket_computer_blinking = new ModelResourceLocation( "computercraft:advanced_pocket_computer_blinking", "inventory" );
 | 
			
		||||
            private ModelResourceLocation colour_pocket_computer_off = new ModelResourceLocation( "computercraft:pocket_computer_colour", "inventory" );
 | 
			
		||||
            private ModelResourceLocation colour_pocket_computer_on = new ModelResourceLocation( "computercraft:pocket_computer_colour_on", "inventory" );
 | 
			
		||||
            private ModelResourceLocation colour_pocket_computer_blinking = new ModelResourceLocation( "computercraft:pocket_computer_colour_blinking", "inventory" );
 | 
			
		||||
 | 
			
		||||
            @Nonnull
 | 
			
		||||
            @Override
 | 
			
		||||
            public ModelResourceLocation getModelLocation( @Nonnull ItemStack stack )
 | 
			
		||||
            {
 | 
			
		||||
                ItemPocketComputer itemPocketComputer = (ItemPocketComputer) stack.getItem();
 | 
			
		||||
                ComputerState state = itemPocketComputer.getState( stack );
 | 
			
		||||
                if( itemPocketComputer.getColour( stack ) == -1 )
 | 
			
		||||
                {
 | 
			
		||||
                    switch( itemPocketComputer.getFamily( stack ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        case Advanced:
 | 
			
		||||
                            switch( state )
 | 
			
		||||
                            {
 | 
			
		||||
                                case Off:
 | 
			
		||||
                                default:
 | 
			
		||||
                                    return advanced_pocket_computer_off;
 | 
			
		||||
                                case On:
 | 
			
		||||
                                    return advanced_pocket_computer_on;
 | 
			
		||||
                                case Blinking:
 | 
			
		||||
                                    return advanced_pocket_computer_blinking;
 | 
			
		||||
                            }
 | 
			
		||||
                        case Normal:
 | 
			
		||||
                        default:
 | 
			
		||||
                            switch( state )
 | 
			
		||||
                            {
 | 
			
		||||
                                case Off:
 | 
			
		||||
                                default:
 | 
			
		||||
                                    return pocket_computer_off;
 | 
			
		||||
                                case On:
 | 
			
		||||
                                    return pocket_computer_on;
 | 
			
		||||
                                case Blinking:
 | 
			
		||||
                                    return pocket_computer_blinking;
 | 
			
		||||
                            }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    switch( state )
 | 
			
		||||
                    {
 | 
			
		||||
                        case Off:
 | 
			
		||||
                        default:
 | 
			
		||||
                            return colour_pocket_computer_off;
 | 
			
		||||
                        case On:
 | 
			
		||||
                            return colour_pocket_computer_on;
 | 
			
		||||
                        case Blinking:
 | 
			
		||||
                            return colour_pocket_computer_blinking;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, new String[] {
 | 
			
		||||
            "pocket_computer", "pocket_computer_on", "pocket_computer_blinking",
 | 
			
		||||
            "advanced_pocket_computer", "advanced_pocket_computer_on", "advanced_pocket_computer_blinking",
 | 
			
		||||
            "pocket_computer_colour", "pocket_computer_colour_on", "pocket_computer_colour_blinking",
 | 
			
		||||
        } );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void init()
 | 
			
		||||
    {
 | 
			
		||||
        super.init();
 | 
			
		||||
 | 
			
		||||
        // Load textures
 | 
			
		||||
        Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
        m_fixedWidthFontRenderer = new FixedWidthFontRenderer( mc.getTextureManager() );
 | 
			
		||||
 | 
			
		||||
        // Setup
 | 
			
		||||
        mc.getItemColors().registerItemColorHandler( new DiskColorHandler( ComputerCraft.Items.disk ), ComputerCraft.Items.disk );
 | 
			
		||||
        mc.getItemColors().registerItemColorHandler( new DiskColorHandler( ComputerCraft.Items.diskExpanded ), ComputerCraft.Items.diskExpanded );
 | 
			
		||||
 | 
			
		||||
        mc.getItemColors().registerItemColorHandler( ( stack, layer ) ->
 | 
			
		||||
        {
 | 
			
		||||
            switch( layer )
 | 
			
		||||
            {
 | 
			
		||||
                case 0:
 | 
			
		||||
                default:
 | 
			
		||||
                    return 0xFFFFFF;
 | 
			
		||||
                case 1:
 | 
			
		||||
                {
 | 
			
		||||
                    // Frame colour
 | 
			
		||||
                    int colour = ComputerCraft.Items.pocketComputer.getColour( stack );
 | 
			
		||||
                    return colour == -1 ? 0xFFFFFF : colour;
 | 
			
		||||
                }
 | 
			
		||||
                case 2:
 | 
			
		||||
                {
 | 
			
		||||
                    // Light colour
 | 
			
		||||
                    int colour = ComputerCraft.Items.pocketComputer.getLightState( stack );
 | 
			
		||||
                    return colour == -1 ? Colour.Black.getHex() : colour;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, ComputerCraft.Items.pocketComputer );
 | 
			
		||||
 | 
			
		||||
        // Setup renderers
 | 
			
		||||
        ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() );
 | 
			
		||||
        ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Block block, int damage, String name )
 | 
			
		||||
    @Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
 | 
			
		||||
    public static class ForgeHandlers
 | 
			
		||||
    {
 | 
			
		||||
        registerItemModel( Item.getItemFromBlock( block ), damage, name );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Item item, int damage, String name )
 | 
			
		||||
    {
 | 
			
		||||
        ModelResourceLocation res = new ModelResourceLocation( "computercraft:" + name, "inventory" );
 | 
			
		||||
        ModelBakery.registerItemVariants( item, new ResourceLocation( "computercraft", name ) );
 | 
			
		||||
        ModelLoader.setCustomModelResourceLocation( item, damage, res );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Block block, String name )
 | 
			
		||||
    {
 | 
			
		||||
        registerItemModel( Item.getItemFromBlock( block ), name );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Item item, String name )
 | 
			
		||||
    {
 | 
			
		||||
        final ModelResourceLocation res = new ModelResourceLocation( "computercraft:" + name, "inventory" );
 | 
			
		||||
        ModelBakery.registerItemVariants( item, new ResourceLocation( "computercraft", name ) );
 | 
			
		||||
        ModelLoader.setCustomMeshDefinition( item, new ItemMeshDefinition()
 | 
			
		||||
        {
 | 
			
		||||
            @Nonnull
 | 
			
		||||
            @Override
 | 
			
		||||
            public ModelResourceLocation getModelLocation( @Nonnull ItemStack stack )
 | 
			
		||||
            {
 | 
			
		||||
                return res;
 | 
			
		||||
            }
 | 
			
		||||
        } );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Block block, ItemMeshDefinition definition, String[] names )
 | 
			
		||||
    {
 | 
			
		||||
        registerItemModel( Item.getItemFromBlock( block ), definition, names );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerItemModel( Item item, ItemMeshDefinition definition, String[] names )
 | 
			
		||||
    {
 | 
			
		||||
        ResourceLocation[] resources = new ResourceLocation[names.length];
 | 
			
		||||
        for( int i=0; i<resources.length; ++i )
 | 
			
		||||
        {
 | 
			
		||||
            resources[i] = new ResourceLocation( "computercraft", names[i] );
 | 
			
		||||
        }
 | 
			
		||||
        ModelBakery.registerItemVariants( item, resources );
 | 
			
		||||
        ModelLoader.setCustomMeshDefinition( item, definition );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isClient()
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean getGlobalCursorBlink()
 | 
			
		||||
    {
 | 
			
		||||
        return ( m_tick / 8) % 2 == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getRenderFrame()
 | 
			
		||||
    {
 | 
			
		||||
        return m_renderFrame;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getFixedWidthFontRenderer()
 | 
			
		||||
    {
 | 
			
		||||
        return m_fixedWidthFontRenderer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getRecordInfo( @Nonnull ItemStack recordStack )
 | 
			
		||||
    {
 | 
			
		||||
        List<String> info = new ArrayList<>( 1 );
 | 
			
		||||
        recordStack.getItem().addInformation( recordStack, null, info, ITooltipFlag.TooltipFlags.NORMAL );
 | 
			
		||||
        if( info.size() > 0 ) {
 | 
			
		||||
            return info.get( 0 );
 | 
			
		||||
        } else {
 | 
			
		||||
            return super.getRecordInfo( recordStack );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getDiskDriveGUI( InventoryPlayer inventory, TileDiskDrive drive )
 | 
			
		||||
    {
 | 
			
		||||
        return new GuiDiskDrive( inventory, drive );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getComputerGUI( TileComputer computer )
 | 
			
		||||
    {
 | 
			
		||||
        return new GuiComputer( computer );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getPrinterGUI( InventoryPlayer inventory, TilePrinter printer )
 | 
			
		||||
    {
 | 
			
		||||
        return new GuiPrinter( inventory, printer );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getTurtleGUI( InventoryPlayer inventory, TileTurtle turtle )
 | 
			
		||||
    {
 | 
			
		||||
        return new GuiTurtle( turtle.getWorld(), inventory, turtle );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getPrintoutGUI( EntityPlayer player, EnumHand hand )
 | 
			
		||||
    {
 | 
			
		||||
        ContainerHeldItem container = new ContainerHeldItem( player, hand );
 | 
			
		||||
        if( container.getStack().getItem() instanceof ItemPrintout )
 | 
			
		||||
        {
 | 
			
		||||
            return new GuiPrintout( container );
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getPocketComputerGUI( EntityPlayer player, EnumHand hand )
 | 
			
		||||
    {
 | 
			
		||||
        ContainerPocketComputer container = new ContainerPocketComputer( player, hand );
 | 
			
		||||
        if( container.getStack().getItem() instanceof ItemPocketComputer )
 | 
			
		||||
        {
 | 
			
		||||
            return new GuiPocketComputer( container );
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getComputerGUI( IComputer computer, int width, int height, ComputerFamily family )
 | 
			
		||||
    {
 | 
			
		||||
        ContainerViewComputer container = new ContainerViewComputer( computer );
 | 
			
		||||
        return new GuiComputer( container, family, computer, width, height );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public File getWorldDir( World world )
 | 
			
		||||
    {
 | 
			
		||||
        return world.getSaveHandler().getWorldDirectory();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handlePacket( final ComputerCraftPacket packet, final EntityPlayer player )
 | 
			
		||||
    {
 | 
			
		||||
        switch( packet.m_packetType )
 | 
			
		||||
        {
 | 
			
		||||
            case ComputerCraftPacket.ComputerChanged:
 | 
			
		||||
            case ComputerCraftPacket.ComputerTerminalChanged:
 | 
			
		||||
            case ComputerCraftPacket.ComputerDeleted:
 | 
			
		||||
            case ComputerCraftPacket.PlayRecord:
 | 
			
		||||
            case ComputerCraftPacket.PostChat:
 | 
			
		||||
            {
 | 
			
		||||
                // Packet from Server to Client
 | 
			
		||||
                IThreadListener listener = Minecraft.getMinecraft();
 | 
			
		||||
                if( listener != null )
 | 
			
		||||
                {
 | 
			
		||||
                    if( listener.isCallingFromMinecraftThread() )
 | 
			
		||||
                    {
 | 
			
		||||
                        processPacket( packet, player );
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        listener.addScheduledTask( () -> processPacket( packet, player ) );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                // Packet from Client to Server
 | 
			
		||||
                super.handlePacket( packet, player );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void processPacket( ComputerCraftPacket packet, EntityPlayer player )
 | 
			
		||||
    {
 | 
			
		||||
        switch( packet.m_packetType )
 | 
			
		||||
        {
 | 
			
		||||
            ///////////////////////////////////
 | 
			
		||||
            // Packets from Server to Client //
 | 
			
		||||
            ///////////////////////////////////
 | 
			
		||||
            case ComputerCraftPacket.ComputerChanged:
 | 
			
		||||
            case ComputerCraftPacket.ComputerTerminalChanged:
 | 
			
		||||
            {
 | 
			
		||||
                int instanceID = packet.m_dataInt[ 0 ];
 | 
			
		||||
                if( !ComputerCraft.clientComputerRegistry.contains( instanceID ) )
 | 
			
		||||
                {
 | 
			
		||||
                    ComputerCraft.clientComputerRegistry.add( instanceID, new ClientComputer( instanceID ) );
 | 
			
		||||
                }
 | 
			
		||||
                ComputerCraft.clientComputerRegistry.get( instanceID ).handlePacket( packet, player );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case ComputerCraftPacket.ComputerDeleted:
 | 
			
		||||
            {
 | 
			
		||||
                int instanceID = packet.m_dataInt[ 0 ];
 | 
			
		||||
                if( ComputerCraft.clientComputerRegistry.contains( instanceID ) )
 | 
			
		||||
                {
 | 
			
		||||
                    ComputerCraft.clientComputerRegistry.remove( instanceID );
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case ComputerCraftPacket.PlayRecord:
 | 
			
		||||
            {
 | 
			
		||||
                BlockPos pos = new BlockPos( packet.m_dataInt[ 0 ], packet.m_dataInt[ 1 ], packet.m_dataInt[ 2 ] );
 | 
			
		||||
                Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
                if( packet.m_dataInt.length > 3 )
 | 
			
		||||
                {
 | 
			
		||||
                    SoundEvent sound = SoundEvent.REGISTRY.getObjectById( packet.m_dataInt[ 3 ] );
 | 
			
		||||
                    mc.world.playRecord( pos, sound );
 | 
			
		||||
                    mc.ingameGUI.setRecordPlayingMessage( packet.m_dataString[ 0 ] );
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mc.world.playRecord( pos, null );
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case ComputerCraftPacket.PostChat:
 | 
			
		||||
            {
 | 
			
		||||
                /*
 | 
			
		||||
                  This allows us to send delete chat messages of the same "category" as the previous one.
 | 
			
		||||
                  It's used by the various /computercraft commands to avoid filling the chat with repetitive
 | 
			
		||||
                  messages.
 | 
			
		||||
                 */
 | 
			
		||||
 | 
			
		||||
                int id = packet.m_dataInt[0];
 | 
			
		||||
                ITextComponent[] components = new ITextComponent[packet.m_dataString.length];
 | 
			
		||||
                for( int i = 0; i < packet.m_dataString.length; i++ )
 | 
			
		||||
                {
 | 
			
		||||
                    components[i] = ITextComponent.Serializer.jsonToComponent( packet.m_dataString[i] );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
 | 
			
		||||
 | 
			
		||||
                // Keep track of how many lines we wrote last time, deleting any extra ones.
 | 
			
		||||
                int lastCount = lastCounts.get( id );
 | 
			
		||||
                for( int i = components.length; i < lastCount; i++ ) chat.deleteChatLine( i + id );
 | 
			
		||||
                lastCounts.put( id, components.length );
 | 
			
		||||
 | 
			
		||||
                // Add new lines
 | 
			
		||||
                for( int i = 0; i < components.length; i++ )
 | 
			
		||||
                {
 | 
			
		||||
                    chat.printChatMessageWithOptionalDeletion( components[i], id + i );
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void registerForgeHandlers()
 | 
			
		||||
    {
 | 
			
		||||
        ForgeHandlers handlers = new ForgeHandlers();
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( handlers );
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( new RenderOverlayCable() );
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( new ItemPocketRenderer() );
 | 
			
		||||
        MinecraftForge.EVENT_BUS.register( new ItemPrintoutRenderer() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ForgeHandlers
 | 
			
		||||
    {
 | 
			
		||||
        public ForgeHandlers()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onRenderHand( RenderHandEvent event )
 | 
			
		||||
        {
 | 
			
		||||
            // Don't draw the player arm when in turtle vision
 | 
			
		||||
            Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
            if( mc.getRenderViewEntity() instanceof TurtleVisionCamera )
 | 
			
		||||
            {
 | 
			
		||||
                event.setCanceled( true );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onRenderPlayer( RenderPlayerEvent.Pre event )
 | 
			
		||||
        {
 | 
			
		||||
            Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
            if( event.getEntityPlayer().isUser() && mc.getRenderViewEntity() instanceof TurtleVisionCamera )
 | 
			
		||||
            {
 | 
			
		||||
                // HACK: Force the 'livingPlayer' variable to the player, this ensures the entity is drawn
 | 
			
		||||
                //event.getRenderer().getRenderManager().livingPlayer = event.getEntityPlayer();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onRenderPlayer( RenderPlayerEvent.Post event )
 | 
			
		||||
        {
 | 
			
		||||
            Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
            if( event.getEntityPlayer().isUser() && mc.getRenderViewEntity() instanceof TurtleVisionCamera )
 | 
			
		||||
            {
 | 
			
		||||
                // HACK: Restore the 'livingPlayer' variable to what it was before the RenderPlayerEvent.Pre hack
 | 
			
		||||
                //event.getRenderer().getRenderManager().livingPlayer = mc.getRenderViewEntity();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onPreRenderGameOverlay( RenderGameOverlayEvent.Pre event )
 | 
			
		||||
        {
 | 
			
		||||
            Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
            if( mc.getRenderViewEntity() instanceof TurtleVisionCamera )
 | 
			
		||||
            {
 | 
			
		||||
                switch( event.getType() )
 | 
			
		||||
                {
 | 
			
		||||
                    case HELMET:
 | 
			
		||||
                    case PORTAL:
 | 
			
		||||
                    //case CROSSHAIRS:
 | 
			
		||||
                    case BOSSHEALTH:
 | 
			
		||||
                    case ARMOR:
 | 
			
		||||
                    case HEALTH:
 | 
			
		||||
                    case FOOD:
 | 
			
		||||
                    case AIR:
 | 
			
		||||
                    case HOTBAR:
 | 
			
		||||
                    case EXPERIENCE:
 | 
			
		||||
                    case HEALTHMOUNT:
 | 
			
		||||
                    case JUMPBAR:
 | 
			
		||||
                    {
 | 
			
		||||
                        event.setCanceled( true );
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onTick( TickEvent.ClientTickEvent event )
 | 
			
		||||
        {
 | 
			
		||||
            if( event.phase == TickEvent.Phase.START )
 | 
			
		||||
            {
 | 
			
		||||
                m_tick++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onRenderTick( TickEvent.RenderTickEvent event )
 | 
			
		||||
        {
 | 
			
		||||
            if( event.phase == TickEvent.Phase.START )
 | 
			
		||||
            {
 | 
			
		||||
                m_renderFrame++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SubscribeEvent
 | 
			
		||||
        public void onWorldUnload( WorldEvent.Unload event )
 | 
			
		||||
        public static void onWorldUnload( WorldEvent.Unload event )
 | 
			
		||||
        {
 | 
			
		||||
            if( event.getWorld().isRemote )
 | 
			
		||||
            {
 | 
			
		||||
@@ -597,20 +55,5 @@ public class ComputerCraftProxyClient extends ComputerCraftProxyCommon
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SideOnly(Side.CLIENT)
 | 
			
		||||
    private static class DiskColorHandler implements IItemColor
 | 
			
		||||
    {
 | 
			
		||||
        private final ItemDiskLegacy disk;
 | 
			
		||||
 | 
			
		||||
        private DiskColorHandler( ItemDiskLegacy disk )
 | 
			
		||||
        {
 | 
			
		||||
            this.disk = disk;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public int colorMultiplier( @Nonnull ItemStack stack, int layer )
 | 
			
		||||
        {
 | 
			
		||||
            return layer == 0 ? 0xFFFFFF : disk.getColour( stack );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.renderer.ItemRenderer;
 | 
			
		||||
import net.minecraft.entity.player.EntityPlayer;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.EnumHand;
 | 
			
		||||
import net.minecraft.util.EnumHandSide;
 | 
			
		||||
import net.minecraft.util.math.MathHelper;
 | 
			
		||||
 | 
			
		||||
public abstract class ItemMapLikeRenderer
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * The main rendering method for the item
 | 
			
		||||
     *
 | 
			
		||||
     * @param stack The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPerson(ItemStack)
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract void renderItem( ItemStack stack );
 | 
			
		||||
 | 
			
		||||
    protected void renderItemFirstPerson( EnumHand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        EntityPlayer player = Minecraft.getMinecraft().player;
 | 
			
		||||
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        if( hand == EnumHand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
 | 
			
		||||
        {
 | 
			
		||||
            renderItemFirstPersonCenter( pitch, equipProgress, swingProgress, stack );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            renderItemFirstPersonSide(
 | 
			
		||||
                hand == EnumHand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
 | 
			
		||||
                equipProgress, swingProgress, stack
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        GlStateManager.popMatrix();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renders the item to one side of the player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param side          The side to render on
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
     * @param swingProgress The swing progress of this item
 | 
			
		||||
     * @param stack         The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPersonSide(float, EnumHandSide, float, ItemStack)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderItemFirstPersonSide( EnumHandSide side, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        Minecraft minecraft = Minecraft.getMinecraft();
 | 
			
		||||
        float offset = side == EnumHandSide.RIGHT ? 1f : -1f;
 | 
			
		||||
        GlStateManager.translate( offset * 0.125f, -0.125f, 0f );
 | 
			
		||||
 | 
			
		||||
        // If the player is not invisible then render a single arm
 | 
			
		||||
        if( !minecraft.player.isInvisible() )
 | 
			
		||||
        {
 | 
			
		||||
            GlStateManager.pushMatrix();
 | 
			
		||||
            GlStateManager.rotate( offset * 10f, 0f, 0f, 1f );
 | 
			
		||||
            minecraft.getItemRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
 | 
			
		||||
            GlStateManager.popMatrix();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Setup the appropriate transformations. This is just copied from the
 | 
			
		||||
        // corresponding method in ItemRenderer.
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        GlStateManager.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
 | 
			
		||||
        float f1 = MathHelper.sqrt( swingProgress );
 | 
			
		||||
        float f2 = MathHelper.sin( f1 * (float) Math.PI );
 | 
			
		||||
        float f3 = -0.5f * f2;
 | 
			
		||||
        float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) );
 | 
			
		||||
        float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI );
 | 
			
		||||
        GlStateManager.translate( offset * f3, f4 - 0.3f * f2, f5 );
 | 
			
		||||
        GlStateManager.rotate( f2 * -45f, 1f, 0f, 0f );
 | 
			
		||||
        GlStateManager.rotate( offset * f2 * -30f, 0f, 1f, 0f );
 | 
			
		||||
 | 
			
		||||
        renderItem( stack );
 | 
			
		||||
 | 
			
		||||
        GlStateManager.popMatrix();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Render an item in the middle of the screen
 | 
			
		||||
     *
 | 
			
		||||
     * @param pitch         The pitch of the player
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
     * @param swingProgress The swing progress of this item
 | 
			
		||||
     * @param stack         The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPerson(float, float, float)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderItemFirstPersonCenter( float pitch, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        ItemRenderer itemRenderer = Minecraft.getMinecraft().getItemRenderer();
 | 
			
		||||
 | 
			
		||||
        // Setup the appropriate transformations. This is just copied from the
 | 
			
		||||
        // corresponding method in ItemRenderer.
 | 
			
		||||
        float swingRt = MathHelper.sqrt( swingProgress );
 | 
			
		||||
        float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
 | 
			
		||||
        float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
 | 
			
		||||
        GlStateManager.translate( 0f, -tX / 2f, tZ );
 | 
			
		||||
        float pitchAngle = itemRenderer.getMapAngleFromPitch( pitch );
 | 
			
		||||
        GlStateManager.translate( 0f, 0.04f + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
 | 
			
		||||
        GlStateManager.rotate( pitchAngle * -85f, 1f, 0f, 0f );
 | 
			
		||||
        itemRenderer.renderArms();
 | 
			
		||||
        float rX = MathHelper.sin( swingRt * (float) Math.PI );
 | 
			
		||||
        GlStateManager.rotate( rX * 20f, 1f, 0f, 0f );
 | 
			
		||||
        GlStateManager.scale( 2f, 2f, 2f );
 | 
			
		||||
 | 
			
		||||
        renderItem( stack );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,13 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.FrameInfo;
 | 
			
		||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
 | 
			
		||||
import dan200.computercraft.core.terminal.Terminal;
 | 
			
		||||
import dan200.computercraft.core.terminal.TextBuffer;
 | 
			
		||||
@@ -10,22 +16,17 @@ import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
 | 
			
		||||
import dan200.computercraft.shared.util.Palette;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.renderer.ItemRenderer;
 | 
			
		||||
import net.minecraft.client.renderer.RenderItem;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureManager;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureMap;
 | 
			
		||||
import net.minecraft.entity.player.EntityPlayer;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.EnumHand;
 | 
			
		||||
import net.minecraft.util.EnumHandSide;
 | 
			
		||||
import net.minecraft.util.math.MathHelper;
 | 
			
		||||
import net.minecraftforge.client.ForgeHooksClient;
 | 
			
		||||
import net.minecraftforge.client.event.RenderSpecificHandEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.Side;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.SideOnly;
 | 
			
		||||
import org.lwjgl.opengl.GL11;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
 | 
			
		||||
@@ -34,48 +35,27 @@ import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
 | 
			
		||||
/**
 | 
			
		||||
 * Emulates map rendering for pocket computers
 | 
			
		||||
 */
 | 
			
		||||
@SideOnly(Side.CLIENT)
 | 
			
		||||
public class ItemPocketRenderer
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
 | 
			
		||||
public final class ItemPocketRenderer extends ItemMapLikeRenderer
 | 
			
		||||
{
 | 
			
		||||
    private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
 | 
			
		||||
 | 
			
		||||
    private ItemPocketRenderer()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public void renderItem( RenderSpecificHandEvent event )
 | 
			
		||||
    public static void renderItem( RenderSpecificHandEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        ItemStack stack = event.getItemStack();
 | 
			
		||||
        if( !(stack.getItem() instanceof ItemPocketComputer) ) return;
 | 
			
		||||
 | 
			
		||||
        event.setCanceled( true );
 | 
			
		||||
 | 
			
		||||
        EntityPlayer player = Minecraft.getMinecraft().player;
 | 
			
		||||
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        if( event.getHand() == EnumHand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
 | 
			
		||||
        {
 | 
			
		||||
            renderItemFirstCentre(
 | 
			
		||||
                event.getInterpolatedPitch(),
 | 
			
		||||
                event.getEquipProgress(),
 | 
			
		||||
                event.getSwingProgress(),
 | 
			
		||||
                stack
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            renderItemFirstPersonSide(
 | 
			
		||||
                event.getHand() == EnumHand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
 | 
			
		||||
                event.getEquipProgress(),
 | 
			
		||||
                event.getSwingProgress(),
 | 
			
		||||
                stack
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        GlStateManager.popMatrix();
 | 
			
		||||
        INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The main rendering method for pocket computers and their associated terminal
 | 
			
		||||
     *
 | 
			
		||||
     * @param stack The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPerson(ItemStack)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderPocketComputerItem( ItemStack stack )
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void renderItem( ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        // Setup various transformations. Note that these are partially adapated from the corresponding method
 | 
			
		||||
        // in ItemRenderer
 | 
			
		||||
@@ -89,8 +69,8 @@ public class ItemPocketRenderer
 | 
			
		||||
        ClientComputer computer = pocketComputer.createClientComputer( stack );
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            // First render the background item. We use the item's model rather than a direct texture as this ensures 
 | 
			
		||||
            // we display the pocket light and other such decorations. 
 | 
			
		||||
            // First render the background item. We use the item's model rather than a direct texture as this ensures
 | 
			
		||||
            // we display the pocket light and other such decorations.
 | 
			
		||||
            GlStateManager.pushMatrix();
 | 
			
		||||
 | 
			
		||||
            GlStateManager.scale( 1.0f, -1.0f, 1.0f );
 | 
			
		||||
@@ -153,12 +133,12 @@ public class ItemPocketRenderer
 | 
			
		||||
                    int startX = (max - width) / 2 + margin;
 | 
			
		||||
                    int startY = (max - height) / 2 + margin;
 | 
			
		||||
 | 
			
		||||
                    FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
 | 
			
		||||
                    FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance();
 | 
			
		||||
                    boolean greyscale = !computer.isColour();
 | 
			
		||||
                    Palette palette = terminal.getPalette();
 | 
			
		||||
 | 
			
		||||
                    // Render the actual text
 | 
			
		||||
                    for( int line = 0; line < th; ++line )
 | 
			
		||||
                    for( int line = 0; line < th; line++ )
 | 
			
		||||
                    {
 | 
			
		||||
                        TextBuffer text = terminal.getLine( line );
 | 
			
		||||
                        TextBuffer colour = terminal.getTextColourLine( line );
 | 
			
		||||
@@ -171,7 +151,7 @@ public class ItemPocketRenderer
 | 
			
		||||
 | 
			
		||||
                    // And render the cursor;
 | 
			
		||||
                    int tx = terminal.getCursorX(), ty = terminal.getCursorY();
 | 
			
		||||
                    if( terminal.getCursorBlink() && ComputerCraft.getGlobalCursorBlink() &&
 | 
			
		||||
                    if( terminal.getCursorBlink() && FrameInfo.getGlobalCursorBlink() &&
 | 
			
		||||
                        tx >= 0 && ty >= 0 && tx < tw && ty < th )
 | 
			
		||||
                    {
 | 
			
		||||
                        TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 );
 | 
			
		||||
@@ -189,76 +169,4 @@ public class ItemPocketRenderer
 | 
			
		||||
 | 
			
		||||
        GlStateManager.enableLighting();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renders a pocket computer to one side of the player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param side          The side to render on
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
     * @param swingProgress The swing progress of this item
 | 
			
		||||
     * @param stack         The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPersonSide(float, EnumHandSide, float, ItemStack)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderItemFirstPersonSide( EnumHandSide side, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        Minecraft minecraft = Minecraft.getMinecraft();
 | 
			
		||||
        float offset = side == EnumHandSide.RIGHT ? 1f : -1f;
 | 
			
		||||
        GlStateManager.translate( offset * 0.125f, -0.125f, 0f );
 | 
			
		||||
 | 
			
		||||
        // If the player is not invisible then render a single arm
 | 
			
		||||
        if( !minecraft.player.isInvisible() )
 | 
			
		||||
        {
 | 
			
		||||
            GlStateManager.pushMatrix();
 | 
			
		||||
            GlStateManager.rotate( offset * 10f, 0f, 0f, 1f );
 | 
			
		||||
            minecraft.getItemRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
 | 
			
		||||
            GlStateManager.popMatrix();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Setup the appropriate transformations. This is just copied from the
 | 
			
		||||
        // corresponding method in ItemRenderer. 
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        GlStateManager.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
 | 
			
		||||
        float f1 = MathHelper.sqrt( swingProgress );
 | 
			
		||||
        float f2 = MathHelper.sin( f1 * (float) Math.PI );
 | 
			
		||||
        float f3 = -0.5f * f2;
 | 
			
		||||
        float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) );
 | 
			
		||||
        float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI );
 | 
			
		||||
        GlStateManager.translate( offset * f3, f4 - 0.3f * f2, f5 );
 | 
			
		||||
        GlStateManager.rotate( f2 * -45f, 1f, 0f, 0f );
 | 
			
		||||
        GlStateManager.rotate( offset * f2 * -30f, 0f, 1f, 0f );
 | 
			
		||||
 | 
			
		||||
        renderPocketComputerItem( stack );
 | 
			
		||||
 | 
			
		||||
        GlStateManager.popMatrix();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Render an item in the middle of the screen
 | 
			
		||||
     *
 | 
			
		||||
     * @param pitch         The pitch of the player
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
     * @param swingProgress The swing progress of this item
 | 
			
		||||
     * @param stack         The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPerson(float, float, float)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderItemFirstCentre( float pitch, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        ItemRenderer itemRenderer = Minecraft.getMinecraft().getItemRenderer();
 | 
			
		||||
 | 
			
		||||
        // Setup the appropriate transformations. This is just copied from the
 | 
			
		||||
        // corresponding method in ItemRenderer.
 | 
			
		||||
        float swingRt = MathHelper.sqrt( swingProgress );
 | 
			
		||||
        float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
 | 
			
		||||
        float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
 | 
			
		||||
        GlStateManager.translate( 0f, -tX / 2f, tZ );
 | 
			
		||||
        float pitchAngle = itemRenderer.getMapAngleFromPitch( pitch );
 | 
			
		||||
        GlStateManager.translate( 0f, 0.04f + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
 | 
			
		||||
        GlStateManager.rotate( pitchAngle * -85f, 1f, 0f, 0f );
 | 
			
		||||
        itemRenderer.renderArms();
 | 
			
		||||
        float rX = MathHelper.sin( swingRt * (float) Math.PI );
 | 
			
		||||
        GlStateManager.rotate( rX * 20f, 1f, 0f, 0f );
 | 
			
		||||
        GlStateManager.scale( 2f, 2f, 2f );
 | 
			
		||||
 | 
			
		||||
        renderPocketComputerItem( stack );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,20 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.shared.media.items.ItemPrintout;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.renderer.ItemRenderer;
 | 
			
		||||
import net.minecraft.entity.player.EntityPlayer;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.EnumHand;
 | 
			
		||||
import net.minecraft.util.EnumHandSide;
 | 
			
		||||
import net.minecraft.util.math.MathHelper;
 | 
			
		||||
import net.minecraftforge.client.event.RenderItemInFrameEvent;
 | 
			
		||||
import net.minecraftforge.client.event.RenderSpecificHandEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.Side;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
 | 
			
		||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
 | 
			
		||||
@@ -20,114 +22,31 @@ import static dan200.computercraft.client.render.PrintoutRenderer.*;
 | 
			
		||||
import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE;
 | 
			
		||||
import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH;
 | 
			
		||||
 | 
			
		||||
public class ItemPrintoutRenderer
 | 
			
		||||
/**
 | 
			
		||||
 * Emulates map and item-frame rendering for prinouts
 | 
			
		||||
 */
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
 | 
			
		||||
public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
 | 
			
		||||
{
 | 
			
		||||
    private static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer();
 | 
			
		||||
 | 
			
		||||
    private ItemPrintoutRenderer()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public void onRenderInHand( RenderSpecificHandEvent event )
 | 
			
		||||
    public static void onRenderInHand( RenderSpecificHandEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        ItemStack stack = event.getItemStack();
 | 
			
		||||
        if( stack.getItem() != ComputerCraft.Items.printout ) return;
 | 
			
		||||
 | 
			
		||||
        event.setCanceled( true );
 | 
			
		||||
 | 
			
		||||
        EntityPlayer player = Minecraft.getMinecraft().player;
 | 
			
		||||
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        if( event.getHand() == EnumHand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
 | 
			
		||||
        {
 | 
			
		||||
            renderPrintoutFirstPersonCentre(
 | 
			
		||||
                event.getInterpolatedPitch(),
 | 
			
		||||
                event.getEquipProgress(),
 | 
			
		||||
                event.getSwingProgress(),
 | 
			
		||||
                stack
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            renderPrintoutFirstPersonSide(
 | 
			
		||||
                event.getHand() == EnumHand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
 | 
			
		||||
                event.getEquipProgress(),
 | 
			
		||||
                event.getSwingProgress(),
 | 
			
		||||
                stack
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        GlStateManager.popMatrix();
 | 
			
		||||
        INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renders a pocket computer to one side of the player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param side          The side to render on
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
     * @param swingProgress The swing progress of this item
 | 
			
		||||
     * @param stack         The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPersonSide(float, EnumHandSide, float, ItemStack)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderPrintoutFirstPersonSide( EnumHandSide side, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        Minecraft minecraft = Minecraft.getMinecraft();
 | 
			
		||||
        float offset = side == EnumHandSide.RIGHT ? 1f : -1f;
 | 
			
		||||
        GlStateManager.translate( offset * 0.125f, -0.125f, 0f );
 | 
			
		||||
 | 
			
		||||
        // If the player is not invisible then render a single arm
 | 
			
		||||
        if( !minecraft.player.isInvisible() )
 | 
			
		||||
        {
 | 
			
		||||
            GlStateManager.pushMatrix();
 | 
			
		||||
            GlStateManager.rotate( offset * 10f, 0f, 0f, 1f );
 | 
			
		||||
            minecraft.getItemRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
 | 
			
		||||
            GlStateManager.popMatrix();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Setup the appropriate transformations. This is just copied from the
 | 
			
		||||
        // corresponding method in ItemRenderer. 
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        GlStateManager.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
 | 
			
		||||
        float f1 = MathHelper.sqrt( swingProgress );
 | 
			
		||||
        float f2 = MathHelper.sin( f1 * (float) Math.PI );
 | 
			
		||||
        float f3 = -0.5f * f2;
 | 
			
		||||
        float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) );
 | 
			
		||||
        float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI );
 | 
			
		||||
        GlStateManager.translate( offset * f3, f4 - 0.3f * f2, f5 );
 | 
			
		||||
        GlStateManager.rotate( f2 * -45f, 1f, 0f, 0f );
 | 
			
		||||
        GlStateManager.rotate( offset * f2 * -30f, 0f, 1f, 0f );
 | 
			
		||||
 | 
			
		||||
        renderPrintoutFirstPerson( stack );
 | 
			
		||||
 | 
			
		||||
        GlStateManager.popMatrix();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Render an item in the middle of the screen
 | 
			
		||||
     *
 | 
			
		||||
     * @param pitch         The pitch of the player
 | 
			
		||||
     * @param equipProgress The equip progress of this item
 | 
			
		||||
     * @param swingProgress The swing progress of this item
 | 
			
		||||
     * @param stack         The stack to render
 | 
			
		||||
     * @see ItemRenderer#renderMapFirstPerson(float, float, float)
 | 
			
		||||
     */
 | 
			
		||||
    private void renderPrintoutFirstPersonCentre( float pitch, float equipProgress, float swingProgress, ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        ItemRenderer itemRenderer = Minecraft.getMinecraft().getItemRenderer();
 | 
			
		||||
 | 
			
		||||
        // Setup the appropriate transformations. This is just copied from the
 | 
			
		||||
        // corresponding method in ItemRenderer.
 | 
			
		||||
        float swingRt = MathHelper.sqrt( swingProgress );
 | 
			
		||||
        float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
 | 
			
		||||
        float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
 | 
			
		||||
        GlStateManager.translate( 0f, -tX / 2f, tZ );
 | 
			
		||||
        float pitchAngle = itemRenderer.getMapAngleFromPitch( pitch );
 | 
			
		||||
        GlStateManager.translate( 0f, 0.04f + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
 | 
			
		||||
        GlStateManager.rotate( pitchAngle * -85f, 1f, 0f, 0f );
 | 
			
		||||
        itemRenderer.renderArms();
 | 
			
		||||
        float rX = MathHelper.sin( swingRt * (float) Math.PI );
 | 
			
		||||
        GlStateManager.rotate( rX * 20f, 1f, 0f, 0f );
 | 
			
		||||
        GlStateManager.scale( 2f, 2f, 2f );
 | 
			
		||||
 | 
			
		||||
        renderPrintoutFirstPerson( stack );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private static void renderPrintoutFirstPerson( ItemStack stack )
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void renderItem( ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        // Setup various transformations. Note that these are partially adapated from the corresponding method
 | 
			
		||||
        // in ItemRenderer.renderMapFirstPerson
 | 
			
		||||
@@ -144,7 +63,7 @@ public class ItemPrintoutRenderer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public void onRenderInFrame( RenderItemInFrameEvent event )
 | 
			
		||||
    public static void onRenderInFrame( RenderItemInFrameEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        ItemStack stack = event.getItem();
 | 
			
		||||
        if( stack.getItem() != ComputerCraft.Items.printout ) return;
 | 
			
		||||
@@ -162,6 +81,7 @@ public class ItemPrintoutRenderer
 | 
			
		||||
        drawPrintout( stack );
 | 
			
		||||
 | 
			
		||||
        GlStateManager.enableLighting();
 | 
			
		||||
        GlStateManager.disableBlend();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void drawPrintout( ItemStack stack )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.client.renderer.block.model.BakedQuad;
 | 
			
		||||
@@ -85,8 +91,8 @@ public final class ModelTransformer
 | 
			
		||||
        private final Matrix4f normalMatrix;
 | 
			
		||||
 | 
			
		||||
        private int vertexIndex = 0, elementIndex = 0;
 | 
			
		||||
        private final Point3f[] before = new Point3f[ 4 ];
 | 
			
		||||
        private final Point3f[] after = new Point3f[ 4 ];
 | 
			
		||||
        private final Point3f[] before = new Point3f[4];
 | 
			
		||||
        private final Point3f[] after = new Point3f[4];
 | 
			
		||||
 | 
			
		||||
        public NormalAwareTransformer( IVertexConsumer parent, Matrix4f positionMatrix, Matrix4f normalMatrix )
 | 
			
		||||
        {
 | 
			
		||||
@@ -96,7 +102,7 @@ public final class ModelTransformer
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void setQuadOrientation( EnumFacing orientation )
 | 
			
		||||
        public void setQuadOrientation( @Nonnull EnumFacing orientation )
 | 
			
		||||
        {
 | 
			
		||||
            super.setQuadOrientation( orientation == null ? orientation : TRSRTransformation.rotate( positionMatrix, orientation ) );
 | 
			
		||||
        }
 | 
			
		||||
@@ -112,13 +118,13 @@ public final class ModelTransformer
 | 
			
		||||
                    Point3f newVec = new Point3f();
 | 
			
		||||
                    positionMatrix.transform( vec, newVec );
 | 
			
		||||
 | 
			
		||||
                    float[] newData = new float[ 4 ];
 | 
			
		||||
                    float[] newData = new float[4];
 | 
			
		||||
                    newVec.get( newData );
 | 
			
		||||
                    super.put( element, newData );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    before[ vertexIndex ] = vec;
 | 
			
		||||
                    after[ vertexIndex ] = newVec;
 | 
			
		||||
                    before[vertexIndex] = vec;
 | 
			
		||||
                    after[vertexIndex] = newVec;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case NORMAL:
 | 
			
		||||
@@ -126,7 +132,7 @@ public final class ModelTransformer
 | 
			
		||||
                    Vector3f vec = new Vector3f( data );
 | 
			
		||||
                    normalMatrix.transform( vec );
 | 
			
		||||
 | 
			
		||||
                    float[] newData = new float[ 4 ];
 | 
			
		||||
                    float[] newData = new float[4];
 | 
			
		||||
                    vec.get( newData );
 | 
			
		||||
                    super.put( element, newData );
 | 
			
		||||
                    break;
 | 
			
		||||
@@ -150,17 +156,17 @@ public final class ModelTransformer
 | 
			
		||||
            Vector3f crossBefore = new Vector3f(), crossAfter = new Vector3f();
 | 
			
		||||
 | 
			
		||||
            // Determine what cross product we expect to have
 | 
			
		||||
            temp1.sub( before[ 1 ], before[ 0 ] );
 | 
			
		||||
            temp2.sub( before[ 1 ], before[ 2 ] );
 | 
			
		||||
            temp1.sub( before[1], before[0] );
 | 
			
		||||
            temp2.sub( before[1], before[2] );
 | 
			
		||||
            crossBefore.cross( temp1, temp2 );
 | 
			
		||||
            normalMatrix.transform( crossBefore );
 | 
			
		||||
 | 
			
		||||
            // And determine what cross product we actually have
 | 
			
		||||
            temp1.sub( after[ 1 ], after[ 0 ] );
 | 
			
		||||
            temp2.sub( after[ 1 ], after[ 2 ] );
 | 
			
		||||
            temp1.sub( after[1], after[0] );
 | 
			
		||||
            temp2.sub( after[1], after[2] );
 | 
			
		||||
            crossAfter.cross( temp1, temp2 );
 | 
			
		||||
 | 
			
		||||
            // If the angle between expected and actual cross product is greater than 
 | 
			
		||||
            // If the angle between expected and actual cross product is greater than
 | 
			
		||||
            // pi/2 radians then we will need to reorder our quads.
 | 
			
		||||
            return Math.abs( crossBefore.angle( crossAfter ) ) >= Math.PI / 2;
 | 
			
		||||
        }
 | 
			
		||||
@@ -189,7 +195,7 @@ public final class ModelTransformer
 | 
			
		||||
        private BakedQuadBuilder( VertexFormat format )
 | 
			
		||||
        {
 | 
			
		||||
            this.format = format;
 | 
			
		||||
            this.vertexData = new int[ format.getSize() ];
 | 
			
		||||
            this.vertexData = new int[format.getSize()];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
@@ -241,9 +247,9 @@ public final class ModelTransformer
 | 
			
		||||
            int length = vertexData.length / 4;
 | 
			
		||||
            for( int i = 0; i < length; i++ )
 | 
			
		||||
            {
 | 
			
		||||
                int temp = vertexData[ a * length + i ];
 | 
			
		||||
                vertexData[ a * length + i ] = vertexData[ b * length + i ];
 | 
			
		||||
                vertexData[ b * length + i ] = temp;
 | 
			
		||||
                int temp = vertexData[a * length + i];
 | 
			
		||||
                vertexData[a * length + i] = vertexData[b * length + i];
 | 
			
		||||
                vertexData[b * length + i] = temp;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,11 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
 | 
			
		||||
import dan200.computercraft.core.terminal.TextBuffer;
 | 
			
		||||
import dan200.computercraft.shared.util.Palette;
 | 
			
		||||
@@ -55,11 +60,11 @@ public class PrintoutRenderer
 | 
			
		||||
 | 
			
		||||
    public static void drawText( int x, int y, int start, TextBuffer[] text, TextBuffer[] colours )
 | 
			
		||||
    {
 | 
			
		||||
        FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
 | 
			
		||||
        FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance();
 | 
			
		||||
 | 
			
		||||
        for( int line = 0; line < LINES_PER_PAGE && line < text.length; ++line )
 | 
			
		||||
        for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
 | 
			
		||||
        {
 | 
			
		||||
            fontRenderer.drawString( text[ start + line ], x, y + line * FONT_HEIGHT, colours[ start + line ], null, 0, 0, false, Palette.DEFAULT );
 | 
			
		||||
            fontRenderer.drawString( text[start + line], x, y + line * FONT_HEIGHT, colours[start + line], null, 0, 0, false, Palette.DEFAULT );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -69,11 +74,11 @@ public class PrintoutRenderer
 | 
			
		||||
        GlStateManager.enableBlend();
 | 
			
		||||
        GlStateManager.enableTexture2D();
 | 
			
		||||
 | 
			
		||||
        FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
 | 
			
		||||
        FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance();
 | 
			
		||||
 | 
			
		||||
        for( int line = 0; line < LINES_PER_PAGE && line < text.length; ++line )
 | 
			
		||||
        for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
 | 
			
		||||
        {
 | 
			
		||||
            fontRenderer.drawString( new TextBuffer( text[ start + line ] ), x, y + line * FONT_HEIGHT, new TextBuffer( colours[ start + line ] ), null, 0, 0, false, Palette.DEFAULT );
 | 
			
		||||
            fontRenderer.drawString( new TextBuffer( text[start + line] ), x, y + line * FONT_HEIGHT, new TextBuffer( colours[start + line] ), null, 0, 0, false, Palette.DEFAULT );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -106,7 +111,7 @@ public class PrintoutRenderer
 | 
			
		||||
            // Draw centre panel (just stretched texture, sorry).
 | 
			
		||||
            drawTexture( buffer,
 | 
			
		||||
                x - offset, y, z - 0.02, X_SIZE + offset * 2, Y_SIZE,
 | 
			
		||||
                COVER_X + COVER_SIZE / 2, COVER_SIZE, COVER_SIZE, Y_SIZE
 | 
			
		||||
                COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            double borderX = left;
 | 
			
		||||
@@ -120,7 +125,7 @@ public class PrintoutRenderer
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Left half
 | 
			
		||||
        drawTexture( buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2, Y_SIZE );
 | 
			
		||||
        drawTexture( buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE );
 | 
			
		||||
        for( int n = 0; n <= leftPages; n++ )
 | 
			
		||||
        {
 | 
			
		||||
            drawTexture( buffer,
 | 
			
		||||
@@ -132,7 +137,7 @@ public class PrintoutRenderer
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Right half
 | 
			
		||||
        drawTexture( buffer, x + X_SIZE / 2, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2, 0, X_SIZE / 2, Y_SIZE );
 | 
			
		||||
        drawTexture( buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE );
 | 
			
		||||
        for( int n = 0; n <= rightPages; n++ )
 | 
			
		||||
        {
 | 
			
		||||
            drawTexture( buffer,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,15 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.PeripheralType;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.common.BlockCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.TileCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.CableBounds;
 | 
			
		||||
import dan200.computercraft.shared.util.WorldUtil;
 | 
			
		||||
import net.minecraft.block.state.IBlockState;
 | 
			
		||||
import net.minecraft.client.renderer.BufferBuilder;
 | 
			
		||||
@@ -12,23 +18,29 @@ import net.minecraft.client.renderer.RenderGlobal;
 | 
			
		||||
import net.minecraft.client.renderer.Tessellator;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
 | 
			
		||||
import net.minecraft.entity.player.EntityPlayer;
 | 
			
		||||
import net.minecraft.tileentity.TileEntity;
 | 
			
		||||
import net.minecraft.util.EnumFacing;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.RayTraceResult;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
 | 
			
		||||
import net.minecraftforge.fml.common.Mod;
 | 
			
		||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 | 
			
		||||
import net.minecraftforge.fml.relauncher.Side;
 | 
			
		||||
import org.lwjgl.opengl.GL11;
 | 
			
		||||
 | 
			
		||||
public class RenderOverlayCable
 | 
			
		||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
 | 
			
		||||
public final class RenderOverlayCable
 | 
			
		||||
{
 | 
			
		||||
    private static final float EXPAND = 0.002f;
 | 
			
		||||
    private static final double MIN = TileCable.MIN - EXPAND;
 | 
			
		||||
    private static final double MAX = TileCable.MAX + EXPAND;
 | 
			
		||||
    private static final double MIN = CableBounds.MIN - EXPAND;
 | 
			
		||||
    private static final double MAX = CableBounds.MAX + EXPAND;
 | 
			
		||||
 | 
			
		||||
    private RenderOverlayCable()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SubscribeEvent
 | 
			
		||||
    public void drawHighlight( DrawBlockHighlightEvent event )
 | 
			
		||||
    public static void drawHighlight( DrawBlockHighlightEvent event )
 | 
			
		||||
    {
 | 
			
		||||
        if( event.getTarget().typeOfHit != RayTraceResult.Type.BLOCK ) return;
 | 
			
		||||
 | 
			
		||||
@@ -38,13 +50,10 @@ public class RenderOverlayCable
 | 
			
		||||
        IBlockState state = world.getBlockState( pos );
 | 
			
		||||
        if( state.getBlock() != ComputerCraft.Blocks.cable ) return;
 | 
			
		||||
 | 
			
		||||
        TileEntity tile = world.getTileEntity( pos );
 | 
			
		||||
        if( tile == null || !(tile instanceof TileCable) ) return;
 | 
			
		||||
        state = state.getActualState( world, pos );
 | 
			
		||||
 | 
			
		||||
        event.setCanceled( true );
 | 
			
		||||
        TileCable cable = (TileCable) tile;
 | 
			
		||||
 | 
			
		||||
        PeripheralType type = cable.getPeripheralType();
 | 
			
		||||
        PeripheralType type = ComputerCraft.Blocks.cable.getPeripheralType( state );
 | 
			
		||||
 | 
			
		||||
        GlStateManager.enableBlend();
 | 
			
		||||
        GlStateManager.tryBlendFuncSeparate( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0 );
 | 
			
		||||
@@ -63,9 +72,9 @@ public class RenderOverlayCable
 | 
			
		||||
            GlStateManager.translate( -x + pos.getX(), -y + pos.getY(), -z + pos.getZ() );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( type != PeripheralType.Cable && WorldUtil.isVecInsideInclusive( cable.getModemBounds(), event.getTarget().hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) )
 | 
			
		||||
        if( type != PeripheralType.Cable && WorldUtil.isVecInsideInclusive( CableBounds.getModemBounds( state ), event.getTarget().hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) )
 | 
			
		||||
        {
 | 
			
		||||
            RenderGlobal.drawSelectionBoundingBox( cable.getModemBounds(), 0, 0, 0, 0.4f );
 | 
			
		||||
            RenderGlobal.drawSelectionBoundingBox( CableBounds.getModemBounds( state ), 0, 0, 0, 0.4f );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.PeripheralType;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.common.BlockCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.common.BlockCableModemVariant;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.TileCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.BlockCableModemVariant;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.CableBounds;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
 | 
			
		||||
import dan200.computercraft.shared.util.WorldUtil;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.block.state.IBlockState;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.BufferBuilder;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.renderer.RenderGlobal;
 | 
			
		||||
import net.minecraft.client.renderer.Tessellator;
 | 
			
		||||
import net.minecraft.client.renderer.BufferBuilder;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | 
			
		||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
 | 
			
		||||
@@ -52,7 +59,7 @@ public class TileEntityCableRenderer extends TileEntitySpecialRenderer<TileCable
 | 
			
		||||
        if( block != ComputerCraft.Blocks.cable ) return;
 | 
			
		||||
 | 
			
		||||
        state = state.getActualState( world, pos );
 | 
			
		||||
        if( te.getPeripheralType() != PeripheralType.Cable && WorldUtil.isVecInsideInclusive( te.getModemBounds(), hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) )
 | 
			
		||||
        if( te.getPeripheralType() != PeripheralType.Cable && WorldUtil.isVecInsideInclusive( CableBounds.getModemBounds( state ), hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) )
 | 
			
		||||
        {
 | 
			
		||||
            state = block.getDefaultState().withProperty( BlockCable.Properties.MODEM, state.getValue( BlockCable.Properties.MODEM ) );
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.client.render;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.client.FrameInfo;
 | 
			
		||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
 | 
			
		||||
import dan200.computercraft.core.terminal.Terminal;
 | 
			
		||||
import dan200.computercraft.core.terminal.TextBuffer;
 | 
			
		||||
@@ -28,10 +28,6 @@ import org.lwjgl.opengl.GL11;
 | 
			
		||||
 | 
			
		||||
public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMonitor>
 | 
			
		||||
{
 | 
			
		||||
    public TileEntityMonitorRenderer()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void render( TileMonitor tileEntity, double posX, double posY, double posZ, float f, int i, float f2 )
 | 
			
		||||
    {
 | 
			
		||||
@@ -51,9 +47,9 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
        BlockPos monitorPos = monitor.getPos();
 | 
			
		||||
 | 
			
		||||
        // Ensure each monitor terminal is rendered only once. We allow rendering a specific tile
 | 
			
		||||
        // multiple times in a single frame to ensure compatibility with shaders which may run a 
 | 
			
		||||
        // multiple times in a single frame to ensure compatibility with shaders which may run a
 | 
			
		||||
        // pass multiple times.
 | 
			
		||||
        long renderFrame = ComputerCraft.getRenderFrame();
 | 
			
		||||
        long renderFrame = FrameInfo.getRenderFrame();
 | 
			
		||||
        if( originTerminal.lastRenderFrame == renderFrame && !monitorPos.equals( originTerminal.lastRenderPos ) )
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
@@ -70,7 +66,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
        // Determine orientation
 | 
			
		||||
        EnumFacing dir = origin.getDirection();
 | 
			
		||||
        EnumFacing front = origin.getFront();
 | 
			
		||||
        float yaw = DirectionUtil.toYawAngle( dir );
 | 
			
		||||
        float yaw = dir.getHorizontalAngle();
 | 
			
		||||
        float pitch = DirectionUtil.toPitchAngle( front );
 | 
			
		||||
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
@@ -85,8 +81,8 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                (origin.getHeight() - 0.5) - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN),
 | 
			
		||||
                0.5
 | 
			
		||||
            );
 | 
			
		||||
            double xSize = origin.getWidth() - 2.0 * ( TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER );
 | 
			
		||||
            double ySize = origin.getHeight() - 2.0 * ( TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER );
 | 
			
		||||
            double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
 | 
			
		||||
            double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
 | 
			
		||||
 | 
			
		||||
            // Get renderers
 | 
			
		||||
            Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
@@ -121,17 +117,17 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                    int height = terminal.getHeight();
 | 
			
		||||
                    int cursorX = terminal.getCursorX();
 | 
			
		||||
                    int cursorY = terminal.getCursorY();
 | 
			
		||||
                    FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
 | 
			
		||||
                    FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance();
 | 
			
		||||
 | 
			
		||||
                    GlStateManager.pushMatrix();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        double xScale = xSize / ( width * FixedWidthFontRenderer.FONT_WIDTH );
 | 
			
		||||
                        double yScale = ySize / ( height * FixedWidthFontRenderer.FONT_HEIGHT );
 | 
			
		||||
                        double xScale = xSize / (width * FixedWidthFontRenderer.FONT_WIDTH);
 | 
			
		||||
                        double yScale = ySize / (height * FixedWidthFontRenderer.FONT_HEIGHT);
 | 
			
		||||
                        GlStateManager.scale( xScale, -yScale, 1.0 );
 | 
			
		||||
 | 
			
		||||
                        // Draw background
 | 
			
		||||
                        mc.getTextureManager().bindTexture( FixedWidthFontRenderer.background );
 | 
			
		||||
                        mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND );
 | 
			
		||||
                        if( redraw )
 | 
			
		||||
                        {
 | 
			
		||||
                            // Build background display list
 | 
			
		||||
@@ -158,14 +154,14 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                // Backgrounds
 | 
			
		||||
                                for( int y = 0; y < height; ++y )
 | 
			
		||||
                                for( int y = 0; y < height; y++ )
 | 
			
		||||
                                {
 | 
			
		||||
                                    fontRenderer.drawStringBackgroundPart(
 | 
			
		||||
                                            0, FixedWidthFontRenderer.FONT_HEIGHT * y,
 | 
			
		||||
                                            terminal.getBackgroundColourLine( y ),
 | 
			
		||||
                                            marginXSize, marginXSize,
 | 
			
		||||
                                            greyscale,
 | 
			
		||||
                                            palette
 | 
			
		||||
                                        0, FixedWidthFontRenderer.FONT_HEIGHT * y,
 | 
			
		||||
                                        terminal.getBackgroundColourLine( y ),
 | 
			
		||||
                                        marginXSize, marginXSize,
 | 
			
		||||
                                        greyscale,
 | 
			
		||||
                                        palette
 | 
			
		||||
                                    );
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
@@ -186,14 +182,14 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                // Lines
 | 
			
		||||
                                for( int y = 0; y < height; ++y )
 | 
			
		||||
                                for( int y = 0; y < height; y++ )
 | 
			
		||||
                                {
 | 
			
		||||
                                    fontRenderer.drawStringTextPart(
 | 
			
		||||
                                            0, FixedWidthFontRenderer.FONT_HEIGHT * y,
 | 
			
		||||
                                            terminal.getLine( y ),
 | 
			
		||||
                                            terminal.getTextColourLine( y ),
 | 
			
		||||
                                            greyscale,
 | 
			
		||||
                                            palette
 | 
			
		||||
                                        0, FixedWidthFontRenderer.FONT_HEIGHT * y,
 | 
			
		||||
                                        terminal.getLine( y ),
 | 
			
		||||
                                        terminal.getTextColourLine( y ),
 | 
			
		||||
                                        greyscale,
 | 
			
		||||
                                        palette
 | 
			
		||||
                                    );
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
@@ -219,13 +215,13 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                                    TextBuffer cursor = new TextBuffer( "_" );
 | 
			
		||||
                                    TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 );
 | 
			
		||||
                                    fontRenderer.drawString(
 | 
			
		||||
                                            cursor,
 | 
			
		||||
                                            FixedWidthFontRenderer.FONT_WIDTH * cursorX,
 | 
			
		||||
                                            FixedWidthFontRenderer.FONT_HEIGHT * cursorY,
 | 
			
		||||
                                            cursorColour, null,
 | 
			
		||||
                                            0, 0,
 | 
			
		||||
                                            greyscale,
 | 
			
		||||
                                            palette
 | 
			
		||||
                                        cursor,
 | 
			
		||||
                                        FixedWidthFontRenderer.FONT_WIDTH * cursorX,
 | 
			
		||||
                                        FixedWidthFontRenderer.FONT_HEIGHT * cursorY,
 | 
			
		||||
                                        cursorColour, null,
 | 
			
		||||
                                        0, 0,
 | 
			
		||||
                                        greyscale,
 | 
			
		||||
                                        palette
 | 
			
		||||
                                    );
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
@@ -234,7 +230,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                                GlStateManager.glEndList();
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        if( ComputerCraft.getGlobalCursorBlink() )
 | 
			
		||||
                        if( FrameInfo.getGlobalCursorBlink() )
 | 
			
		||||
                        {
 | 
			
		||||
                            GlStateManager.callList( originTerminal.renderDisplayLists[2] );
 | 
			
		||||
                            GlStateManager.resetColor();
 | 
			
		||||
@@ -248,7 +244,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // Draw a big black quad
 | 
			
		||||
                    mc.getTextureManager().bindTexture( FixedWidthFontRenderer.background );
 | 
			
		||||
                    mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND );
 | 
			
		||||
                    final Colour colour = Colour.Black;
 | 
			
		||||
 | 
			
		||||
                    final float r = colour.getR();
 | 
			
		||||
@@ -274,7 +270,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
 | 
			
		||||
            GlStateManager.colorMask( false, false, false, false );
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                mc.getTextureManager().bindTexture( FixedWidthFontRenderer.background );
 | 
			
		||||
                mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND );
 | 
			
		||||
                renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION );
 | 
			
		||||
                renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
 | 
			
		||||
                renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -10,29 +10,24 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
 | 
			
		||||
import dan200.computercraft.api.turtle.TurtleSide;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
 | 
			
		||||
import dan200.computercraft.shared.turtle.entity.TurtleVisionCamera;
 | 
			
		||||
import dan200.computercraft.shared.util.Holiday;
 | 
			
		||||
import dan200.computercraft.shared.util.HolidayUtil;
 | 
			
		||||
import net.minecraft.block.state.IBlockState;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.gui.FontRenderer;
 | 
			
		||||
import net.minecraft.client.renderer.BufferBuilder;
 | 
			
		||||
import net.minecraft.client.renderer.EntityRenderer;
 | 
			
		||||
import net.minecraft.client.renderer.GlStateManager;
 | 
			
		||||
import net.minecraft.client.renderer.Tessellator;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.BakedQuad;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelManager;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
 | 
			
		||||
import net.minecraft.client.renderer.entity.RenderManager;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureMap;
 | 
			
		||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.VertexFormat;
 | 
			
		||||
import net.minecraft.entity.Entity;
 | 
			
		||||
import net.minecraft.util.EnumFacing;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.RayTraceResult;
 | 
			
		||||
import net.minecraft.util.math.Vec3d;
 | 
			
		||||
import net.minecraftforge.client.ForgeHooksClient;
 | 
			
		||||
import net.minecraftforge.client.model.pipeline.LightUtil;
 | 
			
		||||
@@ -44,36 +39,15 @@ import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurtle>
 | 
			
		||||
{
 | 
			
		||||
    private static ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle", "inventory" );
 | 
			
		||||
    private static ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_advanced", "inventory" );
 | 
			
		||||
    private static ModelResourceLocation COLOUR_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_white", "inventory" );
 | 
			
		||||
    private static ModelResourceLocation BEGINNER_TURTLE_MODEL = new ModelResourceLocation( "computercraftedu:CC-TurtleJunior", "inventory" );
 | 
			
		||||
    private static ModelResourceLocation BEGINNER_TURTLE_COLOUR_MODEL = new ModelResourceLocation( "computercraftedu:turtleJunior_white", "inventory" );
 | 
			
		||||
    private static ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" );
 | 
			
		||||
 | 
			
		||||
    public TileEntityTurtleRenderer()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    private static final ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle", "inventory" );
 | 
			
		||||
    private static final ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_advanced", "inventory" );
 | 
			
		||||
    private static final ModelResourceLocation COLOUR_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_white", "inventory" );
 | 
			
		||||
    private static final ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" );
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void render( TileTurtle tileEntity, double posX, double posY, double posZ, float f, int i, float f2 )
 | 
			
		||||
    {
 | 
			
		||||
        if( tileEntity != null )
 | 
			
		||||
        {
 | 
			
		||||
            // Check the turtle isn't first person
 | 
			
		||||
            Entity viewEntity = Minecraft.getMinecraft().getRenderViewEntity();
 | 
			
		||||
            if( viewEntity != null && viewEntity instanceof TurtleVisionCamera )
 | 
			
		||||
            {
 | 
			
		||||
                TurtleVisionCamera camera = (TurtleVisionCamera) viewEntity;
 | 
			
		||||
                if( camera.getTurtle() == tileEntity.getAccess() )
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Render the turtle
 | 
			
		||||
            renderTurtleAt( tileEntity, posX, posY, posZ, f, i );
 | 
			
		||||
        }
 | 
			
		||||
        if( tileEntity != null ) renderTurtleAt( tileEntity, posX, posY, posZ, f, i );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ModelResourceLocation getTurtleModel( ComputerFamily family, boolean coloured )
 | 
			
		||||
@@ -85,18 +59,16 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
                return coloured ? COLOUR_TURTLE_MODEL : NORMAL_TURTLE_MODEL;
 | 
			
		||||
            case Advanced:
 | 
			
		||||
                return coloured ? COLOUR_TURTLE_MODEL : ADVANCED_TURTLE_MODEL;
 | 
			
		||||
            case Beginners:
 | 
			
		||||
                return coloured ? BEGINNER_TURTLE_COLOUR_MODEL : BEGINNER_TURTLE_MODEL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ModelResourceLocation getTurtleOverlayModel( ComputerFamily family, ResourceLocation overlay, boolean christmas )
 | 
			
		||||
    public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
 | 
			
		||||
    {
 | 
			
		||||
        if( overlay != null )
 | 
			
		||||
        {
 | 
			
		||||
            return new ModelResourceLocation( overlay, "inventory" );
 | 
			
		||||
        }
 | 
			
		||||
        else if( christmas && family != ComputerFamily.Beginners )
 | 
			
		||||
        else if( christmas )
 | 
			
		||||
        {
 | 
			
		||||
            return ELF_OVERLAY_MODEL;
 | 
			
		||||
        }
 | 
			
		||||
@@ -108,6 +80,19 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
 | 
			
		||||
    private void renderTurtleAt( TileTurtle turtle, double posX, double posY, double posZ, float f, int i )
 | 
			
		||||
    {
 | 
			
		||||
        // Render the label
 | 
			
		||||
        String label = turtle.createProxy().getLabel();
 | 
			
		||||
        if( label != null && rendererDispatcher.cameraHitResult != null && turtle.getPos().equals( rendererDispatcher.cameraHitResult.getBlockPos() ) )
 | 
			
		||||
        {
 | 
			
		||||
            setLightmapDisabled( true );
 | 
			
		||||
            EntityRenderer.drawNameplate(
 | 
			
		||||
                getFontRenderer(), label,
 | 
			
		||||
                (float) posX + 0.5F, (float) posY + 1.2F, (float) posZ + 0.5F, 0,
 | 
			
		||||
                rendererDispatcher.entityYaw, rendererDispatcher.entityPitch, false, false
 | 
			
		||||
            );
 | 
			
		||||
            setLightmapDisabled( false );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IBlockState state = turtle.getWorld().getBlockState( turtle.getPos() );
 | 
			
		||||
        GlStateManager.pushMatrix();
 | 
			
		||||
        try
 | 
			
		||||
@@ -119,13 +104,6 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
            yaw = turtle.getRenderYaw( f );
 | 
			
		||||
            GlStateManager.translate( posX + offset.x, posY + offset.y, posZ + offset.z );
 | 
			
		||||
 | 
			
		||||
            // Render the label
 | 
			
		||||
            String label = turtle.createProxy().getLabel();
 | 
			
		||||
            if( label != null )
 | 
			
		||||
            {
 | 
			
		||||
                renderLabel( turtle.getAccess().getPosition(), label );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Render the turtle
 | 
			
		||||
            GlStateManager.translate( 0.5f, 0.5f, 0.5f );
 | 
			
		||||
            GlStateManager.rotate( 180.0f - yaw, 0.0f, 1.0f, 0.0f );
 | 
			
		||||
@@ -148,7 +126,6 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
 | 
			
		||||
            // Render the overlay
 | 
			
		||||
            ModelResourceLocation overlayModel = getTurtleOverlayModel(
 | 
			
		||||
                family,
 | 
			
		||||
                overlay,
 | 
			
		||||
                HolidayUtil.getCurrentHoliday() == Holiday.Christmas
 | 
			
		||||
            );
 | 
			
		||||
@@ -192,7 +169,7 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
                GlStateManager.rotate( -toolAngle, 1.0f, 0.0f, 0.0f );
 | 
			
		||||
                GlStateManager.translate( 0.0f, -0.5f, -0.5f );
 | 
			
		||||
 | 
			
		||||
                Pair<IBakedModel, Matrix4f> pair  = upgrade.getModel( turtle.getAccess(), side );
 | 
			
		||||
                Pair<IBakedModel, Matrix4f> pair = upgrade.getModel( turtle.getAccess(), side );
 | 
			
		||||
                if( pair != null )
 | 
			
		||||
                {
 | 
			
		||||
                    if( pair.getRight() != null )
 | 
			
		||||
@@ -236,7 +213,7 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
        BufferBuilder buffer = tessellator.getBuffer();
 | 
			
		||||
        VertexFormat format = DefaultVertexFormats.ITEM;
 | 
			
		||||
        buffer.begin( GL11.GL_QUADS, format );
 | 
			
		||||
        for (BakedQuad quad : quads)
 | 
			
		||||
        for( BakedQuad quad : quads )
 | 
			
		||||
        {
 | 
			
		||||
            VertexFormat quadFormat = quad.getFormat();
 | 
			
		||||
            if( quadFormat != format )
 | 
			
		||||
@@ -250,79 +227,11 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
			
		||||
            if( quad.hasTintIndex() && tints != null )
 | 
			
		||||
            {
 | 
			
		||||
                int index = quad.getTintIndex();
 | 
			
		||||
                if( index >= 0 && index < tints.length ) colour = tints[ index ] | 0xFF000000;
 | 
			
		||||
                if( index >= 0 && index < tints.length ) colour = tints[index] | 0xFF000000;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            LightUtil.renderQuadColor( buffer, quad, colour );
 | 
			
		||||
        }
 | 
			
		||||
        tessellator.draw();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void renderLabel( BlockPos position, String label )
 | 
			
		||||
    {
 | 
			
		||||
        Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
        RayTraceResult mop = mc.objectMouseOver;
 | 
			
		||||
        if( mop != null && mop.typeOfHit == RayTraceResult.Type.BLOCK && mop.getBlockPos().equals( position ) )
 | 
			
		||||
        {
 | 
			
		||||
            RenderManager renderManager = mc.getRenderManager();
 | 
			
		||||
            FontRenderer fontrenderer = renderManager.getFontRenderer();
 | 
			
		||||
            float scale = 0.016666668F * 1.6f;
 | 
			
		||||
 | 
			
		||||
            GlStateManager.pushMatrix();
 | 
			
		||||
            GlStateManager.disableLighting();
 | 
			
		||||
            GlStateManager.enableBlend();
 | 
			
		||||
            GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA );
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                GlStateManager.translate( 0.5f, 1.25f, 0.5f );
 | 
			
		||||
                GlStateManager.rotate( -renderManager.playerViewY, 0.0F, 1.0F, 0.0F );
 | 
			
		||||
                GlStateManager.rotate( renderManager.playerViewX, 1.0F, 0.0F, 0.0F );
 | 
			
		||||
                GlStateManager.scale( -scale, -scale, scale );
 | 
			
		||||
 | 
			
		||||
                int yOffset = 0;
 | 
			
		||||
                int xOffset = fontrenderer.getStringWidth( label ) / 2;
 | 
			
		||||
 | 
			
		||||
                // Draw background
 | 
			
		||||
                GlStateManager.depthMask( false );
 | 
			
		||||
                GlStateManager.disableDepth();
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    // Quad
 | 
			
		||||
                    GlStateManager.disableTexture2D();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        Tessellator tessellator = Tessellator.getInstance();
 | 
			
		||||
                        BufferBuilder renderer = tessellator.getBuffer();
 | 
			
		||||
                        renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR );
 | 
			
		||||
                        renderer.pos( -xOffset - 1, -1 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
 | 
			
		||||
                        renderer.pos( -xOffset - 1, 8 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
 | 
			
		||||
                        renderer.pos( xOffset + 1, 8 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
 | 
			
		||||
                        renderer.pos( xOffset + 1, -1 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
 | 
			
		||||
                        tessellator.draw();
 | 
			
		||||
                    }
 | 
			
		||||
                    finally
 | 
			
		||||
                    {
 | 
			
		||||
                        GlStateManager.enableTexture2D();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Text
 | 
			
		||||
                    fontrenderer.drawString( label, -fontrenderer.getStringWidth( label ) / 2, yOffset, 0x20ffffff );
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    GlStateManager.enableDepth();
 | 
			
		||||
                    GlStateManager.depthMask( true );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Draw foreground text
 | 
			
		||||
                fontrenderer.drawString( label, -fontrenderer.getStringWidth( label ) / 2, yOffset, -1 );
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                GlStateManager.disableBlend();
 | 
			
		||||
                GlStateManager.enableLighting();
 | 
			
		||||
                GlStateManager.popMatrix();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,121 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableMap;
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | 
			
		||||
import net.minecraft.client.renderer.vertex.VertexFormat;
 | 
			
		||||
import net.minecraft.client.resources.IResourceManager;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraftforge.client.model.ICustomModelLoader;
 | 
			
		||||
import net.minecraftforge.client.model.IModel;
 | 
			
		||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
 | 
			
		||||
import net.minecraftforge.common.model.IModelState;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
 | 
			
		||||
public class TurtleModelLoader implements ICustomModelLoader
 | 
			
		||||
{
 | 
			
		||||
    private static final ResourceLocation NORMAL_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle" );
 | 
			
		||||
    private static final ResourceLocation ADVANCED_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/advanced_turtle" );
 | 
			
		||||
    private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_white" );
 | 
			
		||||
 | 
			
		||||
    public static final TurtleModelLoader INSTANCE = new TurtleModelLoader();
 | 
			
		||||
 | 
			
		||||
    private TurtleModelLoader()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onResourceManagerReload( @Nonnull IResourceManager manager )
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean accepts( @Nonnull ResourceLocation name )
 | 
			
		||||
    {
 | 
			
		||||
        return name.getNamespace().equals( ComputerCraft.MOD_ID )
 | 
			
		||||
            && (name.getPath().equals( "turtle" ) || name.getPath().equals( "turtle_advanced" ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public IModel loadModel( @Nonnull ResourceLocation name ) throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        if( name.getNamespace().equals( ComputerCraft.MOD_ID ) )
 | 
			
		||||
        {
 | 
			
		||||
            IModel colourModel = ModelLoaderRegistry.getModel( COLOUR_TURTLE_MODEL );
 | 
			
		||||
            switch( name.getPath() )
 | 
			
		||||
            {
 | 
			
		||||
                case "turtle":
 | 
			
		||||
                    return new TurtleModel( ModelLoaderRegistry.getModel( NORMAL_TURTLE_MODEL ), colourModel );
 | 
			
		||||
                case "turtle_advanced":
 | 
			
		||||
                    return new TurtleModel( ModelLoaderRegistry.getModel( ADVANCED_TURTLE_MODEL ), colourModel );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new IllegalStateException( "Loader does not accept " + name );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class TurtleModel implements IModel
 | 
			
		||||
    {
 | 
			
		||||
        private final IModel family;
 | 
			
		||||
        private final IModel colour;
 | 
			
		||||
 | 
			
		||||
        private TurtleModel( IModel family, IModel colour )
 | 
			
		||||
        {
 | 
			
		||||
            this.family = family;
 | 
			
		||||
            this.colour = colour;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public IBakedModel bake( @Nonnull IModelState state, @Nonnull VertexFormat format, @Nonnull Function<ResourceLocation, TextureAtlasSprite> function )
 | 
			
		||||
        {
 | 
			
		||||
            return new TurtleSmartItemModel(
 | 
			
		||||
                family.bake( state, format, function ),
 | 
			
		||||
                colour.bake( state, format, function )
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private TurtleModel copy( IModel family, IModel colour )
 | 
			
		||||
        {
 | 
			
		||||
            return this.family == family && this.colour == colour ? this : new TurtleModel( family, colour );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public IModel smoothLighting( boolean value )
 | 
			
		||||
        {
 | 
			
		||||
            return copy( family.smoothLighting( value ), colour.smoothLighting( value ) );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public IModel gui3d( boolean value )
 | 
			
		||||
        {
 | 
			
		||||
            return copy( family.gui3d( value ), colour.gui3d( value ) );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public IModel uvlock( boolean value )
 | 
			
		||||
        {
 | 
			
		||||
            return copy( family.uvlock( value ), colour.uvlock( value ) );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public IModel retexture( ImmutableMap<String, String> textures )
 | 
			
		||||
        {
 | 
			
		||||
            return copy( family.retexture( textures ), colour.retexture( textures ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.client.render;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.block.state.IBlockState;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -9,7 +9,6 @@ package dan200.computercraft.client.render;
 | 
			
		||||
import com.google.common.base.Objects;
 | 
			
		||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
 | 
			
		||||
import dan200.computercraft.api.turtle.TurtleSide;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.turtle.items.ItemTurtleBase;
 | 
			
		||||
import dan200.computercraft.shared.util.Holiday;
 | 
			
		||||
import dan200.computercraft.shared.util.HolidayUtil;
 | 
			
		||||
@@ -17,15 +16,11 @@ import net.minecraft.block.state.IBlockState;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.renderer.block.model.*;
 | 
			
		||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | 
			
		||||
import net.minecraft.client.resources.IResourceManager;
 | 
			
		||||
import net.minecraft.entity.EntityLivingBase;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.EnumFacing;
 | 
			
		||||
import net.minecraft.util.ResourceLocation;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraftforge.client.resource.IResourceType;
 | 
			
		||||
import net.minecraftforge.client.resource.ISelectiveResourceReloadListener;
 | 
			
		||||
import net.minecraftforge.client.resource.VanillaResourceType;
 | 
			
		||||
import org.apache.commons.lang3.tuple.Pair;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
@@ -34,9 +29,8 @@ import javax.vecmath.Matrix4f;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.function.Predicate;
 | 
			
		||||
 | 
			
		||||
public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceReloadListener
 | 
			
		||||
public class TurtleSmartItemModel implements IBakedModel
 | 
			
		||||
{
 | 
			
		||||
    private static final Matrix4f s_identity, s_flip;
 | 
			
		||||
 | 
			
		||||
@@ -53,17 +47,15 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
 | 
			
		||||
    private static class TurtleModelCombination
 | 
			
		||||
    {
 | 
			
		||||
        public final ComputerFamily m_family;
 | 
			
		||||
        public final boolean m_colour;
 | 
			
		||||
        public final ITurtleUpgrade m_leftUpgrade;
 | 
			
		||||
        public final ITurtleUpgrade m_rightUpgrade;
 | 
			
		||||
        public final ResourceLocation m_overlay;
 | 
			
		||||
        public final boolean m_christmas;
 | 
			
		||||
        public final boolean m_flip;
 | 
			
		||||
        final boolean m_colour;
 | 
			
		||||
        final ITurtleUpgrade m_leftUpgrade;
 | 
			
		||||
        final ITurtleUpgrade m_rightUpgrade;
 | 
			
		||||
        final ResourceLocation m_overlay;
 | 
			
		||||
        final boolean m_christmas;
 | 
			
		||||
        final boolean m_flip;
 | 
			
		||||
 | 
			
		||||
        public TurtleModelCombination( ComputerFamily family, boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
 | 
			
		||||
        TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
 | 
			
		||||
        {
 | 
			
		||||
            m_family = family;
 | 
			
		||||
            m_colour = colour;
 | 
			
		||||
            m_leftUpgrade = leftUpgrade;
 | 
			
		||||
            m_rightUpgrade = rightUpgrade;
 | 
			
		||||
@@ -75,33 +67,23 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
        @Override
 | 
			
		||||
        public boolean equals( Object other )
 | 
			
		||||
        {
 | 
			
		||||
            if( other == this )
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if( other instanceof TurtleModelCombination )
 | 
			
		||||
            {
 | 
			
		||||
                TurtleModelCombination otherCombo = (TurtleModelCombination) other;
 | 
			
		||||
                if( otherCombo.m_family == m_family &&
 | 
			
		||||
                    otherCombo.m_colour == m_colour &&
 | 
			
		||||
                    otherCombo.m_leftUpgrade == m_leftUpgrade &&
 | 
			
		||||
                    otherCombo.m_rightUpgrade == m_rightUpgrade &&
 | 
			
		||||
                    Objects.equal( otherCombo.m_overlay, m_overlay ) &&
 | 
			
		||||
                    otherCombo.m_christmas == m_christmas &&
 | 
			
		||||
                    otherCombo.m_flip == m_flip )
 | 
			
		||||
                {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
            if( other == this ) return true;
 | 
			
		||||
            if( !(other instanceof TurtleModelCombination) ) return false;
 | 
			
		||||
 | 
			
		||||
            TurtleModelCombination otherCombo = (TurtleModelCombination) other;
 | 
			
		||||
            return otherCombo.m_colour == m_colour &&
 | 
			
		||||
                otherCombo.m_leftUpgrade == m_leftUpgrade &&
 | 
			
		||||
                otherCombo.m_rightUpgrade == m_rightUpgrade &&
 | 
			
		||||
                Objects.equal( otherCombo.m_overlay, m_overlay ) &&
 | 
			
		||||
                otherCombo.m_christmas == m_christmas &&
 | 
			
		||||
                otherCombo.m_flip == m_flip;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public int hashCode()
 | 
			
		||||
        {
 | 
			
		||||
            final int prime = 31;
 | 
			
		||||
            int result = 1;
 | 
			
		||||
            result = prime * result + m_family.hashCode();
 | 
			
		||||
            int result = 0;
 | 
			
		||||
            result = prime * result + (m_colour ? 1 : 0);
 | 
			
		||||
            result = prime * result + (m_leftUpgrade != null ? m_leftUpgrade.hashCode() : 0);
 | 
			
		||||
            result = prime * result + (m_rightUpgrade != null ? m_rightUpgrade.hashCode() : 0);
 | 
			
		||||
@@ -112,14 +94,18 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final IBakedModel familyModel;
 | 
			
		||||
    private final IBakedModel colourModel;
 | 
			
		||||
 | 
			
		||||
    private HashMap<TurtleModelCombination, IBakedModel> m_cachedModels;
 | 
			
		||||
    private ItemOverrideList m_overrides;
 | 
			
		||||
    private final TurtleModelCombination m_defaultCombination;
 | 
			
		||||
 | 
			
		||||
    public TurtleSmartItemModel()
 | 
			
		||||
    public TurtleSmartItemModel( IBakedModel familyModel, IBakedModel colourModel )
 | 
			
		||||
    {
 | 
			
		||||
        this.familyModel = familyModel;
 | 
			
		||||
        this.colourModel = colourModel;
 | 
			
		||||
 | 
			
		||||
        m_cachedModels = new HashMap<>();
 | 
			
		||||
        m_defaultCombination = new TurtleModelCombination( ComputerFamily.Normal, false, null, null, null, false, false );
 | 
			
		||||
        m_overrides = new ItemOverrideList( new ArrayList<>() )
 | 
			
		||||
        {
 | 
			
		||||
            @Nonnull
 | 
			
		||||
@@ -127,7 +113,6 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
            public IBakedModel handleItemState( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity )
 | 
			
		||||
            {
 | 
			
		||||
                ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
 | 
			
		||||
                ComputerFamily family = turtle.getFamily( stack );
 | 
			
		||||
                int colour = turtle.getColour( stack );
 | 
			
		||||
                ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.Left );
 | 
			
		||||
                ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
 | 
			
		||||
@@ -135,17 +120,11 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
                boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas;
 | 
			
		||||
                String label = turtle.getLabel( stack );
 | 
			
		||||
                boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
 | 
			
		||||
                TurtleModelCombination combo = new TurtleModelCombination( family, colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
 | 
			
		||||
                if( m_cachedModels.containsKey( combo ) )
 | 
			
		||||
                {
 | 
			
		||||
                    return m_cachedModels.get( combo );
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    IBakedModel model = buildModel( combo );
 | 
			
		||||
                    m_cachedModels.put( combo, model );
 | 
			
		||||
                    return model;
 | 
			
		||||
                }
 | 
			
		||||
                TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
 | 
			
		||||
 | 
			
		||||
                IBakedModel model = m_cachedModels.get( combo );
 | 
			
		||||
                if( model == null ) m_cachedModels.put( combo, model = buildModel( combo ) );
 | 
			
		||||
                return model;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
@@ -157,19 +136,13 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
        return m_overrides;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onResourceManagerReload( @Nonnull IResourceManager resourceManager, @Nonnull Predicate<IResourceType> resourcePredicate )
 | 
			
		||||
    {
 | 
			
		||||
        if( resourcePredicate.test( VanillaResourceType.MODELS ) ) m_cachedModels.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private IBakedModel buildModel( TurtleModelCombination combo )
 | 
			
		||||
    {
 | 
			
		||||
        Minecraft mc = Minecraft.getMinecraft();
 | 
			
		||||
        ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager();
 | 
			
		||||
        ModelResourceLocation baseModelLocation = TileEntityTurtleRenderer.getTurtleModel( combo.m_family, combo.m_colour );
 | 
			
		||||
        ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_family, combo.m_overlay, combo.m_christmas );
 | 
			
		||||
        IBakedModel baseModel = modelManager.getModel( baseModelLocation );
 | 
			
		||||
        ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas );
 | 
			
		||||
 | 
			
		||||
        IBakedModel baseModel = combo.m_colour ? colourModel : familyModel;
 | 
			
		||||
        IBakedModel overlayModel = (overlayModelLocation != null) ? modelManager.getModel( overlayModelLocation ) : null;
 | 
			
		||||
        Matrix4f transform = combo.m_flip ? s_flip : s_identity;
 | 
			
		||||
        Pair<IBakedModel, Matrix4f> leftModel = (combo.m_leftUpgrade != null) ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
 | 
			
		||||
@@ -192,38 +165,36 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // These should not be called:
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<BakedQuad> getQuads( IBlockState state, EnumFacing facing, long rand )
 | 
			
		||||
    {
 | 
			
		||||
        return getDefaultModel().getQuads( state, facing, rand );
 | 
			
		||||
        return familyModel.getQuads( state, facing, rand );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isAmbientOcclusion()
 | 
			
		||||
    {
 | 
			
		||||
        return getDefaultModel().isAmbientOcclusion();
 | 
			
		||||
        return familyModel.isAmbientOcclusion();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isGui3d()
 | 
			
		||||
    {
 | 
			
		||||
        return getDefaultModel().isGui3d();
 | 
			
		||||
        return familyModel.isGui3d();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isBuiltInRenderer()
 | 
			
		||||
    {
 | 
			
		||||
        return getDefaultModel().isBuiltInRenderer();
 | 
			
		||||
        return familyModel.isBuiltInRenderer();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextureAtlasSprite getParticleTexture()
 | 
			
		||||
    {
 | 
			
		||||
        return getDefaultModel().getParticleTexture();
 | 
			
		||||
        return familyModel.getParticleTexture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
@@ -231,18 +202,7 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
 | 
			
		||||
    @Deprecated
 | 
			
		||||
    public ItemCameraTransforms getItemCameraTransforms()
 | 
			
		||||
    {
 | 
			
		||||
        return getDefaultModel().getItemCameraTransforms();
 | 
			
		||||
        return familyModel.getItemCameraTransforms();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private IBakedModel getDefaultModel()
 | 
			
		||||
    {
 | 
			
		||||
        IBakedModel model = m_cachedModels.get( m_defaultCombination );
 | 
			
		||||
        if( model == null )
 | 
			
		||||
        {
 | 
			
		||||
            model = buildModel( m_defaultCombination );
 | 
			
		||||
            m_cachedModels.put( m_defaultCombination, model );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return model;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.core.apis;
 | 
			
		||||
 | 
			
		||||
import com.google.common.net.InetAddresses;
 | 
			
		||||
@@ -32,8 +38,8 @@ public class AddressPredicate
 | 
			
		||||
 | 
			
		||||
            for( int i = 0; i < entry.length; i++ )
 | 
			
		||||
            {
 | 
			
		||||
                int value = 0xFF & entry[ i ];
 | 
			
		||||
                if( value < (0xFF & min[ i ]) || value > (0xFF & max[ i ]) ) return false;
 | 
			
		||||
                int value = 0xFF & entry[i];
 | 
			
		||||
                if( value < (0xFF & min[i]) || value > (0xFF & max[i]) ) return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
@@ -85,13 +91,13 @@ public class AddressPredicate
 | 
			
		||||
                {
 | 
			
		||||
                    if( size <= 0 )
 | 
			
		||||
                    {
 | 
			
		||||
                        minBytes[ i ] &= 0;
 | 
			
		||||
                        maxBytes[ i ] |= 0xFF;
 | 
			
		||||
                        minBytes[i] &= 0;
 | 
			
		||||
                        maxBytes[i] |= 0xFF;
 | 
			
		||||
                    }
 | 
			
		||||
                    else if( size < 8 )
 | 
			
		||||
                    {
 | 
			
		||||
                        minBytes[ i ] &= 0xFF << (8 - size);
 | 
			
		||||
                        maxBytes[ i ] |= ~(0xFF << (8 - size));
 | 
			
		||||
                        minBytes[i] &= 0xFF << (8 - size);
 | 
			
		||||
                        maxBytes[i] |= ~(0xFF << (8 - size));
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    size -= 8;
 | 
			
		||||
@@ -157,12 +163,8 @@ public class AddressPredicate
 | 
			
		||||
        if( matchesAddress( address ) ) return true;
 | 
			
		||||
 | 
			
		||||
        // If we're an IPv4 address in disguise then let's check that.
 | 
			
		||||
        if( address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
 | 
			
		||||
            && matchesAddress( InetAddresses.get6to4IPv4Address( (Inet6Address) address ) ) )
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
 | 
			
		||||
            && matchesAddress( InetAddresses.get6to4IPv4Address( (Inet6Address) address ) );
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.core.apis;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Preconditions;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.LinkedHashSet;
 | 
			
		||||
 | 
			
		||||
public final class ApiFactories
 | 
			
		||||
{
 | 
			
		||||
    private ApiFactories()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final Collection<ILuaAPIFactory> factories = new LinkedHashSet<>();
 | 
			
		||||
    private static final Collection<ILuaAPIFactory> factoriesView = Collections.unmodifiableCollection( factories );
 | 
			
		||||
 | 
			
		||||
    public static void register( @Nonnull ILuaAPIFactory factory )
 | 
			
		||||
    {
 | 
			
		||||
        Preconditions.checkNotNull( factory, "provider cannot be null" );
 | 
			
		||||
        factories.add( factory );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Iterable<ILuaAPIFactory> getAll()
 | 
			
		||||
    {
 | 
			
		||||
        return factoriesView;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.core.apis;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
@@ -58,7 +64,7 @@ public final class ArgumentHelper
 | 
			
		||||
    public static double getNumber( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "number", "nil" );
 | 
			
		||||
        Object value = args[ index ];
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Number )
 | 
			
		||||
        {
 | 
			
		||||
            return ((Number) value).doubleValue();
 | 
			
		||||
@@ -77,7 +83,7 @@ public final class ArgumentHelper
 | 
			
		||||
    public static long getLong( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "number", "nil" );
 | 
			
		||||
        Object value = args[ index ];
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Number )
 | 
			
		||||
        {
 | 
			
		||||
            return checkReal( index, (Number) value ).longValue();
 | 
			
		||||
@@ -96,7 +102,7 @@ public final class ArgumentHelper
 | 
			
		||||
    public static boolean getBoolean( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "boolean", "nil" );
 | 
			
		||||
        Object value = args[ index ];
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Boolean )
 | 
			
		||||
        {
 | 
			
		||||
            return (Boolean) value;
 | 
			
		||||
@@ -111,7 +117,7 @@ public final class ArgumentHelper
 | 
			
		||||
    public static String getString( @Nonnull Object[] args, int index ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        if( index >= args.length ) throw badArgument( index, "string", "nil" );
 | 
			
		||||
        Object value = args[ index ];
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof String )
 | 
			
		||||
        {
 | 
			
		||||
            return (String) value;
 | 
			
		||||
@@ -122,12 +128,12 @@ public final class ArgumentHelper
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings("unchecked")
 | 
			
		||||
    @SuppressWarnings( "unchecked" )
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    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 ];
 | 
			
		||||
        Object value = args[index];
 | 
			
		||||
        if( value instanceof Map )
 | 
			
		||||
        {
 | 
			
		||||
            return (Map<Object, Object>) value;
 | 
			
		||||
@@ -140,7 +146,7 @@ public final class ArgumentHelper
 | 
			
		||||
 | 
			
		||||
    public static double optNumber( @Nonnull Object[] args, int index, double def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[ index ] : null;
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
@@ -162,7 +168,7 @@ public final class ArgumentHelper
 | 
			
		||||
 | 
			
		||||
    public static long optLong( @Nonnull Object[] args, int index, long def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[ index ] : null;
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
@@ -184,7 +190,7 @@ public final class ArgumentHelper
 | 
			
		||||
 | 
			
		||||
    public static boolean optBoolean( @Nonnull Object[] args, int index, boolean def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[ index ] : null;
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
@@ -201,7 +207,7 @@ public final class ArgumentHelper
 | 
			
		||||
 | 
			
		||||
    public static String optString( @Nonnull Object[] args, int index, String def ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        Object value = index < args.length ? args[ index ] : null;
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
@@ -216,10 +222,10 @@ public final class ArgumentHelper
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings("unchecked")
 | 
			
		||||
    @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;
 | 
			
		||||
        Object value = index < args.length ? args[index] : null;
 | 
			
		||||
        if( value == null )
 | 
			
		||||
        {
 | 
			
		||||
            return def;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,135 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.core.apis;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaAPI;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaContext;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaObject;
 | 
			
		||||
import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
import dan200.computercraft.core.terminal.TextBuffer;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.optInt;
 | 
			
		||||
 | 
			
		||||
public class BufferAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
    private static class BufferLuaObject implements ILuaObject
 | 
			
		||||
    {
 | 
			
		||||
        private TextBuffer m_buffer;
 | 
			
		||||
 | 
			
		||||
        public BufferLuaObject( TextBuffer buffer )
 | 
			
		||||
        {
 | 
			
		||||
            m_buffer = buffer;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public String[] getMethodNames()
 | 
			
		||||
        {
 | 
			
		||||
            return new String[] {
 | 
			
		||||
                "len",
 | 
			
		||||
                "tostring",
 | 
			
		||||
                "read",
 | 
			
		||||
                "write",
 | 
			
		||||
                "fill"
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
 | 
			
		||||
        {
 | 
			
		||||
            switch( method )
 | 
			
		||||
            {
 | 
			
		||||
                case 0:
 | 
			
		||||
                {
 | 
			
		||||
                    // len
 | 
			
		||||
                    return new Object[] { m_buffer.length() };
 | 
			
		||||
                }
 | 
			
		||||
                case 1:
 | 
			
		||||
                {
 | 
			
		||||
                    // tostring
 | 
			
		||||
                    return new Object[] { m_buffer.toString() };
 | 
			
		||||
                }
 | 
			
		||||
                case 2:
 | 
			
		||||
                {
 | 
			
		||||
                    // read
 | 
			
		||||
                    int start = optInt( arguments, 0, 0 );
 | 
			
		||||
                    int end = optInt( arguments, 1, m_buffer.length() );
 | 
			
		||||
                    return new Object[] { m_buffer.read( start, end ) };
 | 
			
		||||
                }
 | 
			
		||||
                case 3:
 | 
			
		||||
                {
 | 
			
		||||
                    // write
 | 
			
		||||
                    String text = getString( arguments, 0 );
 | 
			
		||||
                    int start = optInt( arguments, 1, 0 );
 | 
			
		||||
                    int end = optInt( arguments, 2, start + text.length() );
 | 
			
		||||
                    m_buffer.write( text, start, end );
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
                case 4:
 | 
			
		||||
                {
 | 
			
		||||
                    // fill
 | 
			
		||||
                    String text = getString( arguments, 0 );
 | 
			
		||||
                    int start = optInt( arguments, 1, 0 );
 | 
			
		||||
                    int end = optInt( arguments, 2, m_buffer.length() );
 | 
			
		||||
                    m_buffer.fill( text, start, end );
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
                default:
 | 
			
		||||
                {
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public BufferAPI( IAPIEnvironment _env )
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getNames()
 | 
			
		||||
    {
 | 
			
		||||
        return new String[] {
 | 
			
		||||
            "buffer"
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getMethodNames()
 | 
			
		||||
    {
 | 
			
		||||
        return new String[] {
 | 
			
		||||
            "new"
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
 | 
			
		||||
    {
 | 
			
		||||
        switch( method )
 | 
			
		||||
        {
 | 
			
		||||
            case 0:
 | 
			
		||||
            {
 | 
			
		||||
                String text = getString( arguments, 0 );
 | 
			
		||||
                int repetitions = optInt( arguments, 1, 1 );
 | 
			
		||||
                if( repetitions < 0 )
 | 
			
		||||
                {
 | 
			
		||||
                    throw ArgumentHelper.badArgument( 1, "positive number", Integer.toString( repetitions ) );
 | 
			
		||||
                }
 | 
			
		||||
                TextBuffer buffer = new TextBuffer( text, repetitions );
 | 
			
		||||
                return new Object[] { new BufferLuaObject( buffer ) };
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.core.apis;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Preconditions;
 | 
			
		||||
import dan200.computercraft.api.filesystem.IMount;
 | 
			
		||||
import dan200.computercraft.api.filesystem.IWritableMount;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IComputerAccess;
 | 
			
		||||
@@ -11,6 +18,7 @@ import dan200.computercraft.core.filesystem.FileSystemException;
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public abstract class ComputerAccess implements IComputerAccess, IComputerOwned
 | 
			
		||||
@@ -33,22 +41,17 @@ public abstract class ComputerAccess implements IComputerAccess, IComputerOwned
 | 
			
		||||
        m_mounts.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String mount( @Nonnull String desiredLoc, @Nonnull IMount mount )
 | 
			
		||||
    {
 | 
			
		||||
        return mount( desiredLoc, mount, getAttachmentName() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName )
 | 
			
		||||
    {
 | 
			
		||||
        Objects.requireNonNull( desiredLoc, "desiredLocation cannot be null" );
 | 
			
		||||
        Objects.requireNonNull( mount, "mount cannot be null" );
 | 
			
		||||
        Objects.requireNonNull( driveName, "driveName cannot be null" );
 | 
			
		||||
 | 
			
		||||
        // Mount the location
 | 
			
		||||
        String location;
 | 
			
		||||
        FileSystem fileSystem = m_environment.getFileSystem();
 | 
			
		||||
        if( fileSystem == null )
 | 
			
		||||
        {
 | 
			
		||||
            throw new IllegalStateException( "File system has not been created" );
 | 
			
		||||
        }
 | 
			
		||||
        if( fileSystem == null ) throw new IllegalStateException( "File system has not been created" );
 | 
			
		||||
 | 
			
		||||
        synchronized( fileSystem )
 | 
			
		||||
        {
 | 
			
		||||
@@ -64,29 +67,22 @@ public abstract class ComputerAccess implements IComputerAccess, IComputerOwned
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if( location != null )
 | 
			
		||||
        {
 | 
			
		||||
            m_mounts.add( location );
 | 
			
		||||
        }
 | 
			
		||||
        return location;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount )
 | 
			
		||||
    {
 | 
			
		||||
        return mountWritable( desiredLoc, mount, getAttachmentName() );
 | 
			
		||||
        if( location != null ) m_mounts.add( location );
 | 
			
		||||
        return location;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName )
 | 
			
		||||
    {
 | 
			
		||||
        Objects.requireNonNull( desiredLoc, "desiredLocation cannot be null" );
 | 
			
		||||
        Objects.requireNonNull( mount, "mount cannot be null" );
 | 
			
		||||
        Objects.requireNonNull( driveName, "driveName cannot be null" );
 | 
			
		||||
 | 
			
		||||
        // Mount the location
 | 
			
		||||
        String location;
 | 
			
		||||
        FileSystem fileSystem = m_environment.getFileSystem();
 | 
			
		||||
        if( fileSystem == null )
 | 
			
		||||
        {
 | 
			
		||||
            throw new IllegalStateException( "File system has not been created" );
 | 
			
		||||
        }
 | 
			
		||||
        if( fileSystem == null ) throw new IllegalStateException( "File system has not been created" );
 | 
			
		||||
 | 
			
		||||
        synchronized( fileSystem )
 | 
			
		||||
        {
 | 
			
		||||
@@ -102,26 +98,19 @@ public abstract class ComputerAccess implements IComputerAccess, IComputerOwned
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if( location != null )
 | 
			
		||||
        {
 | 
			
		||||
            m_mounts.add( location );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( location != null ) m_mounts.add( location );
 | 
			
		||||
        return location;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void unmount( String location )
 | 
			
		||||
    {
 | 
			
		||||
        if( location != null )
 | 
			
		||||
        {
 | 
			
		||||
            if( !m_mounts.contains( location ) )
 | 
			
		||||
            {
 | 
			
		||||
                throw new RuntimeException( "You didn't mount this location" );
 | 
			
		||||
            }
 | 
			
		||||
        if( location == null ) return;
 | 
			
		||||
        if( !m_mounts.contains( location ) ) throw new IllegalStateException( "You didn't mount this location" );
 | 
			
		||||
 | 
			
		||||
            m_environment.getFileSystem().unmount( location );
 | 
			
		||||
            m_mounts.remove( location );
 | 
			
		||||
        }
 | 
			
		||||
        m_environment.getFileSystem().unmount( location );
 | 
			
		||||
        m_mounts.remove( location );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -133,6 +122,7 @@ public abstract class ComputerAccess implements IComputerAccess, IComputerOwned
 | 
			
		||||
    @Override
 | 
			
		||||
    public void queueEvent( @Nonnull final String event, final Object[] arguments )
 | 
			
		||||
    {
 | 
			
		||||
        Preconditions.checkNotNull( event, "event cannot be null" );
 | 
			
		||||
        m_environment.queueEvent( event, arguments );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -148,13 +138,9 @@ public abstract class ComputerAccess implements IComputerAccess, IComputerOwned
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            FileSystem fileSystem = m_environment.getFileSystem();
 | 
			
		||||
            if( !fileSystem.exists( desiredLoc ) )
 | 
			
		||||
            {
 | 
			
		||||
                return desiredLoc;
 | 
			
		||||
            }
 | 
			
		||||
            if( !fileSystem.exists( desiredLoc ) ) return desiredLoc;
 | 
			
		||||
 | 
			
		||||
            // We used to check foo2,foo3,foo4,etc here
 | 
			
		||||
            // but the disk drive does this itself now
 | 
			
		||||
            // We used to check foo2, foo3, foo4, etc here but the disk drive does this itself now
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        catch( FileSystemException e )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -33,13 +33,13 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
    private IAPIEnvironment m_env;
 | 
			
		||||
    private FileSystem m_fileSystem;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public FSAPI( IAPIEnvironment _env )
 | 
			
		||||
    {
 | 
			
		||||
        m_env = _env;
 | 
			
		||||
        m_fileSystem = null;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getNames()
 | 
			
		||||
    {
 | 
			
		||||
@@ -49,13 +49,13 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void startup( )
 | 
			
		||||
    public void startup()
 | 
			
		||||
    {
 | 
			
		||||
        m_fileSystem = m_env.getFileSystem();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void shutdown( )
 | 
			
		||||
    public void shutdown()
 | 
			
		||||
    {
 | 
			
		||||
        m_fileSystem = null;
 | 
			
		||||
    }
 | 
			
		||||
@@ -94,11 +94,13 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
                // list
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    String[] results = m_fileSystem.list( path );
 | 
			
		||||
                    Map<Object,Object> table = new HashMap<>();
 | 
			
		||||
                    for(int i=0; i<results.length; ++i ) {
 | 
			
		||||
                        table.put( i+1, results[i] );
 | 
			
		||||
                    Map<Object, Object> table = new HashMap<>();
 | 
			
		||||
                    for( int i = 0; i < results.length; i++ )
 | 
			
		||||
                    {
 | 
			
		||||
                        table.put( i + 1, results[i] );
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[] { table };
 | 
			
		||||
                }
 | 
			
		||||
@@ -118,7 +120,7 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // getName
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                return new Object[]{ FileSystem.getName( path ) };
 | 
			
		||||
                return new Object[] { FileSystem.getName( path ) };
 | 
			
		||||
            }
 | 
			
		||||
            case 3:
 | 
			
		||||
            {
 | 
			
		||||
@@ -126,7 +128,7 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[]{ m_fileSystem.getSize( path ) };
 | 
			
		||||
                    return new Object[] { m_fileSystem.getSize( path ) };
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
@@ -137,41 +139,53 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // exists
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                    return new Object[]{ m_fileSystem.exists( path ) };
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                    return new Object[]{ false };
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { m_fileSystem.exists( path ) };
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { false };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            case 5:
 | 
			
		||||
            {
 | 
			
		||||
                // isDir
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                    return new Object[]{ m_fileSystem.isDir( path ) };
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                    return new Object[]{ false };
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { m_fileSystem.isDir( path ) };
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { false };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            case 6:
 | 
			
		||||
            {
 | 
			
		||||
                // isReadOnly
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                    return new Object[]{ m_fileSystem.isReadOnly( path ) };
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                    return new Object[]{ false };
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { m_fileSystem.isReadOnly( path ) };
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { false };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            case 7:
 | 
			
		||||
            {
 | 
			
		||||
                // makeDir
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                    m_fileSystem.makeDir( path );
 | 
			
		||||
                    return null;
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -180,11 +194,14 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
                // move
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                String dest = getString( args, 1 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                    m_fileSystem.move( path, dest );
 | 
			
		||||
                    return null;
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -193,11 +210,14 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
                // copy
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                String dest = getString( args, 1 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                    m_fileSystem.copy( path, dest );
 | 
			
		||||
                    return null;
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -205,11 +225,14 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // delete
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                    m_fileSystem.delete( path );
 | 
			
		||||
                    return null;
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -219,7 +242,8 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                String mode = getString( args, 1 );
 | 
			
		||||
                m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    switch( mode )
 | 
			
		||||
                    {
 | 
			
		||||
                        case "r":
 | 
			
		||||
@@ -261,7 +285,9 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
                        default:
 | 
			
		||||
                            throw new LuaException( "Unsupported mode" );
 | 
			
		||||
                    }
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[] { null, e.getMessage() };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -269,13 +295,16 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // getDrive
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if( !m_fileSystem.exists( path ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        return null;
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[]{ m_fileSystem.getMountLabel( path ) };
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                    return new Object[] { m_fileSystem.getMountLabel( path ) };
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -283,14 +312,17 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // getFreeSpace
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    long freeSpace = m_fileSystem.getFreeSpace( path );
 | 
			
		||||
                    if( freeSpace >= 0 )
 | 
			
		||||
                    {
 | 
			
		||||
                        return new Object[]{ freeSpace };
 | 
			
		||||
                        return new Object[] { freeSpace };
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[]{ "unlimited" };
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                    return new Object[] { "unlimited" };
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -298,15 +330,19 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // find
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                try {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    m_env.addTrackingChange( TrackingField.FS_OPS );
 | 
			
		||||
                    String[] results = m_fileSystem.find( path );
 | 
			
		||||
                    Map<Object,Object> table = new HashMap<>();
 | 
			
		||||
                    for(int i=0; i<results.length; ++i ) {
 | 
			
		||||
                        table.put( i+1, results[i] );
 | 
			
		||||
                    Map<Object, Object> table = new HashMap<>();
 | 
			
		||||
                    for( int i = 0; i < results.length; i++ )
 | 
			
		||||
                    {
 | 
			
		||||
                        table.put( i + 1, results[i] );
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[] { table };
 | 
			
		||||
                } catch( FileSystemException e ) {
 | 
			
		||||
                }
 | 
			
		||||
                catch( FileSystemException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -314,11 +350,11 @@ public class FSAPI implements ILuaAPI
 | 
			
		||||
            {
 | 
			
		||||
                // getDir
 | 
			
		||||
                String path = getString( args, 0 );
 | 
			
		||||
                return new Object[]{ FileSystem.getDirectory( path ) };
 | 
			
		||||
                return new Object[] { FileSystem.getDirectory( path ) };
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                assert( false );
 | 
			
		||||
                assert (false);
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,101 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.core.apis;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaAPI;
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaContext;
 | 
			
		||||
import dan200.computercraft.api.lua.LuaException;
 | 
			
		||||
import dan200.computercraft.core.apis.http.*;
 | 
			
		||||
import dan200.computercraft.core.apis.http.request.HttpRequest;
 | 
			
		||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
 | 
			
		||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
 | 
			
		||||
import io.netty.handler.codec.http.HttpHeaders;
 | 
			
		||||
import io.netty.handler.codec.http.HttpMethod;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import java.io.Closeable;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.URI;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.concurrent.Future;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.core.apis.ArgumentHelper.*;
 | 
			
		||||
import static dan200.computercraft.core.apis.TableHelper.*;
 | 
			
		||||
 | 
			
		||||
public class HTTPAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
    private static final Set<String> HTTP_METHODS = ImmutableSet.of(
 | 
			
		||||
        "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE"
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    private final IAPIEnvironment m_apiEnvironment;
 | 
			
		||||
    private final List<Future<?>> m_httpTasks;
 | 
			
		||||
    private final Set<Closeable> m_closeables;
 | 
			
		||||
 | 
			
		||||
    private final ResourceGroup<CheckUrl> checkUrls = new ResourceGroup<>();
 | 
			
		||||
    private final ResourceGroup<HttpRequest> requests = new ResourceQueue<>( () -> ComputerCraft.httpMaxRequests );
 | 
			
		||||
    private final ResourceGroup<Websocket> websockets = new ResourceGroup<>( () -> ComputerCraft.httpMaxWebsockets );
 | 
			
		||||
 | 
			
		||||
    public HTTPAPI( IAPIEnvironment environment )
 | 
			
		||||
    {
 | 
			
		||||
        m_apiEnvironment = environment;
 | 
			
		||||
        m_httpTasks = new ArrayList<>();
 | 
			
		||||
        m_closeables = new HashSet<>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getNames()
 | 
			
		||||
    {
 | 
			
		||||
        return new String[]{
 | 
			
		||||
        return new String[] {
 | 
			
		||||
            "http"
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update()
 | 
			
		||||
    public void startup()
 | 
			
		||||
    {
 | 
			
		||||
        // Wait for all of our http requests
 | 
			
		||||
        synchronized( m_httpTasks )
 | 
			
		||||
        {
 | 
			
		||||
            Iterator<Future<?>> it = m_httpTasks.iterator();
 | 
			
		||||
            while( it.hasNext() )
 | 
			
		||||
            {
 | 
			
		||||
                final Future<?> h = it.next();
 | 
			
		||||
                if( h.isDone() ) it.remove();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        checkUrls.startup();
 | 
			
		||||
        requests.startup();
 | 
			
		||||
        websockets.startup();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void shutdown()
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( m_httpTasks )
 | 
			
		||||
        {
 | 
			
		||||
            for( Future<?> r : m_httpTasks )
 | 
			
		||||
            {
 | 
			
		||||
                r.cancel( false );
 | 
			
		||||
            }
 | 
			
		||||
            m_httpTasks.clear();
 | 
			
		||||
        }
 | 
			
		||||
        synchronized( m_closeables )
 | 
			
		||||
        {
 | 
			
		||||
            for( Closeable x : m_closeables )
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    x.close();
 | 
			
		||||
                }
 | 
			
		||||
                catch( IOException ignored )
 | 
			
		||||
                {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            m_closeables.clear();
 | 
			
		||||
        }
 | 
			
		||||
        checkUrls.shutdown();
 | 
			
		||||
        requests.shutdown();
 | 
			
		||||
        websockets.shutdown();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update()
 | 
			
		||||
    {
 | 
			
		||||
        // It's rather ugly to run this here, but we need to clean up
 | 
			
		||||
        // resources as often as possible to reduce blocking.
 | 
			
		||||
        Resource.cleanup();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getMethodNames()
 | 
			
		||||
    {
 | 
			
		||||
        return new String[]{
 | 
			
		||||
        return new String[] {
 | 
			
		||||
            "request",
 | 
			
		||||
            "checkURL",
 | 
			
		||||
            "websocket",
 | 
			
		||||
@@ -109,16 +89,16 @@ public class HTTPAPI implements ILuaAPI
 | 
			
		||||
        {
 | 
			
		||||
            case 0: // request
 | 
			
		||||
            {
 | 
			
		||||
                String urlString, postString, requestMethod;
 | 
			
		||||
                String address, postString, requestMethod;
 | 
			
		||||
                Map<Object, Object> headerTable;
 | 
			
		||||
                boolean binary, redirect;
 | 
			
		||||
 | 
			
		||||
                if( args.length >= 1 && args[0] instanceof Map )
 | 
			
		||||
                {
 | 
			
		||||
                    Map<?, ?> options = (Map) args[0];
 | 
			
		||||
                    urlString = getStringField( options, "url" );
 | 
			
		||||
                    address = getStringField( options, "url" );
 | 
			
		||||
                    postString = optStringField( options, "body", null );
 | 
			
		||||
                    headerTable = optTableField( options, "headers", null );
 | 
			
		||||
                    headerTable = optTableField( options, "headers", Collections.emptyMap() );
 | 
			
		||||
                    binary = optBooleanField( options, "binary", false );
 | 
			
		||||
                    requestMethod = optStringField( options, "method", null );
 | 
			
		||||
                    redirect = optBooleanField( options, "redirect", true );
 | 
			
		||||
@@ -127,70 +107,68 @@ public class HTTPAPI implements ILuaAPI
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // Get URL and post information
 | 
			
		||||
                    urlString = getString( args, 0 );
 | 
			
		||||
                    address = getString( args, 0 );
 | 
			
		||||
                    postString = optString( args, 1, null );
 | 
			
		||||
                    headerTable = optTable( args, 2, null );
 | 
			
		||||
                    headerTable = optTable( args, 2, Collections.emptyMap() );
 | 
			
		||||
                    binary = optBoolean( args, 3, false );
 | 
			
		||||
                    requestMethod = null;
 | 
			
		||||
                    redirect = true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Map<String, String> headers = null;
 | 
			
		||||
                if( headerTable != null )
 | 
			
		||||
                HttpHeaders headers = getHeaders( headerTable );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                HttpMethod httpMethod;
 | 
			
		||||
                if( requestMethod == null )
 | 
			
		||||
                {
 | 
			
		||||
                    headers = new HashMap<>( headerTable.size() );
 | 
			
		||||
                    for( Object key : headerTable.keySet() )
 | 
			
		||||
                    httpMethod = postString == null ? HttpMethod.GET : HttpMethod.POST;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    httpMethod = HttpMethod.valueOf( requestMethod.toUpperCase( Locale.ROOT ) );
 | 
			
		||||
                    if( httpMethod == null || requestMethod.equalsIgnoreCase( "CONNECT" ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        Object value = headerTable.get( key );
 | 
			
		||||
                        if( key instanceof String && value instanceof String )
 | 
			
		||||
                        {
 | 
			
		||||
                            headers.put( (String) key, (String) value );
 | 
			
		||||
                        }
 | 
			
		||||
                        throw new LuaException( "Unsupported HTTP method" );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                if( requestMethod != null && !HTTP_METHODS.contains( requestMethod ) )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( "Unsupported HTTP method" );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Make the request
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    URL url = HTTPRequest.checkURL( urlString );
 | 
			
		||||
                    HTTPRequest request = new HTTPRequest( m_apiEnvironment, urlString, url, postString, headers, binary, requestMethod, redirect );
 | 
			
		||||
                    synchronized( m_httpTasks )
 | 
			
		||||
                    URI uri = HttpRequest.checkUri( address );
 | 
			
		||||
 | 
			
		||||
                    HttpRequest request = new HttpRequest( requests, m_apiEnvironment, address, postString, headers, binary, redirect );
 | 
			
		||||
 | 
			
		||||
                    long requestBody = request.body().readableBytes() + HttpRequest.getHeaderSize( headers );
 | 
			
		||||
                    if( ComputerCraft.httpMaxUpload != 0 && requestBody > ComputerCraft.httpMaxUpload )
 | 
			
		||||
                    {
 | 
			
		||||
                        m_httpTasks.add( HTTPExecutor.EXECUTOR.submit( request ) );
 | 
			
		||||
                        throw new HTTPRequestException( "Request body is too large" );
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[]{ true };
 | 
			
		||||
 | 
			
		||||
                    // Make the request
 | 
			
		||||
                    request.queue( r -> r.request( uri, httpMethod ) );
 | 
			
		||||
 | 
			
		||||
                    return new Object[] { true };
 | 
			
		||||
                }
 | 
			
		||||
                catch( HTTPRequestException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[]{ false, e.getMessage() };
 | 
			
		||||
                    return new Object[] { false, e.getMessage() };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            case 1:
 | 
			
		||||
            case 1: // checkURL
 | 
			
		||||
            {
 | 
			
		||||
                // checkURL
 | 
			
		||||
                // Get URL
 | 
			
		||||
                String urlString = getString( args, 0 );
 | 
			
		||||
                String address = getString( args, 0 );
 | 
			
		||||
 | 
			
		||||
                // Check URL
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    URL url = HTTPRequest.checkURL( urlString );
 | 
			
		||||
                    HTTPCheck check = new HTTPCheck( m_apiEnvironment, urlString, url );
 | 
			
		||||
                    synchronized( m_httpTasks )
 | 
			
		||||
                    {
 | 
			
		||||
                        m_httpTasks.add( HTTPExecutor.EXECUTOR.submit( check ) );
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[]{ true };
 | 
			
		||||
                    URI uri = HttpRequest.checkUri( address );
 | 
			
		||||
                    new CheckUrl( checkUrls, m_apiEnvironment, address, uri ).queue( CheckUrl::run );
 | 
			
		||||
 | 
			
		||||
                    return new Object[] { true };
 | 
			
		||||
                }
 | 
			
		||||
                catch( HTTPRequestException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[]{ false, e.getMessage() };
 | 
			
		||||
                    return new Object[] { false, e.getMessage() };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            case 2: // websocket
 | 
			
		||||
@@ -198,36 +176,26 @@ public class HTTPAPI implements ILuaAPI
 | 
			
		||||
                String address = getString( args, 0 );
 | 
			
		||||
                Map<Object, Object> headerTbl = optTable( args, 1, Collections.emptyMap() );
 | 
			
		||||
 | 
			
		||||
                HashMap<String, String> headers = new HashMap<String, String>( headerTbl.size() );
 | 
			
		||||
                for( Object key : headerTbl.keySet() )
 | 
			
		||||
                {
 | 
			
		||||
                    Object value = headerTbl.get( key );
 | 
			
		||||
                    if( key instanceof String && value instanceof String )
 | 
			
		||||
                    {
 | 
			
		||||
                        headers.put( (String) key, (String) value );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if( !ComputerCraft.http_websocket_enable )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( "Websocket connections are disabled" );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                HttpHeaders headers = getHeaders( headerTbl );
 | 
			
		||||
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    URI uri = WebsocketConnector.checkURI( address );
 | 
			
		||||
                    int port = WebsocketConnector.getPort( uri );
 | 
			
		||||
 | 
			
		||||
                    Future<?> connector = WebsocketConnector.createConnector( m_apiEnvironment, this, uri, address, port, headers );
 | 
			
		||||
                    synchronized( m_httpTasks )
 | 
			
		||||
                    URI uri = Websocket.checkUri( address );
 | 
			
		||||
                    if( !new Websocket( websockets, m_apiEnvironment, uri, address, headers ).queue( Websocket::connect ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        m_httpTasks.add( connector );
 | 
			
		||||
                        throw new LuaException( "Too many websockets already open" );
 | 
			
		||||
                    }
 | 
			
		||||
                    return new Object[]{ true };
 | 
			
		||||
 | 
			
		||||
                    return new Object[] { true };
 | 
			
		||||
                }
 | 
			
		||||
                catch( HTTPRequestException e )
 | 
			
		||||
                {
 | 
			
		||||
                    return new Object[]{ false, e.getMessage() };
 | 
			
		||||
                    return new Object[] { false, e.getMessage() };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
@@ -237,19 +205,25 @@ public class HTTPAPI implements ILuaAPI
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addCloseable( Closeable closeable )
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    private static HttpHeaders getHeaders( @Nonnull Map<?, ?> headerTable ) throws LuaException
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( m_closeables )
 | 
			
		||||
        HttpHeaders headers = new DefaultHttpHeaders();
 | 
			
		||||
        for( Object key : headerTable.keySet() )
 | 
			
		||||
        {
 | 
			
		||||
            m_closeables.add( closeable );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void removeCloseable( Closeable closeable )
 | 
			
		||||
    {
 | 
			
		||||
        synchronized( m_closeables )
 | 
			
		||||
        {
 | 
			
		||||
            m_closeables.remove( closeable );
 | 
			
		||||
            Object value = headerTable.get( key );
 | 
			
		||||
            if( key instanceof String && value instanceof String )
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    headers.add( (String) key, value );
 | 
			
		||||
                }
 | 
			
		||||
                catch( IllegalArgumentException e )
 | 
			
		||||
                {
 | 
			
		||||
                    throw new LuaException( e.getMessage() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return headers;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of ComputerCraft - http://www.computercraft.info
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
 | 
			
		||||
 * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
 | 
			
		||||
 * Send enquiries to dratcliffe@gmail.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -14,41 +14,66 @@ import dan200.computercraft.core.filesystem.FileSystem;
 | 
			
		||||
import dan200.computercraft.core.terminal.Terminal;
 | 
			
		||||
import dan200.computercraft.core.tracking.TrackingField;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
public interface IAPIEnvironment extends IComputerOwned
 | 
			
		||||
{
 | 
			
		||||
    String[] SIDE_NAMES = new String[] {
 | 
			
		||||
        "bottom", "top", "back", "front", "right", "left",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    int SIDE_COUNT = 6;
 | 
			
		||||
 | 
			
		||||
    interface IPeripheralChangeListener
 | 
			
		||||
    {
 | 
			
		||||
        void onPeripheralChanged( int side, IPeripheral newPeripheral );
 | 
			
		||||
        void onPeripheralChanged( int side, @Nullable IPeripheral newPeripheral );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    Computer getComputer();
 | 
			
		||||
 | 
			
		||||
    int getComputerID();
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    IComputerEnvironment getComputerEnvironment();
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    Terminal getTerminal();
 | 
			
		||||
 | 
			
		||||
    FileSystem getFileSystem();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    void shutdown();
 | 
			
		||||
 | 
			
		||||
    void reboot();
 | 
			
		||||
 | 
			
		||||
    void queueEvent( String event, Object[] args );
 | 
			
		||||
 | 
			
		||||
    void setOutput( int side, int output );
 | 
			
		||||
 | 
			
		||||
    int getOutput( int side );
 | 
			
		||||
 | 
			
		||||
    int getInput( int side );
 | 
			
		||||
 | 
			
		||||
    void setBundledOutput( int side, int output );
 | 
			
		||||
 | 
			
		||||
    int getBundledOutput( int side );
 | 
			
		||||
 | 
			
		||||
    int getBundledInput( int side );
 | 
			
		||||
    
 | 
			
		||||
    void setPeripheralChangeListener( IPeripheralChangeListener listener );
 | 
			
		||||
 | 
			
		||||
    void setPeripheralChangeListener( @Nullable IPeripheralChangeListener listener );
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    IPeripheral getPeripheral( int side );
 | 
			
		||||
 | 
			
		||||
    String getLabel();
 | 
			
		||||
    void setLabel( String label );
 | 
			
		||||
 | 
			
		||||
    void addTrackingChange( TrackingField field, long change );
 | 
			
		||||
    void setLabel( @Nullable String label );
 | 
			
		||||
 | 
			
		||||
    default void addTrackingChange( TrackingField field )
 | 
			
		||||
    void addTrackingChange( @Nonnull TrackingField field, long change );
 | 
			
		||||
 | 
			
		||||
    default void addTrackingChange( @Nonnull TrackingField field )
 | 
			
		||||
    {
 | 
			
		||||
        addTrackingChange( field, 1 );
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.core.apis;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -5,10 +11,12 @@ package dan200.computercraft.core.apis;
 | 
			
		||||
 *
 | 
			
		||||
 * @see dan200.computercraft.api.lua.ILuaAPI
 | 
			
		||||
 */
 | 
			
		||||
@Deprecated
 | 
			
		||||
public interface ILuaAPI extends dan200.computercraft.api.lua.ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
    void advance( double v );
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    default void update()
 | 
			
		||||
    {
 | 
			
		||||
        advance( 0.05 );
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user