diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000000..24487ced6b
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,36 @@
+name: Java CI with Gradle
+
+on: [push, pull_request, workflow_dispatch]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up JDK 8
+ uses: actions/setup-java@v3
+ with:
+ java-version: '8'
+ distribution: 'temurin'
+ - name: Validate Gradle wrapper
+ uses: gradle/wrapper-validation-action@v1
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
+ restore-keys: ${{ runner.os }}-gradle-
+ - name: Build with Gradle
+ run: ./gradlew build
+ env:
+ GPR_USER: ${{ secrets.GPR_USER }}
+ GPR_KEY: ${{ secrets.GPR_KEY }}
+ - name: Archive artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: OpenComputers
+ path: build/libs/*.jar
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000000..f68ee4d979
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,154 @@
+name: publish
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ publish-github:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Extract Version from Tag
+ uses: rishabhgupta/split-by@v1
+ id: split_tag
+ with:
+ string: ${{ github.event.release.tag_name }}
+ split-by: '/'
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v3
+ with:
+ java-version: '8'
+ distribution: 'temurin'
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+ - name: Validate Gradle wrapper
+ uses: gradle/wrapper-validation-action@v1
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ubuntu-latest-gradle-${{ hashFiles('**/*.gradle*') }}
+ restore-keys: ubuntu-latest-gradle-
+ - name: Build with Gradle
+ run: ./gradlew -Pmod_version='${{ steps.split_tag.outputs._1 }}' build
+ env:
+ GPR_USER: ${{ secrets.GPR_USER }}
+ GPR_KEY: ${{ secrets.GPR_KEY }}
+
+ - name: Add Artifacts to Github Release
+ uses: alexellis/upload-assets@0.3.0
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ with:
+ asset_paths: '["./build/libs/*.jar"]'
+
+ - name: Publish to Github Packages
+ run: ./gradlew -Pmod_version='${{ steps.split_tag.outputs._1 }}' publish
+ env:
+ GPR_USER: ${{ secrets.GPR_USER }}
+ GPR_KEY: ${{ secrets.GPR_KEY }}
+ GITHUB_MAVEN_URL: 'https://maven.pkg.github.com/${{ github.repository }}'
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ publish-curse:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Extract Version from Tag
+ uses: rishabhgupta/split-by@v1
+ id: split_tag
+ with:
+ string: ${{ github.event.release.tag_name }}
+ split-by: '/'
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v3
+ with:
+ java-version: '8'
+ distribution: 'temurin'
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+ - name: Validate Gradle wrapper
+ uses: gradle/wrapper-validation-action@v1
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ubuntu-latest-gradle-${{ hashFiles('**/*.gradle*') }}
+ restore-keys: ubuntu-latest-gradle-
+
+ # Set Curseforge release type based on pre-release flag.
+ - name: Set release type to 'release'
+ run: |
+ echo "CURSEFORGE_RELEASE_TYPE=release" >> $GITHUB_ENV
+ if: github.event.release.prerelease == false
+ - name: Set release type to 'alpha'
+ run: |
+ echo "CURSEFORGE_RELEASE_TYPE=alpha" >> $GITHUB_ENV
+ if: github.event.release.prerelease == true
+
+ - name: Publish to Curseforge
+ run: ./gradlew -Pmod_version='${{ steps.split_tag.outputs._1 }}' curseforge
+ env:
+ GPR_USER: ${{ secrets.GPR_USER }}
+ GPR_KEY: ${{ secrets.GPR_KEY }}
+ CURSEFORGE_API_KEY: ${{ secrets.CURSEFORGE_API_KEY }}
+ CURSEFORGE_RELEASE_TYPE: ${{ env.CURSEFORGE_RELEASE_TYPE }}
+ CHANGELOG: ${{ github.event.release.body }}
+
+ publish-modrinth:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Extract Version from Tag
+ uses: rishabhgupta/split-by@v1
+ id: split_tag
+ with:
+ string: ${{ github.event.release.tag_name }}
+ split-by: '/'
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v3
+ with:
+ java-version: '8'
+ distribution: 'temurin'
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+ - name: Validate Gradle wrapper
+ uses: gradle/wrapper-validation-action@v1
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ubuntu-latest-gradle-${{ hashFiles('**/*.gradle*') }}
+ restore-keys: ubuntu-latest-gradle-
+
+ # Set Modrinth release type based on pre-release flag.
+ - name: Set release type to 'release'
+ run: |
+ echo "MODRINTH_RELEASE_TYPE=release" >> $GITHUB_ENV
+ if: github.event.release.prerelease == false
+ - name: Set release type to 'alpha'
+ run: |
+ echo "MODRINTH_RELEASE_TYPE=alpha" >> $GITHUB_ENV
+ if: github.event.release.prerelease == true
+
+ - name: Publish to Modrinth
+ run: ./gradlew -Pmod_version='${{ steps.split_tag.outputs._1 }}' modrinth
+ env:
+ GPR_USER: ${{ secrets.GPR_USER }}
+ GPR_KEY: ${{ secrets.GPR_KEY }}
+ MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
+ MODRINTH_RELEASE_TYPE: ${{ env.MODRINTH_RELEASE_TYPE }}
+ CHANGELOG: ${{ github.event.release.body }}
diff --git a/build.gradle b/build.gradle
index 18e2e0553b..34c5061425 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,27 +1,23 @@
-// For those who want the bleeding edge
buildscript {
repositories {
- jcenter()
- maven {
- name = "forge"
- url = "https://files.minecraftforge.net/maven"
- }
+ maven { url = 'https://maven.minecraftforge.net' }
+ mavenCentral()
}
dependencies {
- classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
+ classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
}
}
plugins {
- id "com.matthewprenger.cursegradle" version "1.0.9"
+ id "com.matthewprenger.cursegradle" version "1.4.0"
+ id 'com.modrinth.minotaur' version '2.2.0'
}
apply plugin: 'scala'
-apply plugin: 'net.minecraftforge.gradle.forge'
+apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'maven-publish'
-sourceCompatibility = JavaVersion.VERSION_1_7
-targetCompatibility = JavaVersion.VERSION_1_7
+java.toolchain.languageVersion = JavaLanguageVersion.of(8)
file "build.properties" withReader {
def prop = new Properties()
@@ -29,7 +25,11 @@ file "build.properties" withReader {
ext.config = new ConfigSlurper().parse prop
}
-version = config.mod.version
+version = "${mod_version}"
+if (version.endsWith("-snapshot")) {
+ version += "-" + (new Date().format('yyyyMMdd'))
+}
+
group = config.mod.group
archivesBaseName = config.mod.name
@@ -46,119 +46,162 @@ def getGitRef() {
}
}
-if (System.getenv("PROMOTED_NUMBER") != null)
- version += ".${System.getenv("PROMOTED_NUMBER")}"
-else if (System.getenv("BUILD_NUMBER") != null)
- version += ".${System.getenv("BUILD_NUMBER")}"
-else
- version += "+" + getGitRef()
+version += "+" + getGitRef()
ext.simpleVersion = version
version = "MC${config.minecraft.version}-${project.version}"
minecraft {
- version = "${config.minecraft.version}-${config.forge.version}"
- runDir = "run"
+ mappings channel: "official", version: config.minecraft.version
+
+ accessTransformer = file("src/main/resources/META-INF/accesstransformer.cfg")
- mappings = config.minecraft.mappings
+ runs {
+ client {
+ workingDirectory project.file("run")
+ property "forge.logging.markers", "REGISTRIES"
+ property "forge.logging.console.level", "debug"
+ environment "MOD_CLASSES", "opencomputers%%"
+ }
- replace "@VERSION@", project.simpleVersion
- replace "/*@MCVERSIONDEP@*/", ", acceptedMinecraftVersions = \"[${config.minecraft.version}]\""
+ server {
+ workingDirectory project.file("run")
+ property "forge.logging.markers", "REGISTRIES"
+ property "forge.logging.console.level", "debug"
+ environment "MOD_CLASSES", "opencomputers%%"
+ }
+ }
}
repositories {
- maven { url "https://maven.cil.li/" }
- maven { url "https://minecraft.curseforge.com/api/maven/" }
+ maven {
+ url "https://cursemaven.com"
+ content {
+ includeGroup "curse.maven"
+ }
+ }
+ maven {
+ url "https://maven.cil.li/"
+ content {
+ includeGroup "li.cil.tis3d"
+ }
+ }
+ ivy {
+ name 'asie dependency mirror'
+ artifactPattern "http://asie.pl/javadeps/[module]-[revision](-[classifier]).[ext]"
+ content {
+ includeModule '', 'OC-LuaJ'
+ includeModule '', 'OC-JNLua'
+ includeModule '', 'OC-JNLua-Natives'
+ }
+ metadataSources {
+ artifact()
+ }
+ }
+ maven {
+ url "https://dvs1.progwml6.com/files/maven"
+ content {
+ includeGroup "mezz.jei"
+ }
+ }
+ maven {
+ url "https://chickenbones.net/maven/"
+ content {
+ includeGroup "codechicken"
+ includeGroup "mrtjp"
+ }
+ }
+ maven {
+ url "https://squiddev.cc/maven/"
+ content {
+ includeGroup "org.squiddev"
+ }
+ }
+ maven {
+ url "https://modmaven.dev/"
+ content {
+ includeGroup "appeng"
+ includeGroup "mekanism"
+ }
+ }
+ maven {
+ url "https://proxy-maven.covers1624.net/"
+ content {
+ includeModule "net.minecraftforge", "Scorge"
+ }
+ }
+ mavenCentral()
}
configurations {
embedded
- compile.extendsFrom provided, embedded
+ implementation.extendsFrom embedded
+}
+
+task devJar(type: Jar) {
+ classifier = 'dev'
+ dependsOn(jar.dependsOn)
+ from(jar.source)
}
dependencies {
- deobfCompile ("li.cil.tis3d:TIS-3D:MC1.12-${config.tis3d.version}") {
- exclude module: "jei_1.12"
- }
- deobfCompile "com.mod-buildcraft:buildcraft-api:${config.buildcraft.version}"
- deobfCompile "MCMultiPart2:MCMultiPart-exp:${config.mcmp.version}"
- provided ("net.sengir.forestry:forestry_1.12.2:${config.forestry.version}") {
- exclude module: "jei_1.12"
- }
- deobfCompile "net.industrial-craft:industrialcraft-2:${config.ic2.version}"
- deobfCompile "mcp.mobius.waila:Hwyla:${config.hwyla.version}:api"
- deobfCompile "dan200.computercraft:ComputerCraft:${config.cc.version}"
- deobfCompile "charset:Charset:${config.charset.version}:api"
-
- provided ("appeng:appliedenergistics2:${config.ae2.version}:api") {
+ var jeiSlug = "jei-${config.minecraft.version}"
+ minecraft "net.minecraftforge:forge:${config.minecraft.version}-${config.forge.version}"
+ runtimeOnly files(devJar.archiveFile)
+
+ compileOnly "org.scala-lang:scala-library:2.13.4"
+ implementation "net.minecraftforge:Scorge:${config.scorge.version}"
+ embedded "com.typesafe:config:1.2.1"
+
+ compileOnly fg.deobf("li.cil.tis3d:tis3d-1.16.5-forge:${config.tis3d.version}")
+ compileOnly fg.deobf("curse.maven:hwyla-${config.hwyla.projectId}:${config.hwyla.fileId}")
+ compileOnly fg.deobf("org.squiddev:cc-tweaked-${config.minecraft.version}:${config.cct.version}")
+
+ compileOnly ("appeng:appliedenergistics2:${config.ae2.version}:api") {
transitive = false
}
- provided "extracells2:ExtraCells-api:${config.extracells.version}"
-
- provided("mekanism:Mekanism:${config.mekanism.version}:api") {
+
+ compileOnly("mekanism:Mekanism:${config.mekanism.version}:api") {
transitive = false
}
- provided ("codechicken:ForgeMultipart:${config.minecraft.version}-${config.forgemultipart.version}:universal") {
- exclude module: "jei_1.12"
+ compileOnly ("codechicken:CBMultipart:${config.cbmultipart.version}:universal") {
+ exclude module: jeiSlug
exclude module: "CodeChickenLib"
}
- provided ("codechicken:ChickenASM:${config.casm.version}")
+ compileOnly ("codechicken:ChickenASM:${config.casm.version}")
- provided "mezz.jei:jei_${config.minecraft.version}:${config.jei.version}"
- provided "codechicken:CodeChickenLib:${config.minecraft.version}-${config.ccl.version}:universal"
- provided "codechicken:WR-CBE:${config.minecraft.version}-${config.wrcbe.version}:universal"
+ compileOnly "mezz.jei:${jeiSlug}:${config.jei.version}"
+ compileOnly "codechicken:CodeChickenLib:${config.ccl.version}:universal"
- provided ("mrtjp:ProjectRed:${config.projred.version}:Base") {
- exclude module: "NotEnoughItems"
+ compileOnly ("mrtjp:ProjectRed:${config.projred.version}:core") {
exclude module: "CodeChickenLib"
- exclude module: "jei_1.12"
- exclude module: "ForgeMultipart"
+ exclude module: jeiSlug
+ exclude module: "CBMultipart"
}
- provided ("mrtjp:ProjectRed:${config.projred.version}:integration") {
- exclude module: "NotEnoughItems"
- exclude module: "CodeChickenLib"
- exclude module: "jei_1.12"
- exclude module: "ForgeMultipart"
- }
+ embedded name: 'OC-LuaJ', version: '20220907.1', ext: 'jar'
+ embedded name: 'OC-JNLua', version: '20220928.1', ext: 'jar'
+ embedded name: 'OC-JNLua-Natives', version: '20220928.1', ext: 'jar'
- provided ("mrtjp:MrTJPCore:${config.mrtjpcore.version}:universal") {
- exclude module: "NotEnoughItems"
- exclude module: "CodeChickenLib"
- exclude module: "jei_1.12"
- exclude module: "ForgeMultipart"
- }
-
- embedded files('libs/OpenComputers-JNLua.jar', 'libs/OpenComputers-LuaJ.jar')
-
- testCompile "org.mockito:mockito-all:1.10.19"
-
- provided "codechicken:EnderStorage:${config.minecraft.version}-${config.enderstorage.version}:universal"
+ compileOnly "codechicken:EnderStorage:${config.enderstorage.version}:universal"
}
processResources {
- inputs.property "version", project.simpleVersion
- inputs.property "mcversion", project.minecraft.version
- inputs.property "fversion", config.forge.version
+ def reducedScorgeVer = config.scorge.version.replaceAll(/(\d+\.\d+)(\.\d+)/, "\$1")
from(sourceSets.main.resources.srcDirs) {
- include 'mcmod.info'
- expand 'version':project.simpleVersion, 'mcversion':project.minecraft.version, 'fversion':config.forge.version
+ duplicatesStrategy = "include"
+ include 'META-INF/mods.toml'
+ expand 'version':mod_version, 'mcversion':config.minecraft.version, 'sversion':reducedScorgeVer
}
from(sourceSets.main.resources.srcDirs) {
+ duplicatesStrategy = "include"
include 'application.conf'
filter { line ->
- line.replaceAll("@VERSION@", project.simpleVersion)
+ line.replaceAll("@VERSION@", mod_version)
}
}
- from(sourceSets.main.resources.srcDirs) {
- exclude 'mcmod.info'
- exclude 'application.conf'
- }
-
- // Move access transformer to META-INF
- rename '(.+_at.cfg)', 'META-INF/$1'
}
allprojects {
@@ -167,16 +210,24 @@ allprojects {
}
}
-jar {
+configure([jar, devJar]) {
configurations.embedded.each { dep ->
from(project.zipTree(dep)) {
- exclude 'META-INF', 'META-INF/**'
+ exclude '*', 'META-INF', 'META-INF/**'
}
}
manifest {
- attributes FMLCorePlugin: "li.cil.oc.common.launch.TransformerLoader"
- attributes FMLCorePluginContainsFMLMod: "true"
- attributes FMLAT: "oc_at.cfg"
+ attributes([
+ "Specification-Title": "opencomputers",
+ "Specification-Vendor": "li.cil.oc",
+ "Specification-Version": "1",
+ "Implementation-Title": project.name,
+ "Implementation-Version": version,
+ "Implementation-Vendor": config.mod.group,
+ "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
+ "FMLCorePlugin": "li.cil.oc.common.launch.TransformerLoader",
+ "FMLCorePluginContainsFMLMod": "true"
+ ])
}
}
@@ -201,9 +252,19 @@ artifacts {
archives javadocJar
}
+jar.finalizedBy('reobfJar')
+afterEvaluate {
+ prepareRuns {
+ dependsOn(devJar)
+ }
+}
+
publishing {
publications {
mavenJava(MavenPublication) {
+ groupId = project.group
+ artifactId = project.name
+ version = mod_version
artifact jar
artifact apiJar
artifact javadocJar
@@ -211,19 +272,37 @@ publishing {
}
repositories {
maven {
- url System.getenv("MAVEN_PATH")
+ name = "GitHubPackages"
+ url = System.getenv("GITHUB_MAVEN_URL") ?: ""
+ credentials {
+ username = System.getenv("GITHUB_ACTOR")
+ password = System.getenv("GITHUB_TOKEN")
+ }
}
}
}
curseforge {
- apiKey = project.hasProperty("curseForgeApiKey") ? project.curseForgeApiKey : ""
+ apiKey = System.getenv('CURSEFORGE_API_KEY') ?: ""
project {
id = config.curse.project.id
- releaseType = config.curse.project.releaseType
+ releaseType = System.getenv('CURSEFORGE_RELEASE_TYPE') ?: "alpha"
changelogType = "markdown"
- changelog = file("changelog.md")
+ changelog = System.getenv("CHANGELOG") ?: "Changelog not available."
addGameVersion config.minecraft.version
addGameVersion "Java 8"
+ addGameVersion "Forge"
}
}
+
+modrinth {
+ token = System.getenv("MODRINTH_API_KEY") ?: ""
+ projectId = config.modrinth.project.id
+ changelog = System.getenv("CHANGELOG") ?: "Changelog not available."
+ versionNumber = mod_version
+ versionName = "${rootProject.name}-${version}"
+ versionType = System.getenv('MODRINTH_RELEASE_TYPE') ?: "alpha"
+ uploadFile = jar
+ gameVersions = [config.minecraft.version]
+ loaders = ["forge"]
+}
diff --git a/build.properties b/build.properties
index 790da7a9ff..eba6e7cdf6 100644
--- a/build.properties
+++ b/build.properties
@@ -1,30 +1,23 @@
-minecraft.version=1.12.2
-minecraft.mappings=snapshot_20180704
-forge.version=14.23.5.2778
+minecraft.version=1.16.5
+forge.version=36.2.34
+scorge.version=3.1.3
mod.name=OpenComputers
mod.group=li.cil.oc
mod.version=1.7.5
-ae2.version=rv6-stable-5
-buildcraft.version=7.99.17
-cc.version=1.80pr1-build0
-charset.version=0.5.6.2
-extracells.version=1.12.2:2.5.3a25
-forestry.version=5.8.0.311
-hwyla.version=1.8.26-B41_1.12.2
-ic2.version=2.8.91-ex112
-jei.version=4.15.0.268
-mcmp.version=2.5.1_66
-mekanism.version=1.12.2-9.4.3.330
-tis3d.version=1.3.1.18
-projred.version=1.12.2-4.9.3.118
-mrtjpcore.version=1.12.2-2.1.4.43
-ccl.version=3.2.3.358
-forgemultipart.version=2.6.2.83
-casm.version=1.12-1.0.2.7
-enderstorage.version=2.4.5.135
-wrcbe.version=2.3.2.33
+ae2.version=8.4.7
+cct.version=1.100.5
+hwyla.projectId=253449
+hwyla.fileId=3033595
+jei.version=7.7.1.152
+mekanism.version=1.16.5-10.1.2.457
+tis3d.version=1.6.8+30
+projred.version=1.16.5-4.12.0-beta-0
+ccl.version=1.16.5-4.0.7.445
+cbmultipart.version=1.16.5-3.0.4.123
+casm.version=2.0.1.14
+enderstorage.version=1.16.5-2.8.0.170
curse.project.id=223008
-curse.project.releaseType=release
+modrinth.project.id=YiAbZis2
diff --git a/gradle.properties b/gradle.properties
index e69de29bb2..ee9da0b886 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.daemon=false
+mod_version=1.8.0-snapshot
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 758de960ec..e708b1c023 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2d80b69a76..2e6e5897b5 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index cccdd3d517..4f906e0c81 100755
--- a/gradlew
+++ b/gradlew
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
- i=$((i+1))
+ i=`expr $i + 1`
done
case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
-APP_ARGS=$(save "$@")
+APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index e95643d6a2..ac1b06f938 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/libs/OpenComputers-JNLua.jar b/libs/OpenComputers-JNLua.jar
deleted file mode 100644
index f06a8f722a..0000000000
Binary files a/libs/OpenComputers-JNLua.jar and /dev/null differ
diff --git a/libs/OpenComputers-LuaJ.jar b/libs/OpenComputers-LuaJ.jar
deleted file mode 100644
index 1d2cc019b4..0000000000
Binary files a/libs/OpenComputers-LuaJ.jar and /dev/null differ
diff --git a/libs/factorization-api.zip b/libs/factorization-api.zip
deleted file mode 100644
index 44566c78ce..0000000000
Binary files a/libs/factorization-api.zip and /dev/null differ
diff --git a/libs/ic2classic-api.zip b/libs/ic2classic-api.zip
deleted file mode 100644
index 5025bac68f..0000000000
Binary files a/libs/ic2classic-api.zip and /dev/null differ
diff --git a/src/main/java/li/cil/oc/api/CreativeTab.java b/src/main/java/li/cil/oc/api/CreativeTab.java
index 2454256fe3..219309b60f 100644
--- a/src/main/java/li/cil/oc/api/CreativeTab.java
+++ b/src/main/java/li/cil/oc/api/CreativeTab.java
@@ -1,6 +1,6 @@
package li.cil.oc.api;
-import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.ItemGroup;
/**
* Allows access to the creative tab used by OpenComputers.
@@ -13,7 +13,7 @@ public final class CreativeTab {
* not try to access this anyway when OpenComputers isn't
* present (don't ship the API in your mod), so don't rely on this!
*/
- public static CreativeTabs instance = CreativeTabs.REDSTONE;
+ public static ItemGroup instance = ItemGroup.TAB_REDSTONE;
private CreativeTab() {
}
diff --git a/src/main/java/li/cil/oc/api/Driver.java b/src/main/java/li/cil/oc/api/Driver.java
index 4d8fe319cf..90ceb83bd9 100644
--- a/src/main/java/li/cil/oc/api/Driver.java
+++ b/src/main/java/li/cil/oc/api/Driver.java
@@ -6,9 +6,9 @@
import li.cil.oc.api.driver.DriverItem;
import li.cil.oc.api.driver.DriverBlock;
import li.cil.oc.api.network.EnvironmentHost;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
@@ -124,7 +124,7 @@ public static void add(final InventoryProvider provider) {
* @param pos the position of the block.
* @return a driver for the block, or null if there is none.
*/
- public static DriverBlock driverFor(World world, BlockPos pos, EnumFacing side) {
+ public static DriverBlock driverFor(World world, BlockPos pos, Direction side) {
if (API.driver != null)
return API.driver.driverFor(world, pos, side);
return null;
@@ -214,7 +214,7 @@ public static Set> environmentsFor(ItemStack stack) {
* @param player the player holding the item. May be null.
* @return the IItemHandler implementation interfacing the stack, or null.
*/
- public static IItemHandler itemHandlerFor(ItemStack stack, EntityPlayer player) {
+ public static IItemHandler itemHandlerFor(ItemStack stack, PlayerEntity player) {
if (API.driver != null)
return API.driver.itemHandlerFor(stack, player);
return null;
diff --git a/src/main/java/li/cil/oc/api/FileSystem.java b/src/main/java/li/cil/oc/api/FileSystem.java
index 49557d0cf5..4dfc83344a 100644
--- a/src/main/java/li/cil/oc/api/FileSystem.java
+++ b/src/main/java/li/cil/oc/api/FileSystem.java
@@ -3,6 +3,7 @@
import li.cil.oc.api.network.EnvironmentHost;
import li.cil.oc.api.fs.Label;
import li.cil.oc.api.network.ManagedEnvironment;
+import net.minecraft.util.ResourceLocation;
/**
* This class provides factory methods for creating file systems that are
@@ -22,29 +23,25 @@
*/
public final class FileSystem {
/**
- * Creates a new file system based on the location of a class.
+ * Creates a new file system based on a mod-specific resource location where
+ * the namespace refers to the mod and the resource path denotes a
+ * (mandatory) subpath relative to that mod's assets directory.
*
- * This can be used to wrap a folder in the assets folder of your mod's JAR.
- * The actual path is built like this:
- *
"/assets/" + domain + "/" + root
- *
- * If the class is located in a JAR file, this will create a read-only file
- * system based on that JAR file. If the class file is located in the native
- * file system, this will create a read-only file system first trying from
- * the actual location of the class file, and failing that by searching the
- * class path (i.e. it'll look for a path constructed as described above).
+ * If {@code location} is stored in a JAR file, this will create a read-only
+ * file system based on that JAR file. If {@code location} is stored in the
+ * native file system, this will create a read-only file system from the the
+ * location constructed as described above (relative to the root of the
+ * namespace).
*
* If the specified path cannot be located, the creation fails and this
* returns null.
*
- * @param clazz the class whose containing JAR to wrap.
- * @param domain the domain, usually your mod's ID.
- * @param root an optional subdirectory.
- * @return a file system wrapping the specified folder.
+ * @param location the location where the file system's contents are stored.
+ * @return a file system wrapping the specified resource.
*/
- public static li.cil.oc.api.fs.FileSystem fromClass(final Class> clazz, final String domain, final String root) {
+ public static li.cil.oc.api.fs.FileSystem fromResource(final ResourceLocation location) {
if (API.fileSystem != null)
- return API.fileSystem.fromClass(clazz, domain, root);
+ return API.fileSystem.fromResource(location);
return null;
}
diff --git a/src/main/java/li/cil/oc/api/IMC.java b/src/main/java/li/cil/oc/api/IMC.java
index 6149544096..11f286e162 100644
--- a/src/main/java/li/cil/oc/api/IMC.java
+++ b/src/main/java/li/cil/oc/api/IMC.java
@@ -1,10 +1,10 @@
package li.cil.oc.api;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraft.nbt.NBTTagString;
-import net.minecraftforge.fml.common.event.FMLInterModComms;
+import net.minecraft.nbt.CompoundNBT;
+import net.minecraft.nbt.ListNBT;
+import net.minecraft.nbt.StringNBT;
+import net.minecraftforge.fml.InterModComms;
import org.apache.commons.lang3.tuple.Pair;
/**
@@ -53,7 +53,7 @@ public final class IMC {
* @param callback the callback to register as a filtering method.
*/
public static void registerAssemblerFilter(final String callback) {
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_ASSEMBLER_FILTER, callback);
+ InterModComms.sendTo(MOD_ID, REGISTER_ASSEMBLER_FILTER, () -> callback);
}
/**
@@ -114,59 +114,59 @@ public static void registerAssemblerFilter(final String callback) {
* for the third component slot. Up to nine.
*/
public static void registerAssemblerTemplate(final String name, final String select, final String validate, final String assemble, final Class host, final int[] containerTiers, final int[] upgradeTiers, final Iterable> componentSlots) {
- final NBTTagCompound nbt = new NBTTagCompound();
+ final CompoundNBT nbt = new CompoundNBT();
if (name != null) {
- nbt.setString("name", name);
+ nbt.putString("name", name);
}
- nbt.setString("select", select);
- nbt.setString("validate", validate);
- nbt.setString("assemble", assemble);
+ nbt.putString("select", select);
+ nbt.putString("validate", validate);
+ nbt.putString("assemble", assemble);
if (host != null) {
- nbt.setString("hostClass", host.getName());
+ nbt.putString("hostClass", host.getName());
}
- final NBTTagList containersNbt = new NBTTagList();
+ final ListNBT containersNbt = new ListNBT();
if (containerTiers != null) {
for (int tier : containerTiers) {
- final NBTTagCompound slotNbt = new NBTTagCompound();
- slotNbt.setInteger("tier", tier);
- containersNbt.appendTag(slotNbt);
+ final CompoundNBT slotNbt = new CompoundNBT();
+ slotNbt.putInt("tier", tier);
+ containersNbt.add(slotNbt);
}
}
- if (containersNbt.tagCount() > 0) {
- nbt.setTag("containerSlots", containersNbt);
+ if (containersNbt.size() > 0) {
+ nbt.put("containerSlots", containersNbt);
}
- final NBTTagList upgradesNbt = new NBTTagList();
+ final ListNBT upgradesNbt = new ListNBT();
if (upgradeTiers != null) {
for (int tier : upgradeTiers) {
- final NBTTagCompound slotNbt = new NBTTagCompound();
- slotNbt.setInteger("tier", tier);
- upgradesNbt.appendTag(slotNbt);
+ final CompoundNBT slotNbt = new CompoundNBT();
+ slotNbt.putInt("tier", tier);
+ upgradesNbt.add(slotNbt);
}
}
- if (upgradesNbt.tagCount() > 0) {
- nbt.setTag("upgradeSlots", upgradesNbt);
+ if (upgradesNbt.size() > 0) {
+ nbt.put("upgradeSlots", upgradesNbt);
}
- final NBTTagList componentsNbt = new NBTTagList();
+ final ListNBT componentsNbt = new ListNBT();
if (componentSlots != null) {
for (Pair slot : componentSlots) {
if (slot == null) {
- componentsNbt.appendTag(new NBTTagCompound());
+ componentsNbt.add(new CompoundNBT());
} else {
- final NBTTagCompound slotNbt = new NBTTagCompound();
- slotNbt.setString("type", slot.getLeft());
- slotNbt.setInteger("tier", slot.getRight());
- componentsNbt.appendTag(slotNbt);
+ final CompoundNBT slotNbt = new CompoundNBT();
+ slotNbt.putString("type", slot.getLeft());
+ slotNbt.putInt("tier", slot.getRight());
+ componentsNbt.add(slotNbt);
}
}
}
- if (componentsNbt.tagCount() > 0) {
- nbt.setTag("componentSlots", componentsNbt);
+ if (componentsNbt.size() > 0) {
+ nbt.put("componentSlots", componentsNbt);
}
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_ASSEMBLER_TEMPLATE, nbt);
+ InterModComms.sendTo(MOD_ID, REGISTER_ASSEMBLER_TEMPLATE, () -> nbt);
}
/**
@@ -203,14 +203,14 @@ public static void registerAssemblerTemplate(final String name, final String sel
* ingredients from an item.
*/
public static void registerDisassemblerTemplate(final String name, final String select, final String disassemble) {
- final NBTTagCompound nbt = new NBTTagCompound();
+ final CompoundNBT nbt = new CompoundNBT();
if (name != null) {
- nbt.setString("name", name);
+ nbt.putString("name", name);
}
- nbt.setString("select", select);
- nbt.setString("disassemble", disassemble);
+ nbt.putString("select", select);
+ nbt.putString("disassemble", disassemble);
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_DISASSEMBLER_TEMPLATE, nbt);
+ InterModComms.sendTo(MOD_ID, REGISTER_DISASSEMBLER_TEMPLATE, () -> nbt);
}
/**
@@ -234,7 +234,7 @@ public static void registerDisassemblerTemplate(final String name, final String
* @param callback the callback to register as a durability provider.
*/
public static void registerToolDurabilityProvider(final String callback) {
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_TOOL_DURABILITY_PROVIDER, callback);
+ InterModComms.sendTo(MOD_ID, REGISTER_TOOL_DURABILITY_PROVIDER, () -> callback);
}
/**
@@ -249,7 +249,7 @@ public static void registerToolDurabilityProvider(final String callback) {
*
* Signature of callbacks must be:
*
*
* Callbacks must be declared as packagePath.className.methodName.
@@ -258,7 +258,7 @@ public static void registerToolDurabilityProvider(final String callback) {
* @param callback the callback to register as a wrench tool handler.
*/
public static void registerWrenchTool(final String callback) {
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_WRENCH_TOOL, callback);
+ InterModComms.sendTo(MOD_ID, REGISTER_WRENCH_TOOL, () -> callback);
}
/**
@@ -281,7 +281,7 @@ public static void registerWrenchTool(final String callback) {
* @param callback the callback to register as a wrench tool tester.
*/
public static void registerWrenchToolCheck(final String callback) {
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_WRENCH_TOOL_CHECK, callback);
+ InterModComms.sendTo(MOD_ID, REGISTER_WRENCH_TOOL_CHECK, () -> callback);
}
/**
@@ -307,11 +307,11 @@ public static void registerWrenchToolCheck(final String callback) {
* @param charge the callback to register for charging items.
*/
public static void registerItemCharge(final String name, final String canCharge, final String charge) {
- final NBTTagCompound nbt = new NBTTagCompound();
- nbt.setString("name", name);
- nbt.setString("canCharge", canCharge);
- nbt.setString("charge", charge);
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_ITEM_CHARGE, nbt);
+ final CompoundNBT nbt = new CompoundNBT();
+ nbt.putString("name", name);
+ nbt.putString("canCharge", canCharge);
+ nbt.putString("charge", charge);
+ InterModComms.sendTo(MOD_ID, REGISTER_ITEM_CHARGE, () -> nbt);
}
/**
@@ -335,7 +335,7 @@ public static void registerItemCharge(final String name, final String canCharge,
* @param callback the callback to register as an ink provider.
*/
public static void registerInkProvider(final String callback) {
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_INK_PROVIDER, callback);
+ InterModComms.sendTo(MOD_ID, REGISTER_INK_PROVIDER, () -> callback);
}
/**
@@ -348,7 +348,7 @@ public static void registerInkProvider(final String callback) {
* @param peripheral the class of the peripheral to blacklist.
*/
public static void blacklistPeripheral(final Class peripheral) {
- FMLInterModComms.sendMessage(MOD_ID, BLACKLIST_PERIPHERAL, peripheral.getName());
+ InterModComms.sendTo(MOD_ID, BLACKLIST_PERIPHERAL, () -> peripheral.getName());
}
/**
@@ -367,13 +367,13 @@ public static void blacklistPeripheral(final Class peripheral) {
* @param stack the item stack representing the blacklisted component.
*/
public static void blacklistHost(final String name, final Class host, final ItemStack stack) {
- final NBTTagCompound nbt = new NBTTagCompound();
- nbt.setString("name", name);
- nbt.setString("host", host.getName());
- final NBTTagCompound stackNbt = new NBTTagCompound();
- stack.writeToNBT(stackNbt);
- nbt.setTag("item", stackNbt);
- FMLInterModComms.sendMessage(MOD_ID, BLACKLIST_HOST, nbt);
+ final CompoundNBT nbt = new CompoundNBT();
+ nbt.putString("name", name);
+ nbt.putString("host", host.getName());
+ final CompoundNBT stackNbt = new CompoundNBT();
+ stack.save(stackNbt);
+ nbt.put("item", stackNbt);
+ InterModComms.sendTo(MOD_ID, BLACKLIST_HOST, () -> nbt);
}
/**
@@ -401,17 +401,17 @@ public static void blacklistHost(final String name, final Class host, final Item
* @param architectures the names of the architectures this entry applies to.
*/
public static void registerProgramDiskLabel(final String programName, final String diskLabel, final String... architectures) {
- final NBTTagCompound nbt = new NBTTagCompound();
- nbt.setString("program", programName);
- nbt.setString("label", diskLabel);
+ final CompoundNBT nbt = new CompoundNBT();
+ nbt.putString("program", programName);
+ nbt.putString("label", diskLabel);
if (architectures != null && architectures.length > 0) {
- final NBTTagList architecturesNbt = new NBTTagList();
+ final ListNBT architecturesNbt = new ListNBT();
for (final String architecture : architectures) {
- architecturesNbt.appendTag(new NBTTagString(architecture));
+ architecturesNbt.add(StringNBT.valueOf(architecture));
}
- nbt.setTag("architectures", architecturesNbt);
+ nbt.put("architectures", architecturesNbt);
}
- FMLInterModComms.sendMessage(MOD_ID, REGISTER_PROGRAM_DISK_LABEL, nbt);
+ InterModComms.sendTo(MOD_ID, REGISTER_PROGRAM_DISK_LABEL, () -> nbt);
}
// ----------------------------------------------------------------------- //
diff --git a/src/main/java/li/cil/oc/api/Items.java b/src/main/java/li/cil/oc/api/Items.java
index ec37582994..b9e7d86903 100644
--- a/src/main/java/li/cil/oc/api/Items.java
+++ b/src/main/java/li/cil/oc/api/Items.java
@@ -1,8 +1,9 @@
package li.cil.oc.api;
import li.cil.oc.api.detail.ItemInfo;
-import net.minecraft.item.EnumDyeColor;
+import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
import java.util.concurrent.Callable;
@@ -54,11 +55,11 @@ public static ItemInfo get(ItemStack stack) {
*
* The specified factory callable will be used to generate a new file
* system when the loot disk is used as a component. The specified name
- * will be used as the label for the loot disk, as well as the identifier
- * to select the corresponding factory method, so choose wisely.
+ * will be used as the label for the loot disk, while the location serves
+ * as the identifier to select the corresponding factory method.
*
* To use some directory in your mod JAR as the directory provided by the
- * loot disk, use {@link FileSystem#fromClass} in your callable.
+ * loot disk, use {@link FileSystem#fromResource} in your callable.
*
* If doRecipeCycling is true, the floppy disk will be
* included in the floppy disk recipe cycle if that is enabled.
@@ -66,15 +67,18 @@ public static ItemInfo get(ItemStack stack) {
* Call this in the init phase or later, not in pre-init.
*
* @param name the label and identifier to use for the loot disk.
+ * @param loc the location where the disk's contents are stored.
* @param color the color of the disk, as a Minecraft color.
* @param factory the callable to call for creating file system instances.
* @param doRecipeCycling whether to include this floppy disk in floppy disk cycling.
* @return an item stack representing the registered loot disk, to allow
* adding a recipe for your loot disk, for example.
*/
- public static ItemStack registerFloppy(String name, EnumDyeColor color, Callable factory, boolean doRecipeCycling) {
+ public static ItemStack registerFloppy(String name, ResourceLocation loc, DyeColor color,
+ Callable factory, boolean doRecipeCycling) {
+
if (API.items != null)
- return API.items.registerFloppy(name, color, factory, doRecipeCycling);
+ return API.items.registerFloppy(name, loc, color, factory, doRecipeCycling);
return ItemStack.EMPTY;
}
diff --git a/src/main/java/li/cil/oc/api/Manual.java b/src/main/java/li/cil/oc/api/Manual.java
index 5096202c78..90b6af2d70 100644
--- a/src/main/java/li/cil/oc/api/Manual.java
+++ b/src/main/java/li/cil/oc/api/Manual.java
@@ -5,7 +5,7 @@
import li.cil.oc.api.manual.ImageRenderer;
import li.cil.oc.api.manual.PathProvider;
import li.cil.oc.api.manual.TabIconRenderer;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -153,7 +153,7 @@ public static Iterable contentFor(String path) {
*
* @param player the player to open the manual for.
*/
- public static void openFor(EntityPlayer player) {
+ public static void openFor(PlayerEntity player) {
if (API.manual != null)
API.manual.openFor(player);
}
diff --git a/src/main/java/li/cil/oc/api/Nanomachines.java b/src/main/java/li/cil/oc/api/Nanomachines.java
index afa239b8d4..39a18df84d 100644
--- a/src/main/java/li/cil/oc/api/Nanomachines.java
+++ b/src/main/java/li/cil/oc/api/Nanomachines.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.nanomachines.BehaviorProvider;
import li.cil.oc.api.nanomachines.Controller;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import java.util.Collections;
@@ -44,7 +44,7 @@ public static Iterable getProviders() {
* @param player the player to check for.
* @return true if the player has a controller, false otherwise.
*/
- public static boolean hasController(EntityPlayer player) {
+ public static boolean hasController(PlayerEntity player) {
if (API.nanomachines != null)
return API.nanomachines.hasController(player);
return false;
@@ -60,7 +60,7 @@ public static boolean hasController(EntityPlayer player) {
* @param player the player to get the controller for.
* @return the controller for the specified player.
*/
- public static Controller getController(EntityPlayer player) {
+ public static Controller getController(PlayerEntity player) {
if (API.nanomachines != null)
return API.nanomachines.getController(player);
return null;
@@ -75,7 +75,7 @@ public static Controller getController(EntityPlayer player) {
*
* @param player the player to install a nanomachine controller for.
*/
- public static Controller installController(EntityPlayer player) {
+ public static Controller installController(PlayerEntity player) {
if (API.nanomachines != null)
return API.nanomachines.installController(player);
return null;
@@ -88,7 +88,7 @@ public static Controller installController(EntityPlayer player) {
*
* @param player the player to uninstall a nanomachine controller from.
*/
- public static void uninstallController(EntityPlayer player) {
+ public static void uninstallController(PlayerEntity player) {
if (API.nanomachines != null)
API.nanomachines.uninstallController(player);
}
diff --git a/src/main/java/li/cil/oc/api/Network.java b/src/main/java/li/cil/oc/api/Network.java
index 5db80f8e5c..f306f68560 100644
--- a/src/main/java/li/cil/oc/api/Network.java
+++ b/src/main/java/li/cil/oc/api/Network.java
@@ -6,10 +6,12 @@
import li.cil.oc.api.network.Packet;
import li.cil.oc.api.network.Visibility;
import li.cil.oc.api.network.WirelessEndpoint;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.RegistryKey;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.IBlockReader;
+import net.minecraft.world.World;
/**
* This class provides factories for networks and nodes.
@@ -31,7 +33,7 @@
*/
public final class Network {
/**
- * Convenience overload for {@link #joinOrCreateNetwork(IBlockAccess, BlockPos)}.
+ * Convenience overload for {@link #joinOrCreateNetwork(IBlockReader, BlockPos)}.
*
* If the tile entity implements {@link Environment} its one node will be
* connected to any existing adjacent tile entity nodes. If none exist a
@@ -56,7 +58,7 @@ public static void joinOrCreateNetwork(final TileEntity tileEntity) {
* @param world the world containing the location to connect.
* @param pos the position at which to update the network.
*/
- public static void joinOrCreateNetwork(final IBlockAccess world, final BlockPos pos) {
+ public static void joinOrCreateNetwork(final IBlockReader world, final BlockPos pos) {
if (API.network != null)
API.network.joinOrCreateNetwork(world, pos);
}
@@ -138,7 +140,7 @@ public static void leaveWirelessNetwork(final WirelessEndpoint endpoint) {
* @param endpoint the endpoint to remove from the wireless network.
* @param dimension the dimension with the wireless network to remove the endpoint from.
*/
- public static void leaveWirelessNetwork(final WirelessEndpoint endpoint, final int dimension) {
+ public static void leaveWirelessNetwork(final WirelessEndpoint endpoint, final RegistryKey dimension) {
if (API.network != null)
API.network.leaveWirelessNetwork(endpoint, dimension);
}
@@ -233,7 +235,7 @@ public static Packet newPacket(final String source, final String destination, fi
* @param nbt the tag to load the packet from.
* @return the loaded packet.
*/
- public static Packet newPacket(final NBTTagCompound nbt) {
+ public static Packet newPacket(final CompoundNBT nbt) {
if (API.network != null)
return API.network.newPacket(nbt);
return null;
diff --git a/src/main/java/li/cil/oc/api/Persistable.java b/src/main/java/li/cil/oc/api/Persistable.java
index 8ad2b2a459..b7bb1ccf93 100644
--- a/src/main/java/li/cil/oc/api/Persistable.java
+++ b/src/main/java/li/cil/oc/api/Persistable.java
@@ -1,6 +1,6 @@
package li.cil.oc.api;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* An object that can be persisted to an NBT tag and restored back from it.
@@ -11,15 +11,15 @@ public interface Persistable {
*
* @param nbt the tag to read the state from.
*/
- void load(NBTTagCompound nbt);
+ void loadData(CompoundNBT nbt);
/**
* Saves the current state of the object into the specified NBT tag.
*
* This should write the state in such a way that it can be restored when
- * {@link #load} is called with that tag.
+ * {@link #loadData} is called with that tag.
*
* @param nbt the tag to save the state to.
*/
- void save(NBTTagCompound nbt);
+ void saveData(CompoundNBT nbt);
}
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/component/RackMountable.java b/src/main/java/li/cil/oc/api/component/RackMountable.java
index efe4057441..9c4aecce41 100644
--- a/src/main/java/li/cil/oc/api/component/RackMountable.java
+++ b/src/main/java/li/cil/oc/api/component/RackMountable.java
@@ -4,11 +4,11 @@
import li.cil.oc.api.network.ComponentHost;
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.api.util.StateAware;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.EnumHand;
+import net.minecraft.nbt.CompoundNBT;
+import net.minecraft.util.Hand;
/**
* Use this interface on environments provided by drivers for items that can
@@ -41,7 +41,7 @@ public interface RackMountable extends ManagedEnvironment, StateAware {
*
* @return the data to synchronize to the clients.
*/
- NBTTagCompound getData();
+ CompoundNBT getData();
/**
* The number of connectables exposed by the environment.
@@ -70,5 +70,5 @@ public interface RackMountable extends ManagedEnvironment, StateAware {
* @param hitY the relative y coordinate of the activation on the mountable.
* @return whether the activation was handled (e.g. GUI opened).
*/
- boolean onActivate(EntityPlayer player, EnumHand hand, ItemStack heldItem, float hitX, float hitY);
+ boolean onActivate(PlayerEntity player, Hand hand, ItemStack heldItem, float hitX, float hitY);
}
diff --git a/src/main/java/li/cil/oc/api/component/package-info.java b/src/main/java/li/cil/oc/api/component/package-info.java
index b8dc74b7bc..e4fee4451b 100644
--- a/src/main/java/li/cil/oc/api/component/package-info.java
+++ b/src/main/java/li/cil/oc/api/component/package-info.java
@@ -4,10 +4,6 @@
* This will allow OpenComputers to provide some more advanced integration
* with your components.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|component",
- apiVersion = API.VERSION)
package li.cil.oc.api.component;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/detail/DriverAPI.java b/src/main/java/li/cil/oc/api/detail/DriverAPI.java
index 138f60becb..c0bcd02681 100644
--- a/src/main/java/li/cil/oc/api/detail/DriverAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/DriverAPI.java
@@ -6,9 +6,9 @@
import li.cil.oc.api.driver.DriverItem;
import li.cil.oc.api.driver.DriverBlock;
import li.cil.oc.api.network.EnvironmentHost;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
@@ -95,7 +95,7 @@ public interface DriverAPI {
* @return a driver for the block, or null if there is none.
*/
@Nullable
- DriverBlock driverFor(World world, BlockPos pos, EnumFacing side);
+ DriverBlock driverFor(World world, BlockPos pos, Direction side);
/**
* Looks up a driver for the specified item stack.
@@ -167,7 +167,7 @@ public interface DriverAPI {
* @param player the player holding the item. May be null.
* @return the IItemHandler implementation interfacing the stack, or null.
*/
- IItemHandler itemHandlerFor(ItemStack stack, EntityPlayer player);
+ IItemHandler itemHandlerFor(ItemStack stack, PlayerEntity player);
/**
* Get a list of all registered item drivers.
diff --git a/src/main/java/li/cil/oc/api/detail/FileSystemAPI.java b/src/main/java/li/cil/oc/api/detail/FileSystemAPI.java
index fa58c3b1a6..6f37e77ee8 100644
--- a/src/main/java/li/cil/oc/api/detail/FileSystemAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/FileSystemAPI.java
@@ -4,30 +4,27 @@
import li.cil.oc.api.fs.FileSystem;
import li.cil.oc.api.fs.Label;
import li.cil.oc.api.network.ManagedEnvironment;
+import net.minecraft.util.ResourceLocation;
public interface FileSystemAPI {
/**
- * Creates a new file system based on the location of a class.
+ * Creates a new file system based on a mod-specific resource location where
+ * the namespace refers to the mod and the resource path denotes a
+ * (mandatory) subpath relative to that mod's assets directory.
*
- * This can be used to wrap a folder in the assets folder of your mod's JAR.
- * The actual path is built like this:
- *
"/assets/" + domain + "/" + root
- *
- * If the class is located in a JAR file, this will create a read-only file
- * system based on that JAR file. If the class file is located in the native
- * file system, this will create a read-only file system first trying from
- * the actual location of the class file, and failing that by searching the
- * class path (i.e. it'll look for a path constructed as described above).
+ * If {@code location} is stored in a JAR file, this will create a read-only
+ * file system based on that JAR file. If {@code location} is stored in the
+ * native file system, this will create a read-only file system from the the
+ * location constructed as described above (relative to the root of the
+ * namespace).
*
* If the specified path cannot be located, the creation fails and this
* returns null.
*
- * @param clazz the class whose containing JAR to wrap.
- * @param domain the domain, usually your mod's ID.
- * @param root an optional subdirectory.
- * @return a file system wrapping the specified folder.
+ * @param location the location where the file system's contents are stored.
+ * @return a file system wrapping the specified resource.
*/
- FileSystem fromClass(Class> clazz, String domain, String root);
+ FileSystem fromResource(ResourceLocation location);
/**
* Creates a new writable file system in the save folder.
diff --git a/src/main/java/li/cil/oc/api/detail/ItemAPI.java b/src/main/java/li/cil/oc/api/detail/ItemAPI.java
index 579500cf5b..f29c54230c 100644
--- a/src/main/java/li/cil/oc/api/detail/ItemAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/ItemAPI.java
@@ -1,8 +1,9 @@
package li.cil.oc.api.detail;
import li.cil.oc.api.FileSystem;
-import net.minecraft.item.EnumDyeColor;
+import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
@@ -41,11 +42,11 @@ public interface ItemAPI {
*
* The specified factory callable will be used to generate a new file
* system when the loot disk is used as a component. The specified name
- * will be used as the label for the loot disk, as well as the identifier
- * to select the corresponding factory method, so choose wisely.
+ * will be used as the label for the loot disk, while the location serves
+ * as the identifier to select the corresponding factory method.
*
* To use some directory in your mod JAR as the directory provided by the
- * loot disk, use {@link FileSystem#fromClass} in your callable.
+ * loot disk, use {@link FileSystem#fromResource} in your callable.
*
* If doRecipeCycling is true, the floppy disk will be
* included in the floppy disk recipe cycle if that is enabled.
@@ -53,13 +54,15 @@ public interface ItemAPI {
* Call this in the init phase or later, not in pre-init.
*
* @param name the label and identifier to use for the loot disk.
+ * @param loc the location where the disk's contents are stored.
* @param color the color of the disk, as a Minecraft color.
* @param factory the callable to call for creating file system instances.
* @param doRecipeCycling whether to include this floppy disk in floppy disk cycling.
* @return an item stack representing the registered loot disk, to allow
* adding a recipe for your loot disk, for example.
*/
- ItemStack registerFloppy(String name, EnumDyeColor color, Callable factory, boolean doRecipeCycling);
+ ItemStack registerFloppy(String name, ResourceLocation loc, DyeColor color,
+ Callable factory, boolean doRecipeCycling);
/**
* Register a single custom EEPROM.
diff --git a/src/main/java/li/cil/oc/api/detail/ManualAPI.java b/src/main/java/li/cil/oc/api/detail/ManualAPI.java
index 605955472d..0eb9718bcc 100644
--- a/src/main/java/li/cil/oc/api/detail/ManualAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/ManualAPI.java
@@ -5,7 +5,7 @@
import li.cil.oc.api.manual.ImageRenderer;
import li.cil.oc.api.manual.PathProvider;
import li.cil.oc.api.manual.TabIconRenderer;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -90,7 +90,7 @@ public interface ManualAPI {
*
* The provided path may contain the special variable %LANGUAGE%,
* which will be resolved to the currently set language, falling back to
- * en_US.
+ * en_us.
*
* @param path the path of the page to get the content of.
* @return the content of the page, or null if none exists.
@@ -119,7 +119,7 @@ public interface ManualAPI {
*
* @param player the player to open the manual for.
*/
- void openFor(EntityPlayer player);
+ void openFor(PlayerEntity player);
/**
* Reset the history of the manual.
diff --git a/src/main/java/li/cil/oc/api/detail/NanomachinesAPI.java b/src/main/java/li/cil/oc/api/detail/NanomachinesAPI.java
index 4a85f5fcf7..3459c3e86c 100644
--- a/src/main/java/li/cil/oc/api/detail/NanomachinesAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/NanomachinesAPI.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.nanomachines.BehaviorProvider;
import li.cil.oc.api.nanomachines.Controller;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
public interface NanomachinesAPI {
/**
@@ -29,7 +29,7 @@ public interface NanomachinesAPI {
* @param player the player to check for.
* @return true if the player has a controller, false otherwise.
*/
- boolean hasController(EntityPlayer player);
+ boolean hasController(PlayerEntity player);
/**
* Get the nanomachine controller of the specified player.
@@ -41,7 +41,7 @@ public interface NanomachinesAPI {
* @param player the player to get the controller for.
* @return the controller for the specified player.
*/
- Controller getController(EntityPlayer player);
+ Controller getController(PlayerEntity player);
/**
* Install a controller for the specified player if it doesn't already
@@ -53,7 +53,7 @@ public interface NanomachinesAPI {
* @param player the player to install a nanomachine controller for.
* @return the controller for the specified player.
*/
- Controller installController(EntityPlayer player);
+ Controller installController(PlayerEntity player);
/**
* Uninstall a controller from the specified player if it has one.
@@ -62,5 +62,5 @@ public interface NanomachinesAPI {
*
* @param player the player to uninstall a nanomachine controller from.
*/
- void uninstallController(EntityPlayer player);
+ void uninstallController(PlayerEntity player);
}
diff --git a/src/main/java/li/cil/oc/api/detail/NetworkAPI.java b/src/main/java/li/cil/oc/api/detail/NetworkAPI.java
index 967f4f1fd1..b48d129989 100644
--- a/src/main/java/li/cil/oc/api/detail/NetworkAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/NetworkAPI.java
@@ -5,14 +5,16 @@
import li.cil.oc.api.network.Packet;
import li.cil.oc.api.network.Visibility;
import li.cil.oc.api.network.WirelessEndpoint;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.RegistryKey;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.IBlockReader;
+import net.minecraft.world.World;
public interface NetworkAPI {
/**
- * Convenience overload for {@link #joinOrCreateNetwork(IBlockAccess, BlockPos)}.
+ * Convenience overload for {@link #joinOrCreateNetwork(IBlockReader, BlockPos)}.
*
* If the tile entity implements {@link Environment} its one node will be
* connected to any existing adjacent tile entity nodes. If none exist a
@@ -34,7 +36,7 @@ public interface NetworkAPI {
* @param world the world containing the location to connect.
* @param pos the position at which to update the network.
*/
- void joinOrCreateNetwork(IBlockAccess world, BlockPos pos);
+ void joinOrCreateNetwork(IBlockReader world, BlockPos pos);
/**
* Creates a new network with the specified node as its initial node.
@@ -101,7 +103,7 @@ public interface NetworkAPI {
* @param endpoint the endpoint to remove from the wireless network.
* @param dimension the dimension with the wireless network to remove the endpoint from.
*/
- void leaveWirelessNetwork(WirelessEndpoint endpoint, int dimension);
+ void leaveWirelessNetwork(WirelessEndpoint endpoint, RegistryKey dimension);
/**
* Sends a packet via the wireless network.
@@ -182,5 +184,5 @@ public interface NetworkAPI {
* @param nbt the tag to load the packet from.
* @return the loaded packet.
*/
- Packet newPacket(NBTTagCompound nbt);
+ Packet newPacket(CompoundNBT nbt);
}
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/driver/DriverBlock.java b/src/main/java/li/cil/oc/api/driver/DriverBlock.java
index 9dd7891c2c..69fd372c06 100644
--- a/src/main/java/li/cil/oc/api/driver/DriverBlock.java
+++ b/src/main/java/li/cil/oc/api/driver/DriverBlock.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.network.ManagedEnvironment;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
import net.minecraft.world.World;
/**
@@ -44,7 +44,7 @@ public interface DriverBlock {
* @param side the side of the block to check.
* @return true if the block is supported; false otherwise.
*/
- boolean worksWith(World world, BlockPos pos, EnumFacing side);
+ boolean worksWith(World world, BlockPos pos, Direction side);
/**
* Create a new managed environment interfacing the specified block.
@@ -67,5 +67,5 @@ public interface DriverBlock {
* @param side the side of the block to check.
* @return the environment for the block at that location.
*/
- ManagedEnvironment createEnvironment(World world, BlockPos pos, EnumFacing side);
+ ManagedEnvironment createEnvironment(World world, BlockPos pos, Direction side);
}
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/driver/DriverItem.java b/src/main/java/li/cil/oc/api/driver/DriverItem.java
index 965d658182..98b42d2823 100644
--- a/src/main/java/li/cil/oc/api/driver/DriverItem.java
+++ b/src/main/java/li/cil/oc/api/driver/DriverItem.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.network.ManagedEnvironment;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* Interface for item component drivers.
@@ -110,5 +110,5 @@ public interface DriverItem {
* @return the tag to use for saving and loading, or null to use
* the default tag oc:data.
*/
- NBTTagCompound dataTag(ItemStack stack);
+ CompoundNBT dataTag(ItemStack stack);
}
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/driver/InventoryProvider.java b/src/main/java/li/cil/oc/api/driver/InventoryProvider.java
index 4308b454a0..e231318a2d 100644
--- a/src/main/java/li/cil/oc/api/driver/InventoryProvider.java
+++ b/src/main/java/li/cil/oc/api/driver/InventoryProvider.java
@@ -1,6 +1,6 @@
package li.cil.oc.api.driver;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
@@ -13,7 +13,7 @@
* the inventory controller upgrade, for example.
*
* Implementations returned by {@link #getInventory} should save changes
- * back to the item stack when {@link IInventory#markDirty()} is called.
+ * back to the item stack when {@link IInventory#setChanged()} is called.
* Return null if the specified stack is not supported.
*/
public interface InventoryProvider {
@@ -24,7 +24,7 @@ public interface InventoryProvider {
* @param player the player holding the item, may be null.
* @return true if the stack is supported, false otherwise.
*/
- boolean worksWith(ItemStack stack, EntityPlayer player);
+ boolean worksWith(ItemStack stack, PlayerEntity player);
/**
* Get an inventory implementation that allows interfacing with the
@@ -38,5 +38,5 @@ public interface InventoryProvider {
* @param player the player holding the item, may be null.
* @return the inventory representing the contents, or null.
*/
- IInventory getInventory(ItemStack stack, EntityPlayer player);
+ IInventory getInventory(ItemStack stack, PlayerEntity player);
}
diff --git a/src/main/java/li/cil/oc/api/driver/MethodWhitelist.java b/src/main/java/li/cil/oc/api/driver/MethodWhitelist.java
index 838f5785ab..25cdfb9e5e 100644
--- a/src/main/java/li/cil/oc/api/driver/MethodWhitelist.java
+++ b/src/main/java/li/cil/oc/api/driver/MethodWhitelist.java
@@ -17,7 +17,7 @@
* suppress inventory functionality if your TileEntity implements IInventory.
*
* To do so, implement this interface in the environment that you
- * return from your driver's {@link DriverBlock#createEnvironment(net.minecraft.world.World, BlockPos, net.minecraft.util.EnumFacing)}
+ * return from your driver's {@link DriverBlock#createEnvironment(net.minecraft.world.World, BlockPos, net.minecraft.util.Direction)}
* method, and provide the names of the allowed methods from {@link #whitelistedMethods()}.
*
* Important: if multiple drivers apply to a single block that each
diff --git a/src/main/java/li/cil/oc/api/driver/NamedBlock.java b/src/main/java/li/cil/oc/api/driver/NamedBlock.java
index 91796fd1c2..4a869bd10f 100644
--- a/src/main/java/li/cil/oc/api/driver/NamedBlock.java
+++ b/src/main/java/li/cil/oc/api/driver/NamedBlock.java
@@ -9,7 +9,7 @@
*
* This was previously to be implemented on the driver itself, but that has been
* deprecated. Implement it in the environment returned from the block driver's
- * {@link DriverBlock#createEnvironment(net.minecraft.world.World, BlockPos, net.minecraft.util.EnumFacing)}
+ * {@link DriverBlock#createEnvironment(net.minecraft.world.World, BlockPos, net.minecraft.util.Direction)}
* method instead.
*/
public interface NamedBlock {
diff --git a/src/main/java/li/cil/oc/api/driver/item/UpgradeRenderer.java b/src/main/java/li/cil/oc/api/driver/item/UpgradeRenderer.java
index 87bc9f1ad0..5edf64b84b 100644
--- a/src/main/java/li/cil/oc/api/driver/item/UpgradeRenderer.java
+++ b/src/main/java/li/cil/oc/api/driver/item/UpgradeRenderer.java
@@ -1,10 +1,12 @@
package li.cil.oc.api.driver.item;
+import com.mojang.blaze3d.matrix.MatrixStack;
import li.cil.oc.api.event.RobotRenderEvent;
import li.cil.oc.api.internal.Robot;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.item.ItemStack;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
import java.util.Set;
@@ -72,7 +74,7 @@ public interface UpgradeRenderer {
* @param robot the robot the upgrade is rendered on.
* @param pt partial tick time, e.g. for animations.
*/
- void render(ItemStack stack, RobotRenderEvent.MountPoint mountPoint, Robot robot, float pt);
+ void render(MatrixStack matrix, IRenderTypeBuffer buffer, ItemStack stack, RobotRenderEvent.MountPoint mountPoint, Robot robot, float pt);
/**
* Mount point names for {@link #computePreferredMountPoint}.
diff --git a/src/main/java/li/cil/oc/api/driver/item/package-info.java b/src/main/java/li/cil/oc/api/driver/item/package-info.java
index 61ba9e400f..ecb06d065a 100644
--- a/src/main/java/li/cil/oc/api/driver/item/package-info.java
+++ b/src/main/java/li/cil/oc/api/driver/item/package-info.java
@@ -4,10 +4,6 @@
* These interfaces allow specializing item drivers to provide static data,
* that is without creating an actual environment.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|driver|item",
- apiVersion = API.VERSION)
package li.cil.oc.api.driver.item;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/driver/package-info.java b/src/main/java/li/cil/oc/api/driver/package-info.java
index 76cca59f09..1e8d4c5d80 100644
--- a/src/main/java/li/cil/oc/api/driver/package-info.java
+++ b/src/main/java/li/cil/oc/api/driver/package-info.java
@@ -4,10 +4,6 @@
* Drivers are used to add items and third party blocks to the internal network,
* which is mostly used to make components wrapping them available to computers.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|driver",
- apiVersion = API.VERSION)
package li.cil.oc.api.driver;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/event/FileSystemAccessEvent.java b/src/main/java/li/cil/oc/api/event/FileSystemAccessEvent.java
index 4a649f7ea2..3e2f9bfb93 100644
--- a/src/main/java/li/cil/oc/api/event/FileSystemAccessEvent.java
+++ b/src/main/java/li/cil/oc/api/event/FileSystemAccessEvent.java
@@ -1,11 +1,11 @@
package li.cil.oc.api.event;
import li.cil.oc.api.network.Node;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
-import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraftforge.eventbus.api.Cancelable;
+import net.minecraftforge.eventbus.api.Event;
/**
* Events for handling file system access and representing it on the client.
@@ -33,7 +33,7 @@ public class FileSystemAccessEvent extends Event {
protected TileEntity tileEntity;
- protected NBTTagCompound data;
+ protected CompoundNBT data;
/**
* Constructor for tile entity hosted file systems.
@@ -42,12 +42,12 @@ public class FileSystemAccessEvent extends Event {
* @param tileEntity the tile entity hosting the file system.
* @param data the additional data.
*/
- protected FileSystemAccessEvent(String sound, TileEntity tileEntity, NBTTagCompound data) {
+ protected FileSystemAccessEvent(String sound, TileEntity tileEntity, CompoundNBT data) {
this.sound = sound;
- this.world = tileEntity.getWorld();
- this.x = tileEntity.getPos().getX() + 0.5;
- this.y = tileEntity.getPos().getY() + 0.5;
- this.z = tileEntity.getPos().getZ() + 0.5;
+ this.world = tileEntity.getLevel();
+ this.x = tileEntity.getBlockPos().getX() + 0.5;
+ this.y = tileEntity.getBlockPos().getY() + 0.5;
+ this.z = tileEntity.getBlockPos().getZ() + 0.5;
this.tileEntity = tileEntity;
this.data = data;
}
@@ -62,7 +62,7 @@ protected FileSystemAccessEvent(String sound, TileEntity tileEntity, NBTTagCompo
* @param z the z coordinate of the file system's container.
* @param data the additional data.
*/
- protected FileSystemAccessEvent(String sound, World world, double x, double y, double z, NBTTagCompound data) {
+ protected FileSystemAccessEvent(String sound, World world, double x, double y, double z, CompoundNBT data) {
this.sound = sound;
this.world = world;
this.x = x;
@@ -113,7 +113,7 @@ public double getZ() {
* Important: this can be null, which is usually the
* case when the container is an entity or item.
*/
- public TileEntity getTileEntity() {
+ public TileEntity getBlockEntity() {
return tileEntity;
}
@@ -121,7 +121,7 @@ public TileEntity getTileEntity() {
* Addition custom data, this is used to transmit the number of the server
* in a server rack the file system lives in, for example.
*/
- public NBTTagCompound getData() {
+ public CompoundNBT getData() {
return data;
}
@@ -129,12 +129,12 @@ public static final class Server extends FileSystemAccessEvent {
private Node node;
public Server(String sound, TileEntity tileEntity, Node node) {
- super(sound, tileEntity, new NBTTagCompound());
+ super(sound, tileEntity, new CompoundNBT());
this.node = node;
}
public Server(String sound, World world, double x, double y, double z, Node node) {
- super(sound, world, x, y, z, new NBTTagCompound());
+ super(sound, world, x, y, z, new CompoundNBT());
this.node = node;
}
@@ -154,7 +154,7 @@ public static final class Client extends FileSystemAccessEvent {
* @param tileEntity the tile entity hosting the file system.
* @param data the additional data.
*/
- public Client(String sound, TileEntity tileEntity, NBTTagCompound data) {
+ public Client(String sound, TileEntity tileEntity, CompoundNBT data) {
super(sound, tileEntity, data);
}
@@ -168,7 +168,7 @@ public Client(String sound, TileEntity tileEntity, NBTTagCompound data) {
* @param z the z coordinate of the file system's container.
* @param data the additional data.
*/
- public Client(String sound, World world, double x, double y, double z, NBTTagCompound data) {
+ public Client(String sound, World world, double x, double y, double z, CompoundNBT data) {
super(sound, world, x, y, z, data);
}
}
diff --git a/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java b/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java
index 1dc5865567..62437d6dc1 100644
--- a/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java
+++ b/src/main/java/li/cil/oc/api/event/GeolyzerEvent.java
@@ -2,8 +2,8 @@
import li.cil.oc.api.network.EnvironmentHost;
import net.minecraft.util.math.BlockPos;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
-import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraftforge.eventbus.api.Cancelable;
+import net.minecraftforge.eventbus.api.Event;
import java.util.HashMap;
import java.util.Map;
diff --git a/src/main/java/li/cil/oc/api/event/NetworkActivityEvent.java b/src/main/java/li/cil/oc/api/event/NetworkActivityEvent.java
index 918f31fe6d..2e2ae9f762 100644
--- a/src/main/java/li/cil/oc/api/event/NetworkActivityEvent.java
+++ b/src/main/java/li/cil/oc/api/event/NetworkActivityEvent.java
@@ -1,10 +1,10 @@
package li.cil.oc.api.event;
import li.cil.oc.api.network.Node;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
-import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraftforge.eventbus.api.Event;
/**
* Events for handling network activity and representing it on the client.
@@ -29,7 +29,7 @@ public class NetworkActivityEvent extends Event {
protected TileEntity tileEntity;
- protected NBTTagCompound data;
+ protected CompoundNBT data;
/**
* Constructor for tile entity hosted network cards.
@@ -37,11 +37,11 @@ public class NetworkActivityEvent extends Event {
* @param tileEntity the tile entity hosting the network card.
* @param data the additional data.
*/
- protected NetworkActivityEvent(TileEntity tileEntity, NBTTagCompound data) {
- this.world = tileEntity.getWorld();
- this.x = tileEntity.getPos().getX() + 0.5;
- this.y = tileEntity.getPos().getY() + 0.5;
- this.z = tileEntity.getPos().getZ() + 0.5;
+ protected NetworkActivityEvent(TileEntity tileEntity, CompoundNBT data) {
+ this.world = tileEntity.getLevel();
+ this.x = tileEntity.getBlockPos().getX() + 0.5;
+ this.y = tileEntity.getBlockPos().getY() + 0.5;
+ this.z = tileEntity.getBlockPos().getZ() + 0.5;
this.tileEntity = tileEntity;
this.data = data;
}
@@ -55,7 +55,7 @@ protected NetworkActivityEvent(TileEntity tileEntity, NBTTagCompound data) {
* @param z the z coordinate of the network card's container.
* @param data the additional data.
*/
- protected NetworkActivityEvent(World world, double x, double y, double z, NBTTagCompound data) {
+ protected NetworkActivityEvent(World world, double x, double y, double z, CompoundNBT data) {
this.world = world;
this.x = x;
this.y = y;
@@ -98,7 +98,7 @@ public double getZ() {
* Important: this can be null, which is usually the
* case when the container is an entity or item.
*/
- public TileEntity getTileEntity() {
+ public TileEntity getBlockEntity() {
return tileEntity;
}
@@ -106,7 +106,7 @@ public TileEntity getTileEntity() {
* Addition custom data, this is used to transmit the number of the server
* in a server rack the network card lives in, for example.
*/
- public NBTTagCompound getData() {
+ public CompoundNBT getData() {
return data;
}
@@ -114,12 +114,12 @@ public static final class Server extends NetworkActivityEvent {
private Node node;
public Server(TileEntity tileEntity, Node node) {
- super(tileEntity, new NBTTagCompound());
+ super(tileEntity, new CompoundNBT());
this.node = node;
}
public Server(World world, double x, double y, double z, Node node) {
- super(world, x, y, z, new NBTTagCompound());
+ super(world, x, y, z, new CompoundNBT());
this.node = node;
}
@@ -138,7 +138,7 @@ public static final class Client extends NetworkActivityEvent {
* @param tileEntity the tile entity hosting the network card.
* @param data the additional data.
*/
- public Client(TileEntity tileEntity, NBTTagCompound data) {
+ public Client(TileEntity tileEntity, CompoundNBT data) {
super(tileEntity, data);
}
@@ -151,7 +151,7 @@ public Client(TileEntity tileEntity, NBTTagCompound data) {
* @param z the z coordinate of the network card's container.
* @param data the additional data.
*/
- public Client(World world, double x, double y, double z, NBTTagCompound data) {
+ public Client(World world, double x, double y, double z, CompoundNBT data) {
super(world, x, y, z, data);
}
}
diff --git a/src/main/java/li/cil/oc/api/event/RackMountableRenderEvent.java b/src/main/java/li/cil/oc/api/event/RackMountableRenderEvent.java
index fc77c14fc1..4f689859c9 100644
--- a/src/main/java/li/cil/oc/api/event/RackMountableRenderEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RackMountableRenderEvent.java
@@ -1,19 +1,16 @@
package li.cil.oc.api.event;
+import com.mojang.blaze3d.matrix.MatrixStack;
import li.cil.oc.api.component.RackMountable;
import li.cil.oc.api.internal.Rack;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
-import net.minecraft.client.renderer.texture.TextureMap;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.nbt.CompoundNBT;
+import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
-import net.minecraftforge.fml.common.eventhandler.Event;
-import org.lwjgl.opengl.GL11;
+import net.minecraftforge.eventbus.api.Cancelable;
+import net.minecraftforge.eventbus.api.Event;
/**
* Fired to allow rendering a custom overlay for {@link li.cil.oc.api.component.RackMountable}s.
@@ -39,9 +36,9 @@ public abstract class RackMountableRenderEvent extends Event {
*
* @see RackMountable#getData()
*/
- public final NBTTagCompound data;
+ public final CompoundNBT data;
- public RackMountableRenderEvent(Rack rack, int mountable, NBTTagCompound data) {
+ public RackMountableRenderEvent(Rack rack, int mountable, CompoundNBT data) {
this.rack = rack;
this.mountable = mountable;
this.data = data;
@@ -62,14 +59,14 @@ public static class Block extends RackMountableRenderEvent {
/**
* The front-facing side, i.e. where the mountable is visible on the rack.
*/
- public final EnumFacing side;
+ public final Direction side;
/**
* Texture to use for the front of the mountable.
*/
private TextureAtlasSprite frontTextureOverride;
- public Block(final Rack rack, final int mountable, final NBTTagCompound data, final EnumFacing side) {
+ public Block(final Rack rack, final int mountable, final CompoundNBT data, final Direction side) {
super(rack, mountable, data);
this.side = side;
}
@@ -94,7 +91,7 @@ public void setFrontTextureOverride(final TextureAtlasSprite texture) {
/**
* Fired when the dynamic rack model is rendered.
*
- * Code here runs inside a TileEntitySpecialRenderer, so go nuts. This is
+ * Code here runs inside a TileEntityRenderer, so go nuts. This is
* primarily meant to allow rendering custom overlays, such as LEDs. The GL state
* will have been adjusted such that rendering a one by one quad starting at the
* origin will fill the full front face of the rack (i.e. rotation and translation
@@ -108,75 +105,35 @@ public void setFrontTextureOverride(final TextureAtlasSprite texture) {
*/
public static class TileEntity extends RackMountableRenderEvent {
/**
- * The vertical low and high texture coordinates for the mountable's slot.
- *
- * This is purely for convenience; they're computed as (2/16)+i*(3/16).
+ * The transformation used by the rendering engine.
*/
- public final float v0, v1;
-
- public TileEntity(final Rack rack, final int mountable, final NBTTagCompound data, final float v0, final float v1) {
- super(rack, mountable, data);
- this.v0 = v0;
- this.v1 = v1;
- }
+ public final MatrixStack stack;
/**
- * Utility method for rendering a texture as the front-side overlay.
- *
- * @param texture the texture to use to render the overlay.
+ * An accessor to the renderer's buffer context.
*/
- public void renderOverlay(final ResourceLocation texture) {
- renderOverlay(texture, 0, 1);
- }
+ public final IRenderTypeBuffer typeBuffer;
/**
- * Utility method for rendering a texture as the front-side overlay
- * over a specified horizontal area.
- *
- * @param texture the texture to use to render the overlay.
- * @param u0 the lower end of the vertical area to render at.
- * @param u1 the upper end of the vertical area to render at.
+ * Packed block light and overlay texture coordinates.
*/
- public void renderOverlay(final ResourceLocation texture, final float u0, final float u1) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(texture);
- final Tessellator t = Tessellator.getInstance();
- final BufferBuilder r = t.getBuffer();
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
- r.pos(u0, v1, 0).tex(u0, v1).endVertex();
- r.pos(u1, v1, 0).tex(u1, v1).endVertex();
- r.pos(u1, v0, 0).tex(u1, v0).endVertex();
- r.pos(u0, v0, 0).tex(u0, v0).endVertex();
- t.draw();
- }
+ public final int light, overlay;
/**
- * Utility method for rendering an atlas texture as the front-side overlay.
- *
- * @param texture the atlas texture to use to render the overlay.
+ * The vertical low and high texture coordinates for the mountable's slot.
+ *
+ * This is purely for convenience; they're computed as (2/16)+i*(3/16).
*/
- public void renderOverlayFromAtlas(final ResourceLocation texture) {
- renderOverlayFromAtlas(texture, 0, 1);
- }
+ public final float v0, v1;
- /**
- * Utility method for rendering an atlas texture as the front-side overlay
- * over a specified horizontal area.
- *
- * @param texture the atlas texture to use to render the overlay.
- * @param u0 the lower end of the vertical area to render at.
- * @param u1 the upper end of the vertical area to render at.
- */
- public void renderOverlayFromAtlas(final ResourceLocation texture, final float u0, final float u1) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
- final TextureAtlasSprite icon = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(texture.toString());
- final Tessellator t = Tessellator.getInstance();
- final BufferBuilder r = t.getBuffer();
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
- r.pos(u0, v1, 0).tex(icon.getInterpolatedU(u0 * 16), icon.getInterpolatedV(v1 * 16)).endVertex();
- r.pos(u1, v1, 0).tex(icon.getInterpolatedU(u1 * 16), icon.getInterpolatedV(v1 * 16)).endVertex();
- r.pos(u1, v0, 0).tex(icon.getInterpolatedU(u1 * 16), icon.getInterpolatedV(v0 * 16)).endVertex();
- r.pos(u0, v0, 0).tex(icon.getInterpolatedU(u0 * 16), icon.getInterpolatedV(v0 * 16)).endVertex();
- t.draw();
+ public TileEntity(final Rack rack, final int mountable, final CompoundNBT data, final MatrixStack stack, final IRenderTypeBuffer typeBuffer, final int light, final int overlay, final float v0, final float v1) {
+ super(rack, mountable, data);
+ this.stack = stack;
+ this.typeBuffer = typeBuffer;
+ this.light = light;
+ this.overlay = overlay;
+ this.v0 = v0;
+ this.v1 = v1;
}
}
}
diff --git a/src/main/java/li/cil/oc/api/event/RobotAnalyzeEvent.java b/src/main/java/li/cil/oc/api/event/RobotAnalyzeEvent.java
index b1497ab402..49309e9ded 100644
--- a/src/main/java/li/cil/oc/api/event/RobotAnalyzeEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotAnalyzeEvent.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.event;
import li.cil.oc.api.internal.Agent;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
/**
* Fired when an analyzer is used on a robot.
@@ -12,9 +12,9 @@ public class RobotAnalyzeEvent extends RobotEvent {
/**
* The player that used the analyzer.
*/
- public final EntityPlayer player;
+ public final PlayerEntity player;
- public RobotAnalyzeEvent(Agent agent, EntityPlayer player) {
+ public RobotAnalyzeEvent(Agent agent, PlayerEntity player) {
super(agent);
this.player = player;
}
diff --git a/src/main/java/li/cil/oc/api/event/RobotAttackEntityEvent.java b/src/main/java/li/cil/oc/api/event/RobotAttackEntityEvent.java
index 55a7501888..a2ecac8141 100644
--- a/src/main/java/li/cil/oc/api/event/RobotAttackEntityEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotAttackEntityEvent.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.internal.Agent;
import net.minecraft.entity.Entity;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
+import net.minecraftforge.eventbus.api.Cancelable;
public class RobotAttackEntityEvent extends RobotEvent {
/**
diff --git a/src/main/java/li/cil/oc/api/event/RobotBreakBlockEvent.java b/src/main/java/li/cil/oc/api/event/RobotBreakBlockEvent.java
index 5e11343aa5..2281d7d899 100644
--- a/src/main/java/li/cil/oc/api/event/RobotBreakBlockEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotBreakBlockEvent.java
@@ -3,7 +3,7 @@
import li.cil.oc.api.internal.Agent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
+import net.minecraftforge.eventbus.api.Cancelable;
public abstract class RobotBreakBlockEvent extends RobotEvent {
protected RobotBreakBlockEvent(Agent agent) {
diff --git a/src/main/java/li/cil/oc/api/event/RobotEvent.java b/src/main/java/li/cil/oc/api/event/RobotEvent.java
index a8672a04b5..0fb168ac28 100644
--- a/src/main/java/li/cil/oc/api/event/RobotEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotEvent.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.event;
import li.cil.oc.api.internal.Agent;
-import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraftforge.eventbus.api.Event;
/**
* Base class for events generated by robots.
diff --git a/src/main/java/li/cil/oc/api/event/RobotMoveEvent.java b/src/main/java/li/cil/oc/api/event/RobotMoveEvent.java
index d1c8f7096c..d721e0e264 100644
--- a/src/main/java/li/cil/oc/api/event/RobotMoveEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotMoveEvent.java
@@ -1,16 +1,16 @@
package li.cil.oc.api.event;
import li.cil.oc.api.internal.Agent;
-import net.minecraft.util.EnumFacing;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
+import net.minecraft.util.Direction;
+import net.minecraftforge.eventbus.api.Cancelable;
public abstract class RobotMoveEvent extends RobotEvent {
/**
* The direction in which the robot will be moving.
*/
- public final EnumFacing direction;
+ public final Direction direction;
- protected RobotMoveEvent(Agent agent, EnumFacing direction) {
+ protected RobotMoveEvent(Agent agent, Direction direction) {
super(agent);
this.direction = direction;
}
@@ -22,7 +22,7 @@ protected RobotMoveEvent(Agent agent, EnumFacing direction) {
*/
@Cancelable
public static class Pre extends RobotMoveEvent {
- public Pre(Agent agent, EnumFacing direction) {
+ public Pre(Agent agent, Direction direction) {
super(agent, direction);
}
}
@@ -31,7 +31,7 @@ public Pre(Agent agent, EnumFacing direction) {
* Fired after a robot moved.
*/
public static class Post extends RobotMoveEvent {
- public Post(Agent agent, EnumFacing direction) {
+ public Post(Agent agent, Direction direction) {
super(agent, direction);
}
}
diff --git a/src/main/java/li/cil/oc/api/event/RobotPlaceBlockEvent.java b/src/main/java/li/cil/oc/api/event/RobotPlaceBlockEvent.java
index 36cb5e60f7..07df5919fd 100644
--- a/src/main/java/li/cil/oc/api/event/RobotPlaceBlockEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotPlaceBlockEvent.java
@@ -4,7 +4,7 @@
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
+import net.minecraftforge.eventbus.api.Cancelable;
public abstract class RobotPlaceBlockEvent extends RobotEvent {
/**
diff --git a/src/main/java/li/cil/oc/api/event/RobotRenderEvent.java b/src/main/java/li/cil/oc/api/event/RobotRenderEvent.java
index 4b20d0364b..9aeef42801 100644
--- a/src/main/java/li/cil/oc/api/event/RobotRenderEvent.java
+++ b/src/main/java/li/cil/oc/api/event/RobotRenderEvent.java
@@ -4,9 +4,10 @@
import li.cil.oc.api.internal.Agent;
import li.cil.oc.api.internal.Robot;
import net.minecraft.item.ItemStack;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
-import org.lwjgl.util.vector.Vector3f;
-import org.lwjgl.util.vector.Vector4f;
+import net.minecraftforge.eventbus.api.Cancelable;
+import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.vector.Vector3f;
+import net.minecraft.util.math.vector.Vector4f;
import java.util.Set;
@@ -34,9 +35,59 @@ public class RobotRenderEvent extends RobotEvent {
*/
public final MountPoint[] mountPoints;
+ /**
+ * Overrides the color of the robot chassis' light. Only used if greater
+ * or equal to zero. Consists of 8 bits per channel: red, green and blue.
+ * The color override does NOT apply to this color.
+ */
+ public int lightColor;
+
+ private float mulR, mulG, mulB;
+
public RobotRenderEvent(Agent agent, MountPoint[] mountPoints) {
super(agent);
this.mountPoints = mountPoints;
+ lightColor = -1;
+ mulR = mulG = mulB = 1.0f;
+ }
+
+ /**
+ * Convenience method for setting {@link #lightColor}. Will clamp values
+ * to between 0 and 1 and pack them into an RGB integer.
+ */
+ public void setLightColor(float r, float g, float b) {
+ int ir = MathHelper.floor(0.5f + 255 * MathHelper.clamp(r, 0.0f, 1.0f));
+ int ig = MathHelper.floor(0.5f + 255 * MathHelper.clamp(g, 0.0f, 1.0f));
+ int ib = MathHelper.floor(0.5f + 255 * MathHelper.clamp(b, 0.0f, 1.0f));
+ lightColor = (ir << 16) | (ig << 8) | ib;
+ }
+
+ /**
+ * Multiplies the color or the robot chassis by a certain value. Each
+ * color component is clamped to between 0 and 1. This multiplier is
+ * cumulative, meaning if it is update too many times the robot will
+ * end up black (multiplier zero). This does not affect the light in
+ * the middle of the robot, nor does it affect upgrades.
+ *
+ * Use {@link #getColorMultiplier()} to obtain the pure multiplier or
+ * {@link #getColorMultiplier(float, float, float)} if you need to mix
+ * your own color into it.
+ */
+ public void multiplyColors(float r, float g, float b) {
+ mulR *= MathHelper.clamp(r, 0.0f, 1.0f);
+ mulG *= MathHelper.clamp(g, 0.0f, 1.0f);
+ mulB *= MathHelper.clamp(b, 0.0f, 1.0f);
+ }
+
+ public int getColorMultiplier() {
+ return getColorValue(1.0f, 1.0f, 1.0f);
+ }
+
+ public int getColorValue(float rm, float gm, float bm) {
+ int r = MathHelper.floor(0.5f + 255 * MathHelper.clamp(rm * mulR, 0.0f, 1.0f));
+ int g = MathHelper.floor(0.5f + 255 * MathHelper.clamp(gm * mulG, 0.0f, 1.0f));
+ int b = MathHelper.floor(0.5f + 255 * MathHelper.clamp(bm * mulB, 0.0f, 1.0f));
+ return (r << 16) | (g << 8) | b;
}
/**
diff --git a/src/main/java/li/cil/oc/api/event/SignChangeEvent.java b/src/main/java/li/cil/oc/api/event/SignChangeEvent.java
index 64321c25f1..88a09b002f 100644
--- a/src/main/java/li/cil/oc/api/event/SignChangeEvent.java
+++ b/src/main/java/li/cil/oc/api/event/SignChangeEvent.java
@@ -1,30 +1,30 @@
package li.cil.oc.api.event;
-import net.minecraft.tileentity.TileEntitySign;
-import net.minecraftforge.fml.common.eventhandler.Cancelable;
-import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraft.tileentity.SignTileEntity;
+import net.minecraftforge.eventbus.api.Cancelable;
+import net.minecraftforge.eventbus.api.Event;
/**
* A bit more specific sign change event that holds information about new text of the sign. Used in the sign upgrade.
*/
public abstract class SignChangeEvent extends Event {
- public final TileEntitySign sign;
+ public final SignTileEntity sign;
public final String[] lines;
- private SignChangeEvent(TileEntitySign sign, String[] lines) {
+ private SignChangeEvent(SignTileEntity sign, String[] lines) {
this.sign = sign;
this.lines = lines;
}
@Cancelable
public static class Pre extends SignChangeEvent {
- public Pre(TileEntitySign sign, String[] lines) {
+ public Pre(SignTileEntity sign, String[] lines) {
super(sign, lines);
}
}
public static class Post extends SignChangeEvent {
- public Post(TileEntitySign sign, String[] lines) {
+ public Post(SignTileEntity sign, String[] lines) {
super(sign, lines);
}
}
diff --git a/src/main/java/li/cil/oc/api/event/package-info.java b/src/main/java/li/cil/oc/api/event/package-info.java
index 6173e66fad..f1758d349d 100644
--- a/src/main/java/li/cil/oc/api/event/package-info.java
+++ b/src/main/java/li/cil/oc/api/event/package-info.java
@@ -2,10 +2,6 @@
* Events dispatched by OpenComputers to allow other mods to hook into some
* of its functionality.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|event",
- apiVersion = API.VERSION)
package li.cil.oc.api.event;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/fs/package-info.java b/src/main/java/li/cil/oc/api/fs/package-info.java
index 6c466110b1..46d9d5a620 100644
--- a/src/main/java/li/cil/oc/api/fs/package-info.java
+++ b/src/main/java/li/cil/oc/api/fs/package-info.java
@@ -13,10 +13,6 @@
* that can be added as component nodes to the network, so they can be used
* from computers).
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|filesystem",
- apiVersion = API.VERSION)
package li.cil.oc.api.fs;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/internal/Agent.java b/src/main/java/li/cil/oc/api/internal/Agent.java
index 6f78c196b6..53a71356f7 100644
--- a/src/main/java/li/cil/oc/api/internal/Agent.java
+++ b/src/main/java/li/cil/oc/api/internal/Agent.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.internal;
import li.cil.oc.api.machine.MachineHost;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.IInventory;
import java.util.UUID;
@@ -67,7 +67,7 @@ public interface Agent extends MachineHost, Rotatable {
*
* @return the fake player for the agent.
*/
- EntityPlayer player();
+ PlayerEntity player();
/**
* Get the name of this agent.
diff --git a/src/main/java/li/cil/oc/api/internal/Drone.java b/src/main/java/li/cil/oc/api/internal/Drone.java
index 45a9aba3d6..95fcfe7ffe 100644
--- a/src/main/java/li/cil/oc/api/internal/Drone.java
+++ b/src/main/java/li/cil/oc/api/internal/Drone.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.internal;
import li.cil.oc.api.network.EnvironmentHost;
-import net.minecraft.util.math.Vec3d;
+import net.minecraft.util.math.vector.Vector3d;
/**
* This interface is implemented as a marker by drones.
@@ -20,7 +20,7 @@ public interface Drone extends Agent, EnvironmentHost, Rotatable, Tiered {
/**
* Get the current target coordinates of the drone.
*/
- Vec3d getTarget();
+ Vector3d getTarget();
/**
* Set the new target coordinates of the drone.
@@ -29,7 +29,7 @@ public interface Drone extends Agent, EnvironmentHost, Rotatable, Tiered {
* to avoid jitter on the client and floating point inaccuracies to
* accumulate.
*/
- void setTarget(Vec3d value);
+ void setTarget(Vector3d value);
/**
* Get the drones velocity vector.
@@ -38,5 +38,5 @@ public interface Drone extends Agent, EnvironmentHost, Rotatable, Tiered {
* so you can cast this to {@link net.minecraft.entity.Entity} and use that
* instead, if you'd like.
*/
- Vec3d getVelocity();
+ Vector3d getVelocity();
}
diff --git a/src/main/java/li/cil/oc/api/internal/Keyboard.java b/src/main/java/li/cil/oc/api/internal/Keyboard.java
index 7fdbf325a7..9ac4c7b6ed 100644
--- a/src/main/java/li/cil/oc/api/internal/Keyboard.java
+++ b/src/main/java/li/cil/oc/api/internal/Keyboard.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.Persistable;
import li.cil.oc.api.network.Environment;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
/**
* This interface is implemented by the keyboard component, to allow more
@@ -42,6 +42,6 @@ interface UsabilityChecker {
* @param player the player to check for.
* @return whether the keyboard is usable by the player.
*/
- boolean isUsableByPlayer(Keyboard keyboard, EntityPlayer player);
+ boolean isUsableByPlayer(Keyboard keyboard, PlayerEntity player);
}
}
diff --git a/src/main/java/li/cil/oc/api/internal/Rack.java b/src/main/java/li/cil/oc/api/internal/Rack.java
index 46aa88d3bc..9a11421a1b 100644
--- a/src/main/java/li/cil/oc/api/internal/Rack.java
+++ b/src/main/java/li/cil/oc/api/internal/Rack.java
@@ -4,7 +4,7 @@
import li.cil.oc.api.network.EnvironmentHost;
import li.cil.oc.api.network.SidedEnvironment;
import net.minecraft.inventory.IInventory;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* This interface is implemented by the rack tile entity.
@@ -48,7 +48,7 @@ public interface Rack extends SidedEnvironment, EnvironmentHost, Rotatable, IInv
* @param slot the slot of the mountable to get the data for.
* @return the data of the mountable in that slot, or null.
*/
- NBTTagCompound getMountableData(int slot);
+ CompoundNBT getMountableData(int slot);
/**
* Mark the mountable in the specified slot as changed.
diff --git a/src/main/java/li/cil/oc/api/internal/Robot.java b/src/main/java/li/cil/oc/api/internal/Robot.java
index ca5efa25fa..a94387a37c 100644
--- a/src/main/java/li/cil/oc/api/internal/Robot.java
+++ b/src/main/java/li/cil/oc/api/internal/Robot.java
@@ -3,8 +3,8 @@
import li.cil.oc.api.network.EnvironmentHost;
import li.cil.oc.api.network.Environment;
import net.minecraft.inventory.ISidedInventory;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
/**
* This interface allows interaction with robots.
@@ -74,7 +74,7 @@ public interface Robot extends Agent, Environment, EnvironmentHost, Tiered, ISid
* to know whether to resume animations or not, based on whether the robot
* is currently powered on or not.
*/
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
boolean shouldAnimate();
}
diff --git a/src/main/java/li/cil/oc/api/internal/Rotatable.java b/src/main/java/li/cil/oc/api/internal/Rotatable.java
index 2695770f15..af1d6ffedc 100644
--- a/src/main/java/li/cil/oc/api/internal/Rotatable.java
+++ b/src/main/java/li/cil/oc/api/internal/Rotatable.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.internal;
import li.cil.oc.api.driver.DriverItem;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
/**
* This interface is implemented by the computer case and robot tile entities
@@ -32,7 +32,7 @@ public interface Rotatable {
*
* @return the current facing.
*/
- EnumFacing facing();
+ Direction facing();
/**
* Converts a facing relative to the block's local coordinate
@@ -45,7 +45,7 @@ public interface Rotatable {
* @param value the value to translate.
* @return the translated orientation.
*/
- EnumFacing toGlobal(EnumFacing value);
+ Direction toGlobal(Direction value);
/**
* Converts a global orientation to a facing relative to the
@@ -58,5 +58,5 @@ public interface Rotatable {
* @param value the value to translate.
* @return the translated orientation.
*/
- EnumFacing toLocal(EnumFacing value);
+ Direction toLocal(Direction value);
}
diff --git a/src/main/java/li/cil/oc/api/internal/Tablet.java b/src/main/java/li/cil/oc/api/internal/Tablet.java
index e042685ac7..1b478170fb 100644
--- a/src/main/java/li/cil/oc/api/internal/Tablet.java
+++ b/src/main/java/li/cil/oc/api/internal/Tablet.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.network.EnvironmentHost;
import li.cil.oc.api.machine.MachineHost;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
/**
* This interface is implemented as a marker by tablets.
@@ -34,5 +34,5 @@ public interface Tablet extends EnvironmentHost, MachineHost, Rotatable {
*
* @return the player last holding the tablet.
*/
- EntityPlayer player();
+ PlayerEntity player();
}
diff --git a/src/main/java/li/cil/oc/api/internal/TextBuffer.java b/src/main/java/li/cil/oc/api/internal/TextBuffer.java
index 2c7d3bcc15..76f13c9d4e 100644
--- a/src/main/java/li/cil/oc/api/internal/TextBuffer.java
+++ b/src/main/java/li/cil/oc/api/internal/TextBuffer.java
@@ -1,10 +1,11 @@
package li.cil.oc.api.internal;
+import com.mojang.blaze3d.matrix.MatrixStack;
import li.cil.oc.api.Persistable;
import li.cil.oc.api.network.ManagedEnvironment;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
/**
* This interface implements functionality for displaying and manipulating
@@ -446,8 +447,8 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @return true if the displayed content changed since the last
* call to this method.
*/
- @SideOnly(Side.CLIENT)
- boolean renderText();
+ @OnlyIn(Dist.CLIENT)
+ boolean renderText(MatrixStack stack);
/**
* The natural width of the rendered text.
@@ -458,7 +459,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
*
* @return the total width of the rendered buffer, in pixels.
*/
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
int renderWidth();
/**
@@ -470,7 +471,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
*
* @return the total height of the rendered buffer, in pixels.
*/
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
int renderHeight();
/**
@@ -481,7 +482,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
*
* @param enabled whether the text buffer should be rendered.
*/
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
void setRenderingEnabled(boolean enabled);
/**
@@ -489,7 +490,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
*
* @see #setRenderingEnabled(boolean)
*/
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
boolean isRenderingEnabled();
// ----------------------------------------------------------------------- //
@@ -505,7 +506,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param code the key code of the pressed key.
* @param player the player that pressed the key. Pass null on the client side.
*/
- void keyDown(char character, int code, EntityPlayer player);
+ void keyDown(char character, int code, PlayerEntity player);
/**
* Signals a key up event for the buffer.
@@ -518,7 +519,20 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param code the key code of the released key.
* @param player the player that released the key. Pass null on the client side.
*/
- void keyUp(char character, int code, EntityPlayer player);
+ void keyUp(char character, int code, PlayerEntity player);
+
+ /**
+ * Signals a code-point (text) event for the buffer.
+ *
+ * On the client side this causes a packet to be sent to the server. On the
+ * server side this will trigger a message that will be picked up by
+ * keyboards, which will then cause a signal in attached machines.
+ *
+ * @param character the character of the released key.
+ * @param codePoint the code point being typed.
+ * @param player the player that typed the code point. Pass null on the client side.
+ */
+ void textInput(int codePoint, PlayerEntity player);
/**
* Signals a clipboard paste event for the buffer.
@@ -530,7 +544,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param value the text that was pasted.
* @param player the player that pasted the text. Pass null on the client side.
*/
- void clipboard(String value, EntityPlayer player);
+ void clipboard(String value, PlayerEntity player);
/**
* Signals a mouse button down event for the buffer.
@@ -543,7 +557,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param button the button of the mouse that was pressed.
* @param player the player that pressed the mouse button. Pass null on the client side.
*/
- void mouseDown(double x, double y, int button, EntityPlayer player);
+ void mouseDown(double x, double y, int button, PlayerEntity player);
/**
* Signals a mouse drag event for the buffer.
@@ -556,7 +570,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param button the button of the mouse that is pressed.
* @param player the player that moved the mouse. Pass null on the client side.
*/
- void mouseDrag(double x, double y, int button, EntityPlayer player);
+ void mouseDrag(double x, double y, int button, PlayerEntity player);
/**
* Signals a mouse button release event for the buffer.
@@ -569,7 +583,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param button the button of the mouse that was released.
* @param player the player that released the mouse button. Pass null on the client side.
*/
- void mouseUp(double x, double y, int button, EntityPlayer player);
+ void mouseUp(double x, double y, int button, PlayerEntity player);
/**
* Signals a mouse wheel scroll event for the buffer.
@@ -582,7 +596,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param delta indicates the direction of the mouse scroll.
* @param player the player that scrolled the mouse wheel. Pass null on the client side.
*/
- void mouseScroll(double x, double y, int delta, EntityPlayer player);
+ void mouseScroll(double x, double y, int delta, PlayerEntity player);
// ----------------------------------------------------------------------- //
diff --git a/src/main/java/li/cil/oc/api/internal/Wrench.java b/src/main/java/li/cil/oc/api/internal/Wrench.java
index f1584824af..7609aa8e3e 100644
--- a/src/main/java/li/cil/oc/api/internal/Wrench.java
+++ b/src/main/java/li/cil/oc/api/internal/Wrench.java
@@ -1,6 +1,6 @@
package li.cil.oc.api.internal;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -25,5 +25,5 @@ public interface Wrench {
* @param simulate whether to simulate the usage.
* @return whether the wrench can be used on the block.
*/
- boolean useWrenchOnBlock(EntityPlayer player, World world, BlockPos pos, boolean simulate);
+ boolean useWrenchOnBlock(PlayerEntity player, World world, BlockPos pos, boolean simulate);
}
diff --git a/src/main/java/li/cil/oc/api/internal/package-info.java b/src/main/java/li/cil/oc/api/internal/package-info.java
index 0cea951a40..f07112644f 100644
--- a/src/main/java/li/cil/oc/api/internal/package-info.java
+++ b/src/main/java/li/cil/oc/api/internal/package-info.java
@@ -13,10 +13,6 @@
* used inside the specified environment (where the environment class may
* be assignable to one of the interfaces in this package).
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|internal",
- apiVersion = API.VERSION)
package li.cil.oc.api.internal;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/machine/Architecture.java b/src/main/java/li/cil/oc/api/machine/Architecture.java
index 0bf190b44d..05d431da0c 100644
--- a/src/main/java/li/cil/oc/api/machine/Architecture.java
+++ b/src/main/java/li/cil/oc/api/machine/Architecture.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.machine;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
import java.lang.annotation.*;
@@ -134,13 +134,13 @@ public interface Architecture {
/**
* Restores the state of this architecture as previously saved in
- * {@link #save(NBTTagCompound)}. The architecture should be in the same
+ * {@link #saveData(CompoundNBT)}. The architecture should be in the same
* state it was when it was saved after this, so it can be resumed from
* whatever state the owning machine was in when it was saved.
*
* @param nbt the tag compound to save to.
*/
- void load(NBTTagCompound nbt);
+ void loadData(CompoundNBT nbt);
/**
* Saves the architecture for later restoration, e.g. across games or chunk
@@ -151,7 +151,7 @@ public interface Architecture {
*
* @param nbt the tag compound to save to.
*/
- void save(NBTTagCompound nbt);
+ void saveData(CompoundNBT nbt);
/**
* Architectures can be annotated with this to provide a nice display name.
diff --git a/src/main/java/li/cil/oc/api/machine/Context.java b/src/main/java/li/cil/oc/api/machine/Context.java
index b92aa75096..66dd616cb9 100644
--- a/src/main/java/li/cil/oc/api/machine/Context.java
+++ b/src/main/java/li/cil/oc/api/machine/Context.java
@@ -36,7 +36,7 @@ public interface Context {
* Use this to check whether you should signal something to the computer,
* for example. Note that for signals triggered via network messages there
* is a computer.checked_signal message, that expects an
- * EntityPlayer as the first argument and performs this check
+ * PlayerEntity as the first argument and performs this check
* before pushing the signal.
*
* @param player the name of the player to check for.
@@ -171,7 +171,7 @@ public interface Context {
*
Strings.
*
Byte arrays (which appear as strings on the Lua side, e.g.).
*
Maps if and only if both keys and values are strings.
- *
NBTTagCompounds.
+ *
CompoundNBTs.
*
* If an unsupported type is specified the method will enqueue nothing
* instead, resulting in a nil on the Lua side, e.g., and log a
diff --git a/src/main/java/li/cil/oc/api/machine/package-info.java b/src/main/java/li/cil/oc/api/machine/package-info.java
index 09b038befd..1f5c666e0f 100644
--- a/src/main/java/li/cil/oc/api/machine/package-info.java
+++ b/src/main/java/li/cil/oc/api/machine/package-info.java
@@ -16,10 +16,6 @@
* implemented, but merely to allow accessing some mod internals in a regulated
* fashion, such as {@link li.cil.oc.api.internal.Robot}.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|machine",
- apiVersion = API.VERSION)
package li.cil.oc.api.machine;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/manual/ImageRenderer.java b/src/main/java/li/cil/oc/api/manual/ImageRenderer.java
index 2dcad21f77..0e1a445481 100644
--- a/src/main/java/li/cil/oc/api/manual/ImageRenderer.java
+++ b/src/main/java/li/cil/oc/api/manual/ImageRenderer.java
@@ -1,5 +1,7 @@
package li.cil.oc.api.manual;
+import com.mojang.blaze3d.matrix.MatrixStack;
+
/**
* This allows implementing custom image renderers.
*
@@ -15,7 +17,7 @@ public interface ImageRenderer {
* The width of the area this renderer uses.
*
* This is used to offset the OpenGL state properly before calling
- * {@link #render(int, int)}, to correctly align the image horizontally.
+ * {@link #render(MatrixStack, int, int)}, to correctly align the image horizontally.
*
* @return the width of the rendered image.
*/
@@ -25,7 +27,7 @@ public interface ImageRenderer {
* The height of the area this renderer uses.
*
* This is used to offset the OpenGL state properly before calling
- * {@link #render(int, int)}, as well as to know where to resume rendering
+ * {@link #render(MatrixStack, int, int)}, as well as to know where to resume rendering
* other content below the image.
*
* @return the height of the rendered image.
@@ -40,8 +42,9 @@ public interface ImageRenderer {
* (getWidth,getHeight,*), i.e. translation and scaling are taken care
* of for you.
*
+ * @param stack the render transformation for this image
* @param mouseX the X position of the mouse relative to the element.
* @param mouseY the Y position of the mouse relative to the element.
*/
- void render(int mouseX, int mouseY);
+ void render(MatrixStack stack, int mouseX, int mouseY);
}
diff --git a/src/main/java/li/cil/oc/api/manual/PathProvider.java b/src/main/java/li/cil/oc/api/manual/PathProvider.java
index 4f796f2b2f..dc9701d87e 100644
--- a/src/main/java/li/cil/oc/api/manual/PathProvider.java
+++ b/src/main/java/li/cil/oc/api/manual/PathProvider.java
@@ -16,7 +16,7 @@
*
* Note that you can use the special variable %LANGUAGE% in your
* paths, for language agnostic paths. These will be resolved to the currently
- * set language, falling back to en_US, during actual content lookup.
+ * set language, falling back to en_us, during actual content lookup.
*/
public interface PathProvider {
/**
diff --git a/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java b/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java
index ee7af3a746..d8e68167c9 100644
--- a/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java
+++ b/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java
@@ -1,7 +1,8 @@
package li.cil.oc.api.manual;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import com.mojang.blaze3d.matrix.MatrixStack;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
/**
* Allows defining a renderer for a manual tab.
@@ -21,6 +22,6 @@ public interface TabIconRenderer {
* This should render something in a 16x16 area. The OpenGL state has been
* adjusted so that drawing starts at (0,0,0), and should go to (16,16,0).
*/
- @SideOnly(Side.CLIENT)
- void render();
+ @OnlyIn(Dist.CLIENT)
+ void render(MatrixStack stack);
}
diff --git a/src/main/java/li/cil/oc/api/manual/package-info.java b/src/main/java/li/cil/oc/api/manual/package-info.java
index eba0a4c2e9..cb61332b7c 100644
--- a/src/main/java/li/cil/oc/api/manual/package-info.java
+++ b/src/main/java/li/cil/oc/api/manual/package-info.java
@@ -5,10 +5,6 @@
* other mod that may choose to add its documentation to it, such as addon
* mods.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|manual",
- apiVersion = API.VERSION)
package li.cil.oc.api.manual;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/nanomachines/BehaviorProvider.java b/src/main/java/li/cil/oc/api/nanomachines/BehaviorProvider.java
index 4e0ecf9525..69bbadc9ed 100644
--- a/src/main/java/li/cil/oc/api/nanomachines/BehaviorProvider.java
+++ b/src/main/java/li/cil/oc/api/nanomachines/BehaviorProvider.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.nanomachines;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.nbt.CompoundNBT;
/**
* Implemented by providers for behaviors.
@@ -26,12 +26,12 @@ public interface BehaviorProvider {
* Note that this is only called on the server side when reconfiguring
* nanomachines. If you have a behavior that actually acts client-only,
* you still need to return it here, as it will be synchronized to the
- * client using {@link #writeToNBT} and {@link #readFromNBT}.
+ * client using {@link #save} and {@link #load}.
*
* @param player the player the behaviors should be created for.
* @return list of new behaviors, may be null.
*/
- Iterable createBehaviors(EntityPlayer player);
+ Iterable createBehaviors(PlayerEntity player);
/**
* Write a behavior to NBT.
@@ -45,7 +45,7 @@ public interface BehaviorProvider {
* @param behavior the behavior to serialize.
* @return the serialized representation of the specified behavior.
*/
- NBTTagCompound writeToNBT(Behavior behavior);
+ CompoundNBT save(Behavior behavior);
/**
* Restore a behavior from NBT.
@@ -62,5 +62,5 @@ public interface BehaviorProvider {
* @param nbt the tag to restore the behavior from.
* @return the restored behavior, or null if unhandled.
*/
- Behavior readFromNBT(EntityPlayer player, NBTTagCompound nbt);
+ Behavior load(PlayerEntity player, CompoundNBT nbt);
}
diff --git a/src/main/java/li/cil/oc/api/network/Analyzable.java b/src/main/java/li/cil/oc/api/network/Analyzable.java
index 204d577209..3fab595c6a 100644
--- a/src/main/java/li/cil/oc/api/network/Analyzable.java
+++ b/src/main/java/li/cil/oc/api/network/Analyzable.java
@@ -1,7 +1,7 @@
package li.cil.oc.api.network;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.Direction;
/**
* Allows defining a callback for when a block is right-clicked with an
@@ -31,5 +31,5 @@ public interface Analyzable {
* @return the nodes to display information for, usually an environment's
* main node (i.e. this.node()).
*/
- Node[] onAnalyze(EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ);
+ Node[] onAnalyze(PlayerEntity player, Direction side, float hitX, float hitY, float hitZ);
}
diff --git a/src/main/java/li/cil/oc/api/network/Environment.java b/src/main/java/li/cil/oc/api/network/Environment.java
index 906543874d..b0b63eccd1 100644
--- a/src/main/java/li/cil/oc/api/network/Environment.java
+++ b/src/main/java/li/cil/oc/api/network/Environment.java
@@ -18,20 +18,20 @@
* When a tile entity implements this interface a good way of connecting and
* disconnecting is the following pattern:
*
diff --git a/src/main/java/li/cil/oc/api/network/Network.java b/src/main/java/li/cil/oc/api/network/Network.java
index e1d6fa8931..577eafe17e 100644
--- a/src/main/java/li/cil/oc/api/network/Network.java
+++ b/src/main/java/li/cil/oc/api/network/Network.java
@@ -75,8 +75,8 @@ public interface Network {
* Removes a node from the network.
*
* This should be called by nodes when they are destroyed (e.g. in
- * {@link net.minecraft.tileentity.TileEntity#invalidate()}) or unloaded
- * (e.g. in {@link net.minecraft.tileentity.TileEntity#onChunkUnload()}).
+ * {@link net.minecraft.tileentity.TileEntity#setRemoved()}) or unloaded
+ * (e.g. in {@link net.minecraft.tileentity.TileEntity#onChunkUnloaded()}).
* Removing the node can lead to one or more new networks if it was the a
* bridge node, i.e. the only node connecting the resulting networks.
*
diff --git a/src/main/java/li/cil/oc/api/network/Packet.java b/src/main/java/li/cil/oc/api/network/Packet.java
index 233e720187..572cf606e6 100644
--- a/src/main/java/li/cil/oc/api/network/Packet.java
+++ b/src/main/java/li/cil/oc/api/network/Packet.java
@@ -1,6 +1,6 @@
package li.cil.oc.api.network;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* These packets represent messages sent using a network card or wireless
@@ -65,5 +65,5 @@ public interface Packet {
* Restore a packet saved like this using the factory method in the
* {@link li.cil.oc.api.Network} class.
*/
- void save(NBTTagCompound nbt);
+ void saveData(CompoundNBT nbt);
}
diff --git a/src/main/java/li/cil/oc/api/network/SidedComponent.java b/src/main/java/li/cil/oc/api/network/SidedComponent.java
index bc5eea0dd0..06c1ed13af 100644
--- a/src/main/java/li/cil/oc/api/network/SidedComponent.java
+++ b/src/main/java/li/cil/oc/api/network/SidedComponent.java
@@ -1,6 +1,6 @@
package li.cil.oc.api.network;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
/**
* This is an extended version of {@link li.cil.oc.api.network.SimpleComponent}
@@ -22,5 +22,5 @@ public interface SidedComponent {
* @param side the side to check for.
* @return whether the component may be connected to from the specified side.
*/
- boolean canConnectNode(EnumFacing side);
+ boolean canConnectNode(Direction side);
}
diff --git a/src/main/java/li/cil/oc/api/network/SidedEnvironment.java b/src/main/java/li/cil/oc/api/network/SidedEnvironment.java
index 1257100430..509e56ed54 100644
--- a/src/main/java/li/cil/oc/api/network/SidedEnvironment.java
+++ b/src/main/java/li/cil/oc/api/network/SidedEnvironment.java
@@ -1,9 +1,9 @@
package li.cil.oc.api.network;
import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.EnumFacing;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraft.util.Direction;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
/**
* This interface is like {@link net.minecraft.inventory.ISidedInventory} is to
@@ -32,7 +32,7 @@ public interface SidedEnvironment {
* @return the node for the specified side.
* @see li.cil.oc.api.network.Environment#node
*/
- Node sidedNode(EnumFacing side);
+ Node sidedNode(Direction side);
/**
* Whether the environment provides a node to connect to on the specified
@@ -50,6 +50,6 @@ public interface SidedEnvironment {
* @param side the side to check for.
* @return whether the environment provides a node for the specified side.
*/
- @SideOnly(Side.CLIENT)
- boolean canConnect(EnumFacing side);
+ @OnlyIn(Dist.CLIENT)
+ boolean canConnect(Direction side);
}
diff --git a/src/main/java/li/cil/oc/api/network/SimpleComponent.java b/src/main/java/li/cil/oc/api/network/SimpleComponent.java
deleted file mode 100644
index 7c5d10de3f..0000000000
--- a/src/main/java/li/cil/oc/api/network/SimpleComponent.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package li.cil.oc.api.network;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This interface can be used to easily convert tile entities to components,
- * without having to implement {@link li.cil.oc.api.network.Environment}
- * themselves. The simple implementation will provide no access to OC's internal
- * component network, since you won't have access to the node representing the
- * tile entity. Use this only for simple cases, where you want to expose a
- * couple of methods to the programs running computers.
- *
- * This is an interface instead of an annotation, to allow stripping via the
- * ever so handy {@link net.minecraftforge.fml.common.Optional} annotation,
- * meaning there will be no strong dependency on OpenComputers.
- *
- * Classes implementing this interface will be expanded with the methods
- * required for them to function as native block components (say, like the
- * screen or keyboard). This means functions in the Environment
- * interface have to created using a class transformer. If any of the methods
- * already exist, this will fail! If things don't work, check your logs, first.
- *
- * To expose methods to OC, tag them with {@link li.cil.oc.api.machine.Callback}
- * and have them use the according signature (see the documentation on the
- * Callback annotation).
- *
- * Alternatively, implement {@link li.cil.oc.api.network.ManagedPeripheral} in
- * addition to this interface, to make methods available ComputerCraft style.
- *
- * So, in short:
- *
- *
Implement this interface on a tile entity that should expose
- * methods to computers.
- *
Annotate methods with Callback so they exported.
- *
Alternatively/additionally implement ManagedPeripheral to
- * provide methods via a list of names and single callback method.
- */
-public interface SimpleComponent {
- /**
- * The name the component should be made available as.
- *
component.list() in Lua, for
- * example. You'll want to make this short and descriptive. The convention
- * for component names is: all lowercase, underscores where necessary. Good
- * component names are for example: disk_drive, furnace, crafting_table.
- *
- * @return the component's name.
- */
- String getComponentName();
-
- /**
- * Use this to skip logic injection for the class this is implemented by.
- *
- * For example, if you have a class transformer that injects logic from a
- * template class into your actual tile entities, OC's class transformer
- * would complain when it finds the interface on the template class. That
- * warning can be suppressed by using this annotation on the template.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- @interface SkipInjection {
- }
-}
diff --git a/src/main/java/li/cil/oc/api/network/package-info.java b/src/main/java/li/cil/oc/api/network/package-info.java
index 7fa496cdd0..6dbef6b188 100644
--- a/src/main/java/li/cil/oc/api/network/package-info.java
+++ b/src/main/java/li/cil/oc/api/network/package-info.java
@@ -4,10 +4,6 @@
* This mainly involves the (purely server-side!) network that is spanned over
* all of OpenComputers' components, including blocks and items alike.
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|network",
- apiVersion = API.VERSION)
package li.cil.oc.api.network;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/package-info.java b/src/main/java/li/cil/oc/api/package-info.java
index 502aa3781b..f9dae02d67 100644
--- a/src/main/java/li/cil/oc/api/package-info.java
+++ b/src/main/java/li/cil/oc/api/package-info.java
@@ -15,7 +15,7 @@
* Note that for tile entities you implement yourself, you will not have to
* provide a driver, as long as you implement the necessary interface:
* {@link li.cil.oc.api.network.Environment} and call {@link li.cil.oc.api.Network#joinOrCreateNetwork(net.minecraft.tileentity.TileEntity)}
- * in the first updateEntity() call. For items that should be installed
+ * in the first tick() call. For items that should be installed
* in a computer you will always have to provide a driver.
*
*
The {@link li.cil.oc.api.FileSystem} API
@@ -34,8 +34,4 @@
*
*
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|core",
- apiVersion = API.VERSION)
package li.cil.oc.api;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/api/prefab/AbstractBehavior.java b/src/main/java/li/cil/oc/api/prefab/AbstractBehavior.java
index ea1ad4bb9c..19429a0360 100644
--- a/src/main/java/li/cil/oc/api/prefab/AbstractBehavior.java
+++ b/src/main/java/li/cil/oc/api/prefab/AbstractBehavior.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.nanomachines.Behavior;
import li.cil.oc.api.nanomachines.DisableReason;
-import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.PlayerEntity;
/**
* Base class for behaviors, mostly useful to have less cluttered classes when
@@ -14,7 +14,7 @@ public abstract class AbstractBehavior implements Behavior {
/**
* The player this behavior was created for.
*/
- public final EntityPlayer player;
+ public final PlayerEntity player;
/**
* Pass along the player the behavior was created for here to have it stored
@@ -22,7 +22,7 @@ public abstract class AbstractBehavior implements Behavior {
*
* @param player the player the behavior was created for.
*/
- protected AbstractBehavior(EntityPlayer player) {
+ protected AbstractBehavior(PlayerEntity player) {
this.player = player;
}
diff --git a/src/main/java/li/cil/oc/api/prefab/AbstractManagedEnvironment.java b/src/main/java/li/cil/oc/api/prefab/AbstractManagedEnvironment.java
index cb6c39145e..010668196b 100644
--- a/src/main/java/li/cil/oc/api/prefab/AbstractManagedEnvironment.java
+++ b/src/main/java/li/cil/oc/api/prefab/AbstractManagedEnvironment.java
@@ -3,7 +3,7 @@
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.api.network.Message;
import li.cil.oc.api.network.Node;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* Simple base implementation of the ManagedEnvironment interface, so
@@ -46,14 +46,14 @@ public void onMessage(final Message message) {
}
@Override
- public void load(final NBTTagCompound nbt) {
+ public void loadData(final CompoundNBT nbt) {
if (node() != null) {
- node().load(nbt.getCompoundTag(NODE_TAG));
+ node().loadData(nbt.getCompound(NODE_TAG));
}
}
@Override
- public void save(final NBTTagCompound nbt) {
+ public void saveData(final CompoundNBT nbt) {
if (node() != null) {
// Force joining a network when saving and we're not in one yet, so that
// the address is embedded in the saved data that gets sent to the client,
@@ -62,15 +62,15 @@ public void save(final NBTTagCompound nbt) {
if (node().address() == null) {
li.cil.oc.api.Network.joinNewNetwork(node());
- final NBTTagCompound nodeTag = new NBTTagCompound();
- node().save(nodeTag);
- nbt.setTag(NODE_TAG, nodeTag);
+ final CompoundNBT nodeTag = new CompoundNBT();
+ node().saveData(nodeTag);
+ nbt.put(NODE_TAG, nodeTag);
node().remove();
} else {
- final NBTTagCompound nodeTag = new NBTTagCompound();
- node().save(nodeTag);
- nbt.setTag(NODE_TAG, nodeTag);
+ final CompoundNBT nodeTag = new CompoundNBT();
+ node().saveData(nodeTag);
+ nbt.put(NODE_TAG, nodeTag);
}
}
}
diff --git a/src/main/java/li/cil/oc/api/prefab/AbstractProvider.java b/src/main/java/li/cil/oc/api/prefab/AbstractProvider.java
index 9f03938353..58ca1b8597 100644
--- a/src/main/java/li/cil/oc/api/prefab/AbstractProvider.java
+++ b/src/main/java/li/cil/oc/api/prefab/AbstractProvider.java
@@ -2,8 +2,8 @@
import li.cil.oc.api.nanomachines.Behavior;
import li.cil.oc.api.nanomachines.BehaviorProvider;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.nbt.CompoundNBT;
/**
* Example base implementation of nanomachine behavior provider.
@@ -38,7 +38,7 @@ protected AbstractProvider(String id) {
* @param behavior the behavior to persist.
* @param nbt the NBT tag to persist it to.
*/
- protected void writeBehaviorToNBT(Behavior behavior, NBTTagCompound nbt) {
+ protected void writeBehaviorToNBT(Behavior behavior, CompoundNBT nbt) {
}
/**
@@ -51,20 +51,20 @@ protected void writeBehaviorToNBT(Behavior behavior, NBTTagCompound nbt) {
* @param nbt the NBT tag to load restore the behavior from.
* @return the restored behavior.
*/
- protected abstract Behavior readBehaviorFromNBT(EntityPlayer player, NBTTagCompound nbt);
+ protected abstract Behavior readBehaviorFromNBT(PlayerEntity player, CompoundNBT nbt);
// ----------------------------------------------------------------------- //
@Override
- public NBTTagCompound writeToNBT(Behavior behavior) {
- NBTTagCompound nbt = new NBTTagCompound();
- nbt.setString("provider", id);
+ public CompoundNBT save(Behavior behavior) {
+ CompoundNBT nbt = new CompoundNBT();
+ nbt.putString("provider", id);
writeBehaviorToNBT(behavior, nbt);
return nbt;
}
@Override
- public Behavior readFromNBT(EntityPlayer player, NBTTagCompound nbt) {
+ public Behavior load(PlayerEntity player, CompoundNBT nbt) {
if (id.equals(nbt.getString("provider"))) {
return readBehaviorFromNBT(player, nbt);
} else {
diff --git a/src/main/java/li/cil/oc/api/prefab/AbstractValue.java b/src/main/java/li/cil/oc/api/prefab/AbstractValue.java
index 7d686b5df6..d0c8261808 100644
--- a/src/main/java/li/cil/oc/api/prefab/AbstractValue.java
+++ b/src/main/java/li/cil/oc/api/prefab/AbstractValue.java
@@ -3,7 +3,7 @@
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Context;
import li.cil.oc.api.machine.Value;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* Basic implementation for the Value interface.
@@ -28,10 +28,10 @@ public void dispose(Context context) {
}
@Override
- public void load(NBTTagCompound nbt) {
+ public void loadData(CompoundNBT nbt) {
}
@Override
- public void save(NBTTagCompound nbt) {
+ public void saveData(CompoundNBT nbt) {
}
}
diff --git a/src/main/java/li/cil/oc/api/prefab/DriverItem.java b/src/main/java/li/cil/oc/api/prefab/DriverItem.java
index e44e4b7797..c111035ec9 100644
--- a/src/main/java/li/cil/oc/api/prefab/DriverItem.java
+++ b/src/main/java/li/cil/oc/api/prefab/DriverItem.java
@@ -2,7 +2,7 @@
import li.cil.oc.api.network.EnvironmentHost;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.CompoundNBT;
/**
* If you wish to create item components such as the network card or hard drives
@@ -30,7 +30,7 @@ protected DriverItem(final ItemStack... items) {
public boolean worksWith(final ItemStack stack) {
if (!stack.isEmpty()) {
for (ItemStack item : items) {
- if (!item.isEmpty() && item.isItemEqual(stack)) {
+ if (!item.isEmpty() && item.sameItem(stack)) {
return true;
}
}
@@ -44,17 +44,14 @@ public int tier(final ItemStack stack) {
}
@Override
- public NBTTagCompound dataTag(final ItemStack stack) {
- if (!stack.hasTagCompound()) {
- stack.setTagCompound(new NBTTagCompound());
- }
- final NBTTagCompound nbt = stack.getTagCompound();
+ public CompoundNBT dataTag(final ItemStack stack) {
+ final CompoundNBT nbt = stack.getOrCreateTag();
// This is the suggested key under which to store item component data.
// You are free to change this as you please.
- if (!nbt.hasKey("oc:data")) {
- nbt.setTag("oc:data", new NBTTagCompound());
+ if (!nbt.contains("oc:data")) {
+ nbt.put("oc:data", new CompoundNBT());
}
- return nbt.getCompoundTag("oc:data");
+ return nbt.getCompound("oc:data");
}
// Convenience methods provided for HostAware drivers.
diff --git a/src/main/java/li/cil/oc/api/prefab/DriverSidedBlock.java b/src/main/java/li/cil/oc/api/prefab/DriverSidedBlock.java
index 40ca7f1931..079d372630 100644
--- a/src/main/java/li/cil/oc/api/prefab/DriverSidedBlock.java
+++ b/src/main/java/li/cil/oc/api/prefab/DriverSidedBlock.java
@@ -1,14 +1,10 @@
package li.cil.oc.api.prefab;
import li.cil.oc.api.driver.DriverBlock;
-import net.minecraft.block.Block;
-import net.minecraft.block.state.IBlockState;
-import net.minecraft.item.ItemBlock;
-import net.minecraft.item.ItemStack;
+import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
import net.minecraft.world.World;
-import net.minecraftforge.oredict.OreDictionary;
/**
* If you wish to create a block component for a third-party block, i.e. a block
@@ -22,36 +18,24 @@
* You still have to provide the implementation for creating its environment, if
* any.
*
- * To limit sidedness, I recommend overriding {@link #worksWith(World, BlockPos, EnumFacing)}
+ * To limit sidedness, I recommend overriding {@link #worksWith(World, BlockPos, Direction)}
* and calling super.worksWith in addition to the side check.
*
* @see li.cil.oc.api.network.ManagedEnvironment
*/
@SuppressWarnings("UnusedDeclaration")
public abstract class DriverSidedBlock implements DriverBlock {
- protected final ItemStack[] blocks;
+ protected final BlockState[] blocks;
- protected DriverSidedBlock(final ItemStack... blocks) {
+ protected DriverSidedBlock(final BlockState... blocks) {
this.blocks = blocks.clone();
}
@Override
- public boolean worksWith(final World world, final BlockPos pos, final EnumFacing side) {
- final IBlockState state = world.getBlockState(pos);
- final Block block = state.getBlock();
- return worksWith(block, block.getMetaFromState(state));
- }
-
- protected boolean worksWith(final Block referenceBlock, final int referenceMetadata) {
- for (ItemStack stack : blocks) {
- if (!stack.isEmpty() && stack.getItem() instanceof ItemBlock) {
- final ItemBlock item = (ItemBlock) stack.getItem();
- final Block supportedBlock = item.getBlock();
- final int supportedMetadata = item.getMetadata(stack.getItemDamage());
- if (referenceBlock == supportedBlock && (referenceMetadata == supportedMetadata || stack.getItemDamage() == OreDictionary.WILDCARD_VALUE)) {
- return true;
- }
- }
+ public boolean worksWith(final World world, final BlockPos pos, final Direction side) {
+ final BlockState state = world.getBlockState(pos);
+ for (BlockState block : blocks) {
+ if (block == state) return true;
}
return false;
}
diff --git a/src/main/java/li/cil/oc/api/prefab/DriverSidedTileEntity.java b/src/main/java/li/cil/oc/api/prefab/DriverSidedTileEntity.java
index e17b3b0d86..9c40c7183a 100644
--- a/src/main/java/li/cil/oc/api/prefab/DriverSidedTileEntity.java
+++ b/src/main/java/li/cil/oc/api/prefab/DriverSidedTileEntity.java
@@ -3,25 +3,25 @@
import li.cil.oc.api.driver.DriverBlock;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.EnumFacing;
+import net.minecraft.util.Direction;
import net.minecraft.world.World;
/**
- * To limit sidedness, I recommend overriding {@link #worksWith(World, BlockPos, EnumFacing)}
+ * To limit sidedness, I recommend overriding {@link #worksWith(World, BlockPos, Direction)}
* and calling super.worksWith in addition to the side check.
*/
public abstract class DriverSidedTileEntity implements DriverBlock {
public abstract Class> getTileEntityClass();
@Override
- public boolean worksWith(final World world, final BlockPos pos, final EnumFacing side) {
+ public boolean worksWith(final World world, final BlockPos pos, final Direction side) {
final Class> filter = getTileEntityClass();
if (filter == null) {
// This can happen if filter classes are deduced by reflection and
// the class in question is not present.
return false;
}
- final TileEntity tileEntity = world.getTileEntity(pos);
+ final TileEntity tileEntity = world.getBlockEntity(pos);
return tileEntity != null && filter.isAssignableFrom(tileEntity.getClass());
}
}
diff --git a/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java b/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java
index 883cc40b3c..e916a3d38f 100644
--- a/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java
+++ b/src/main/java/li/cil/oc/api/prefab/ItemStackArrayValue.java
@@ -4,9 +4,8 @@
import li.cil.oc.api.machine.Callback;
import li.cil.oc.api.machine.Context;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTBase;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.CompoundNBT;
+import net.minecraft.nbt.ListNBT;
import java.util.HashMap;
import java.util.TreeMap;
@@ -16,8 +15,8 @@ public class ItemStackArrayValue extends AbstractValue {
private ItemStack[] array = null;
private int iteratorIndex;
- private static final byte TAGLIST_ID = (new NBTTagList()).getId();
- private static final byte COMPOUND_ID = (new NBTTagCompound()).getId();
+ private static final byte TAGLIST_ID = (new ListNBT()).getId();
+ private static final byte COMPOUND_ID = (new CompoundNBT()).getId();
private static final String ARRAY_KEY = "Array";
private static final String INDEX_KEY = "Index";
@@ -70,43 +69,42 @@ public Object apply(Context context, Arguments arguments) {
}
@Override
- public void load(NBTTagCompound nbt) {
- if (nbt.hasKey(ARRAY_KEY, TAGLIST_ID)){
- NBTTagList tagList = nbt.getTagList(ARRAY_KEY,COMPOUND_ID);
- this.array = new ItemStack[tagList.tagCount()];
- for (int i = 0; i < tagList.tagCount(); ++i){
- NBTTagCompound el = tagList.getCompoundTagAt(i);
- if (el.hasNoTags())
+ public void loadData(CompoundNBT nbt) {
+ if (nbt.contains(ARRAY_KEY, TAGLIST_ID)){
+ ListNBT tagList = nbt.getList(ARRAY_KEY,COMPOUND_ID);
+ this.array = new ItemStack[tagList.size()];
+ for (int i = 0; i < tagList.size(); ++i){
+ CompoundNBT el = tagList.getCompound(i);
+ if (el.isEmpty())
this.array[i] = ItemStack.EMPTY;
else
- this.array[i] = new ItemStack(el);
+ this.array[i] = ItemStack.of(el);
}
} else {
this.array = null;
}
- this.iteratorIndex = nbt.getInteger(INDEX_KEY);
+ this.iteratorIndex = nbt.getInt(INDEX_KEY);
}
@Override
- public void save(NBTTagCompound nbt) {
+ public void saveData(CompoundNBT nbt) {
- NBTTagCompound nullnbt = new NBTTagCompound();
+ CompoundNBT nullnbt = new CompoundNBT();
if (this.array != null) {
- NBTTagList nbttaglist = new NBTTagList();
+ ListNBT nbttaglist = new ListNBT();
for (ItemStack stack : this.array) {
if (stack != null) {
- NBTBase nbttagcompound = stack.serializeNBT();
- nbttaglist.appendTag(nbttagcompound);
+ nbttaglist.add(stack.save(new CompoundNBT()));
} else {
- nbttaglist.appendTag(nullnbt);
+ nbttaglist.add(nullnbt);
}
}
- nbt.setTag(ARRAY_KEY, nbttaglist);
+ nbt.put(ARRAY_KEY, nbttaglist);
}
- nbt.setInteger(INDEX_KEY, iteratorIndex);
+ nbt.putInt(INDEX_KEY, iteratorIndex);
}
@Callback(doc="function():nil -- Reset the iterator index so that the next call will return the first element.")
diff --git a/src/main/java/li/cil/oc/api/prefab/ItemStackTabIconRenderer.java b/src/main/java/li/cil/oc/api/prefab/ItemStackTabIconRenderer.java
index 5c42ff2142..2267a68968 100644
--- a/src/main/java/li/cil/oc/api/prefab/ItemStackTabIconRenderer.java
+++ b/src/main/java/li/cil/oc/api/prefab/ItemStackTabIconRenderer.java
@@ -1,13 +1,13 @@
package li.cil.oc.api.prefab;
+import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.systems.RenderSystem;
import li.cil.oc.api.manual.TabIconRenderer;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.OpenGlHelper;
-import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.item.ItemStack;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
+import org.lwjgl.opengl.GL13;
/**
* Simple implementation of a tab icon renderer using an item stack as its graphic.
@@ -20,13 +20,15 @@ public ItemStackTabIconRenderer(ItemStack stack) {
this.stack = stack;
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
@Override
- public void render() {
- GlStateManager.enableRescaleNormal();
- RenderHelper.enableGUIStandardItemLighting();
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
- Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, 0, 0);
- RenderHelper.disableStandardItemLighting();
+ public void render(MatrixStack matrix) {
+ // Translate manually because ItemRenderer generally can't take a MatrixStack.
+ RenderSystem.pushMatrix();
+ RenderSystem.multMatrix(matrix.last().pose());
+ RenderSystem.enableRescaleNormal();
+ RenderSystem.glMultiTexCoord2f(GL13.GL_TEXTURE1, 240, 240);
+ Minecraft.getInstance().getItemRenderer().renderAndDecorateItem(stack, 0, 0);
+ RenderSystem.popMatrix();
}
}
diff --git a/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java b/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java
index 44d5efe680..2113b8f4fb 100644
--- a/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java
+++ b/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java
@@ -40,10 +40,11 @@ public ResourceContentProvider(String resourceDomain) {
@Override
public Iterable getContent(String path) {
- final ResourceLocation location = new ResourceLocation(resourceDomain, basePath + (path.startsWith("/") ? path.substring(1) : path));
+ final String resourcePath = basePath + (path.startsWith("/") ? path.substring(1) : path);
+ final ResourceLocation location = new ResourceLocation(resourceDomain, resourcePath.toLowerCase());
InputStream is = null;
try {
- is = Minecraft.getMinecraft().getResourceManager().getResource(location).getInputStream();
+ is = Minecraft.getInstance().getResourceManager().getResource(location).getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charsets.UTF_8));
final ArrayList lines = new ArrayList();
String line;
diff --git a/src/main/java/li/cil/oc/api/prefab/TextureTabIconRenderer.java b/src/main/java/li/cil/oc/api/prefab/TextureTabIconRenderer.java
index 3b7f45eff4..db63f084c8 100644
--- a/src/main/java/li/cil/oc/api/prefab/TextureTabIconRenderer.java
+++ b/src/main/java/li/cil/oc/api/prefab/TextureTabIconRenderer.java
@@ -1,14 +1,15 @@
package li.cil.oc.api.prefab;
+import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.systems.RenderSystem;
import li.cil.oc.api.manual.TabIconRenderer;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.opengl.GL11;
/**
@@ -23,17 +24,16 @@ public TextureTabIconRenderer(ResourceLocation location) {
}
@Override
- @SideOnly(Side.CLIENT)
- public void render() {
- Minecraft.getMinecraft().getTextureManager().bindTexture(location);
- GlStateManager.bindTexture(Minecraft.getMinecraft().getTextureManager().getTexture(location).getGlTextureId());
+ @OnlyIn(Dist.CLIENT)
+ public void render(MatrixStack stack) {
+ Minecraft.getInstance().getTextureManager().bind(location);
final Tessellator t = Tessellator.getInstance();
- final BufferBuilder r = t.getBuffer();
+ final BufferBuilder r = t.getBuilder();
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
- r.pos(0, 16, 0).tex(0, 1).endVertex();
- r.pos(16, 16, 0).tex(1, 1).endVertex();
- r.pos(16, 0, 0).tex(1, 0).endVertex();
- r.pos(0, 0, 0).tex(0, 0).endVertex();
- t.draw();
+ r.vertex(stack.last().pose(), 0, 16, 0).uv(0, 1).endVertex();
+ r.vertex(stack.last().pose(), 16, 16, 0).uv(1, 1).endVertex();
+ r.vertex(stack.last().pose(), 16, 0, 0).uv(1, 0).endVertex();
+ r.vertex(stack.last().pose(), 0, 0, 0).uv(0, 0).endVertex();
+ t.end();
}
}
diff --git a/src/main/java/li/cil/oc/api/prefab/TileEntityEnvironment.java b/src/main/java/li/cil/oc/api/prefab/TileEntityEnvironment.java
index 010fd82423..ac1a15ad31 100644
--- a/src/main/java/li/cil/oc/api/prefab/TileEntityEnvironment.java
+++ b/src/main/java/li/cil/oc/api/prefab/TileEntityEnvironment.java
@@ -5,8 +5,10 @@
import li.cil.oc.api.network.Message;
import li.cil.oc.api.network.Node;
import li.cil.oc.api.network.Visibility;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.block.BlockState;
+import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
+import net.minecraft.tileentity.TileEntityType;
/**
* TileEntities can implement the {@link li.cil.oc.api.network.Environment}
@@ -58,6 +60,10 @@ public abstract class TileEntityEnvironment extends TileEntity implements Enviro
protected Node node;
// ----------------------------------------------------------------------- //
+
+ public TileEntityEnvironment(TileEntityType> type) {
+ super(type);
+ }
@Override
public Node node() {
@@ -67,7 +73,7 @@ public Node node() {
@Override
public void onConnect(final Node node) {
// This is called when the call to Network.joinOrCreateNetwork(this) in
- // updateEntity was successful, in which case `node == this`.
+ // tick was successful, in which case `node == this`.
// This is also called for any other node that gets connected to the
// network our node is in, in which case `node` is the added node.
// If our node is added to an existing network, this is called for each
@@ -77,8 +83,8 @@ public void onConnect(final Node node) {
@Override
public void onDisconnect(final Node node) {
// This is called when this node is removed from its network when the
- // tile entity is removed from the world (see onChunkUnload() and
- // invalidate()), in which case `node == this`.
+ // tile entity is removed from the world (see onChunkUnloaded() and
+ // setRemoved()), in which case `node == this`.
// This is also called for each other node that gets removed from the
// network our node is in, in which case `node` is the removed node.
// If a net-split occurs this is called for each node that is no longer
@@ -100,16 +106,16 @@ public void onLoad() {
}
@Override
- public void onChunkUnload() {
- super.onChunkUnload();
+ public void onChunkUnloaded() {
+ super.onChunkUnloaded();
// Make sure to remove the node from its network when its environment,
// meaning this tile entity, gets unloaded.
if (node != null) node.remove();
}
@Override
- public void invalidate() {
- super.invalidate();
+ public void setRemoved() {
+ super.setRemoved();
// Make sure to remove the node from its network when its environment,
// meaning this tile entity, gets unloaded.
if (node != null) node.remove();
@@ -118,8 +124,8 @@ public void invalidate() {
// ----------------------------------------------------------------------- //
@Override
- public void readFromNBT(final NBTTagCompound nbt) {
- super.readFromNBT(nbt);
+ public void load(final BlockState state, final CompoundNBT nbt) {
+ super.load(state, nbt);
// The host check may be superfluous for you. It's just there to allow
// some special cases, where getNode() returns some node managed by
// some other instance (for example when you have multiple internal
@@ -129,18 +135,18 @@ public void readFromNBT(final NBTTagCompound nbt) {
// to continue working without interruption across loads. If the
// node is a power connector this is also required to restore the
// internal energy buffer of the node.
- node.load(nbt.getCompoundTag(TAG_NODE));
+ node.loadData(nbt.getCompound(TAG_NODE));
}
}
@Override
- public NBTTagCompound writeToNBT(final NBTTagCompound nbt) {
- super.writeToNBT(nbt);
- // See readFromNBT() regarding host check.
+ public CompoundNBT save(final CompoundNBT nbt) {
+ super.save(nbt);
+ // See load() regarding host check.
if (node != null && node.host() == this) {
- final NBTTagCompound nodeNbt = new NBTTagCompound();
- node.save(nodeNbt);
- nbt.setTag(TAG_NODE, nodeNbt);
+ final CompoundNBT nodeNbt = new CompoundNBT();
+ node.saveData(nodeNbt);
+ nbt.put(TAG_NODE, nodeNbt);
}
return nbt;
}
diff --git a/src/main/java/li/cil/oc/api/prefab/TileEntitySidedEnvironment.java b/src/main/java/li/cil/oc/api/prefab/TileEntitySidedEnvironment.java
index c3d878d9ed..953685a04f 100644
--- a/src/main/java/li/cil/oc/api/prefab/TileEntitySidedEnvironment.java
+++ b/src/main/java/li/cil/oc/api/prefab/TileEntitySidedEnvironment.java
@@ -3,10 +3,12 @@
import li.cil.oc.api.Network;
import li.cil.oc.api.network.Node;
import li.cil.oc.api.network.SidedEnvironment;
-import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.block.BlockState;
+import net.minecraft.nbt.CompoundNBT;
+import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.EnumFacing;
-import net.minecraft.util.ITickable;
+import net.minecraft.tileentity.TileEntityType;
+import net.minecraft.util.Direction;
/**
* TileEntities can implement the {@link li.cil.oc.api.network.SidedEnvironment}
@@ -19,11 +21,11 @@
* network as an index structure to find other nodes connected to them.
*/
@SuppressWarnings("UnusedDeclaration")
-public abstract class TileEntitySidedEnvironment extends TileEntity implements SidedEnvironment, ITickable {
+public abstract class TileEntitySidedEnvironment extends TileEntity implements SidedEnvironment, ITickableTileEntity {
// See constructor.
protected Node[] nodes = new Node[6];
- // See updateEntity().
+ // See tick().
protected boolean addedToNetwork = false;
/**
@@ -60,7 +62,8 @@ public abstract class TileEntitySidedEnvironment extends TileEntity implements S
* .create(), ...);
*
*/
- protected TileEntitySidedEnvironment(final Node... nodes) {
+ protected TileEntitySidedEnvironment(TileEntityType> type, final Node... nodes) {
+ super(type);
System.arraycopy(nodes, 0, this.nodes, 0, Math.min(nodes.length, this.nodes.length));
}
@@ -72,17 +75,17 @@ protected TileEntitySidedEnvironment(final Node... nodes) {
// exists for a side won't work on the client.
@Override
- public Node sidedNode(final EnumFacing side) {
+ public Node sidedNode(final Direction side) {
return nodes[side.ordinal()];
}
// ----------------------------------------------------------------------- //
@Override
- public void update() {
+ public void tick() {
// On the first update, try to add our node to nearby networks. We do
- // this in the update logic, not in validate() because we need to access
- // neighboring tile entities, which isn't possible in validate().
+ // this in the update logic, not in clearRemoved() because we need to access
+ // neighboring tile entities, which isn't possible in clearRemoved().
// We could alternatively check node != null && node.network() == null,
// but this has somewhat better performance, and makes it clearer.
if (!addedToNetwork) {
@@ -94,8 +97,8 @@ public void update() {
}
@Override
- public void onChunkUnload() {
- super.onChunkUnload();
+ public void onChunkUnloaded() {
+ super.onChunkUnloaded();
// Make sure to remove the node from its network when its environment,
// meaning this tile entity, gets unloaded.
for (Node node : nodes) {
@@ -104,8 +107,8 @@ public void onChunkUnload() {
}
@Override
- public void invalidate() {
- super.invalidate();
+ public void setRemoved() {
+ super.setRemoved();
// Make sure to remove the node from its network when its environment,
// meaning this tile entity, gets unloaded.
for (Node node : nodes) {
@@ -116,8 +119,8 @@ public void invalidate() {
// ----------------------------------------------------------------------- //
@Override
- public void readFromNBT(final NBTTagCompound nbt) {
- super.readFromNBT(nbt);
+ public void load(final BlockState state, final CompoundNBT nbt) {
+ super.load(state, nbt);
int index = 0;
for (Node node : nodes) {
// The host check may be superfluous for you. It's just there to allow
@@ -129,22 +132,22 @@ public void readFromNBT(final NBTTagCompound nbt) {
// to continue working without interruption across loads. If the
// node is a power connector this is also required to restore the
// internal energy buffer of the node.
- node.load(nbt.getCompoundTag("oc:node" + index));
+ node.loadData(nbt.getCompound("oc:node" + index));
}
++index;
}
}
@Override
- public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
- super.writeToNBT(nbt);
+ public CompoundNBT save(CompoundNBT nbt) {
+ super.save(nbt);
int index = 0;
for (Node node : nodes) {
- // See readFromNBT() regarding host check.
+ // See load() regarding host check.
if (node != null && node.host() == this) {
- final NBTTagCompound nodeNbt = new NBTTagCompound();
- node.save(nodeNbt);
- nbt.setTag("oc:node" + index, nodeNbt);
+ final CompoundNBT nodeNbt = new CompoundNBT();
+ node.saveData(nodeNbt);
+ nbt.put("oc:node" + index, nodeNbt);
}
++index;
}
diff --git a/src/main/java/li/cil/oc/api/prefab/package-info.java b/src/main/java/li/cil/oc/api/prefab/package-info.java
index a28cc87fba..8fb8970f61 100644
--- a/src/main/java/li/cil/oc/api/prefab/package-info.java
+++ b/src/main/java/li/cil/oc/api/prefab/package-info.java
@@ -7,10 +7,6 @@
* while leaving them in the same package with the same name and then ship them
* with your mod!
*/
-@net.minecraftforge.fml.common.API(
- owner = API.ID_OWNER,
- provides = "opencomputersapi|prefab",
- apiVersion = API.VERSION)
package li.cil.oc.api.prefab;
import li.cil.oc.api.API;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/common/asm/SimpleComponentTickHandler.java b/src/main/java/li/cil/oc/common/asm/SimpleComponentTickHandler.java
deleted file mode 100644
index 1bfca877f6..0000000000
--- a/src/main/java/li/cil/oc/common/asm/SimpleComponentTickHandler.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package li.cil.oc.common.asm;
-
-import li.cil.oc.api.Network;
-import li.cil.oc.util.SideTracker;
-import net.minecraft.tileentity.TileEntity;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.util.ArrayList;
-
-// This class is used for adding simple components to the component network.
-// It is triggered from a validate call, and executed in the next update tick.
-public final class SimpleComponentTickHandler {
- private static final Logger log = LogManager.getLogger("OpenComputers");
-
- public static final ArrayList pending = new java.util.ArrayList();
-
- public static final SimpleComponentTickHandler Instance = new SimpleComponentTickHandler();
-
- private SimpleComponentTickHandler() {
- }
-
- public static void schedule(final TileEntity tileEntity) {
- if (SideTracker.isServer()) {
- synchronized (pending) {
- pending.add(new Runnable() {
- @Override
- public void run() {
- Network.joinOrCreateNetwork(tileEntity);
- }
- });
- }
- }
- }
-
- @SubscribeEvent
- public void onTick(TickEvent.ServerTickEvent e) {
- if (e.phase == TickEvent.Phase.START) {
- final Runnable[] adds;
- synchronized (pending) {
- adds = pending.toArray(new Runnable[pending.size()]);
- pending.clear();
- }
- for (Runnable runnable : adds) {
- try {
- runnable.run();
- } catch (Throwable t) {
- log.warn("Error in scheduled tick action.", t);
- }
- }
- }
- }
-}
diff --git a/src/main/java/li/cil/oc/common/asm/template/SimpleComponentImpl.java b/src/main/java/li/cil/oc/common/asm/template/SimpleComponentImpl.java
deleted file mode 100644
index a73aa62056..0000000000
--- a/src/main/java/li/cil/oc/common/asm/template/SimpleComponentImpl.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package li.cil.oc.common.asm.template;
-
-import li.cil.oc.api.network.Environment;
-import li.cil.oc.api.network.SimpleComponent;
-import net.minecraft.nbt.NBTTagCompound;
-
-/**
- * This interface defines the names to which existing or placeholders for
- * existing methods will be moved. This allows transparent injection of our
- * functionality, i.e. existing validate() etc. methods will be called as
- * if we didn't inject our code.
- *
- * Yes, the names are not "conventional", but that is by design, to avoid
- * naming collisions.
- */
-public interface SimpleComponentImpl extends Environment, SimpleComponent {
- public static final String PostFix = "_OpenComputers";
-
- void validate_OpenComputers();
-
- void invalidate_OpenComputers();
-
- void onChunkUnload_OpenComputers();
-
- void readFromNBT_OpenComputers(NBTTagCompound nbt);
-
- NBTTagCompound writeToNBT_OpenComputers(NBTTagCompound nbt);
-}
diff --git a/src/main/java/li/cil/oc/common/asm/template/SimpleEnvironment.java b/src/main/java/li/cil/oc/common/asm/template/SimpleEnvironment.java
deleted file mode 100644
index c866b4bc48..0000000000
--- a/src/main/java/li/cil/oc/common/asm/template/SimpleEnvironment.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package li.cil.oc.common.asm.template;
-
-import li.cil.oc.api.network.Message;
-import li.cil.oc.api.network.Node;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.tileentity.TileEntity;
-
-// This is a template implementation of methods injected into classes that are
-// marked for component functionality. These methods will be copied into tile
-// entities marked as simple components as necessary by the class transformer.
-@SuppressWarnings("unused")
-public abstract class SimpleEnvironment extends TileEntity implements SimpleComponentImpl {
- @Override
- public Node node() {
- return StaticSimpleEnvironment.node(this);
- }
-
- @Override
- public void onConnect(Node node) {
- }
-
- @Override
- public void onDisconnect(Node node) {
- }
-
- @Override
- public void onMessage(Message message) {
- }
-
- // These are always injected, after possibly existing versions have been
- // renamed to the below variants from the SimpleComponentImpl interface.
- // This allows transparent wrapping of already present implementations,
- // instead of plain overwriting them.
-
- @Override
- public void validate() {
- StaticSimpleEnvironment.validate(this);
- }
-
- @Override
- public void invalidate() {
- StaticSimpleEnvironment.invalidate(this);
- }
-
- @Override
- public void onChunkUnload() {
- StaticSimpleEnvironment.onChunkUnload(this);
- }
-
- @Override
- public void readFromNBT(NBTTagCompound nbt) {
- StaticSimpleEnvironment.readFromNBT(this, nbt);
- }
-
- @Override
- public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
- return StaticSimpleEnvironment.writeToNBT(this, nbt);
- }
-
- // The following methods are only injected if their real versions do not
- // exist in the class we're injecting into. Otherwise their real versions
- // are renamed to these variations, which simply delegate to the parent.
- // This way they are always guaranteed to be present, so we can simply call
- // them through an interface, and need no runtime reflection.
-
- public void validate_OpenComputers() {
- super.validate();
- }
-
- public void invalidate_OpenComputers() {
- super.invalidate();
- }
-
- public void onChunkUnload_OpenComputers() {
- super.onChunkUnload();
- }
-
- public void readFromNBT_OpenComputers(NBTTagCompound nbt) {
- super.readFromNBT(nbt);
- }
-
- public NBTTagCompound writeToNBT_OpenComputers(NBTTagCompound nbt) {
- return super.writeToNBT(nbt);
- }
-}
diff --git a/src/main/java/li/cil/oc/common/asm/template/StaticSimpleEnvironment.java b/src/main/java/li/cil/oc/common/asm/template/StaticSimpleEnvironment.java
deleted file mode 100644
index 82d2b81d82..0000000000
--- a/src/main/java/li/cil/oc/common/asm/template/StaticSimpleEnvironment.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package li.cil.oc.common.asm.template;
-
-import com.google.common.base.Strings;
-import li.cil.oc.api.Network;
-import li.cil.oc.api.network.Environment;
-import li.cil.oc.api.network.Node;
-import li.cil.oc.api.network.Visibility;
-import li.cil.oc.common.asm.SimpleComponentTickHandler;
-import li.cil.oc.util.SideTracker;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.tileentity.TileEntity;
-
-import java.util.HashMap;
-import java.util.Map;
-
-// This class contains actual implementations of methods injected into tile
-// entities marked as simple components using the SimpleComponent interface.
-// They are called from the template methods, to keep the injected methods
-// minimal, instruction wise, and avoid weird dependencies making the injection
-// unnecessarily complicated.
-public final class StaticSimpleEnvironment {
- private StaticSimpleEnvironment() {
- }
-
- private static final Map nodes = new HashMap();
-
- public static Node node(final SimpleComponentImpl self) {
- // Save ourselves the lookup time in the hash map and avoid mixing in
- // client side tile entities into the map when in single player.
- if (SideTracker.isClient()) {
- return null;
- }
- final String name = self.getComponentName();
- // If the name is null (or empty) this indicates we don't have a valid
- // component right now, so if we have a node we kill it.
- if (Strings.isNullOrEmpty(name)) {
- final Node node = nodes.remove(self);
- if (node != null) {
- node.remove();
- }
- } else if (!nodes.containsKey(self)) {
- nodes.put(self, Network.
- newNode(self, Visibility.Network).
- withComponent(name).
- create());
- }
- return nodes.get(self);
- }
-
- public static void validate(final SimpleComponentImpl self) {
- self.validate_OpenComputers();
- SimpleComponentTickHandler.schedule((TileEntity) self);
- }
-
- public static void invalidate(final SimpleComponentImpl self) {
- self.invalidate_OpenComputers();
- final Node node = node(self);
- if (node != null) {
- node.remove();
- nodes.remove(self);
- }
- }
-
- public static void onChunkUnload(final SimpleComponentImpl self) {
- self.onChunkUnload_OpenComputers();
- final Node node = node(self);
- if (node != null) {
- node.remove();
- nodes.remove(self);
- }
- }
-
- public static void readFromNBT(final SimpleComponentImpl self, NBTTagCompound nbt) {
- self.readFromNBT_OpenComputers(nbt);
- final Node node = node(self);
- if (node != null) {
- node.load(nbt.getCompoundTag("oc:node"));
- }
- }
-
- public static NBTTagCompound writeToNBT(final SimpleComponentImpl self, NBTTagCompound nbt) {
- nbt = self.writeToNBT_OpenComputers(nbt);
- final Node node = node(self);
- if (node != null) {
- final NBTTagCompound nodeNbt = new NBTTagCompound();
- node.save(nodeNbt);
- nbt.setTag("oc:node", nodeNbt);
- }
- return nbt;
- }
-}
diff --git a/src/main/java/li/cil/oc/integration/charset/CapabilitiesCharset.java b/src/main/java/li/cil/oc/integration/charset/CapabilitiesCharset.java
deleted file mode 100644
index 32be1c7df9..0000000000
--- a/src/main/java/li/cil/oc/integration/charset/CapabilitiesCharset.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package li.cil.oc.integration.charset;
-
-import net.minecraftforge.common.capabilities.Capability;
-import net.minecraftforge.common.capabilities.CapabilityInject;
-import pl.asie.charset.api.wires.IBundledEmitter;
-import pl.asie.charset.api.wires.IBundledReceiver;
-import pl.asie.charset.api.wires.IRedstoneEmitter;
-import pl.asie.charset.api.wires.IRedstoneReceiver;
-
-public final class CapabilitiesCharset {
- @CapabilityInject(IBundledEmitter.class)
- public static Capability BUNDLED_EMITTER;
- @CapabilityInject(IBundledReceiver.class)
- public static Capability BUNDLED_RECEIVER;
- @CapabilityInject(IRedstoneEmitter.class)
- public static Capability REDSTONE_EMITTER;
- @CapabilityInject(IRedstoneReceiver.class)
- public static Capability REDSTONE_RECEIVER;
-}
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc/util/SideTracker.java b/src/main/java/li/cil/oc/util/SideTracker.java
index 1a0f302ee7..238826eb2e 100644
--- a/src/main/java/li/cil/oc/util/SideTracker.java
+++ b/src/main/java/li/cil/oc/util/SideTracker.java
@@ -1,19 +1,14 @@
package li.cil.oc.util;
-import net.minecraftforge.fml.common.FMLCommonHandler;
+import net.minecraftforge.forgespi.Environment;
+import net.minecraftforge.fml.common.thread.EffectiveSide;
import java.util.Collections;
import java.util.Set;
public final class SideTracker {
- private static final Set serverThreads = Collections.newSetFromMap(new java.util.WeakHashMap());
-
- public static void addServerThread() {
- serverThreads.add(Thread.currentThread());
- }
-
public static boolean isServer() {
- return FMLCommonHandler.instance().getEffectiveSide().isServer() || serverThreads.contains(Thread.currentThread());
+ return Environment.get().getDist().isDedicatedServer() || EffectiveSide.get().isServer();
}
public static boolean isClient() {
diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg
new file mode 100644
index 0000000000..564c1daff7
--- /dev/null
+++ b/src/main/resources/META-INF/accesstransformer.cfg
@@ -0,0 +1,13 @@
+ # OpenComputers access transformer config
+public net.minecraft.block.PistonBlock func_176319_a(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;Z)Z # moveBlocks
+public-f net.minecraft.entity.player.PlayerEntity field_71069_bz # inventoryMenu
+public-f net.minecraft.entity.player.PlayerEntity field_71071_by # inventory
+public net.minecraft.tileentity.AbstractFurnaceTileEntity field_214018_j # litTime
+public net.minecraft.tileentity.AbstractFurnaceTileEntity field_214019_k # litDuration
+public net.minecraft.tileentity.AbstractFurnaceTileEntity field_214020_l # cookingProgress
+public net.minecraft.tileentity.AbstractFurnaceTileEntity field_214021_m # cookingTotalTime
+public net.minecraft.tileentity.BeaconTileEntity field_146010_n # secondaryPower
+public net.minecraft.tileentity.BeaconTileEntity field_146013_m # primaryPower
+public net.minecraft.tileentity.BrewingStandTileEntity field_145946_k # brewTime
+public net.minecraft.tileentity.SignTileEntity field_145915_a # messages
+public net.minecraft.world.spawner.AbstractSpawner func_190895_g()Lnet/minecraft/util/ResourceLocation; # getEntityId
diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml
new file mode 100644
index 0000000000..b043f05888
--- /dev/null
+++ b/src/main/resources/META-INF/mods.toml
@@ -0,0 +1,29 @@
+modLoader="scorge"
+loaderVersion="[${sversion},)"
+license="MIT, CC0 (see LICENSE)"
+issueTrackerURL="https://github.com/MightyPirates/OpenComputers/issues"
+
+[[mods]]
+modId="opencomputers"
+entryClass="li.cil.oc.OpenComputers"
+version="${version}"
+displayName="OpenComputers"
+displayURL="http://oc.cil.li/"
+logoFile="pack.png"
+credits="Inspired by a couple of other mods, most notably ComputerCraft."
+authors="Sangar, Vexatos, payonel, magik6k, Lord Joda and Github Contributors"
+description="This mod adds modular computers and robots that can be programmed in Lua."
+
+[[dependencies.opencomputers]]
+ modId="minecraft"
+ mandatory=true
+ versionRange="[${mcversion}]"
+ ordering="NONE"
+ side="BOTH"
+
+[[dependencies.opencomputers]]
+ modId="jei"
+ mandatory=false
+ versionRange="[7,)"
+ ordering="AFTER"
+ side="BOTH"
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/adapter.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/adapter.json
deleted file mode 100644
index 039cc63217..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/adapter.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:adapter.blocks"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/assembler.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/assembler.json
deleted file mode 100644
index 9db233b831..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/assembler.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:remaining"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/cable.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/cable.json
deleted file mode 100644
index 2a5da92da9..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/cable.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["traits/environment.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/capacitor.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/capacitor.json
deleted file mode 100644
index 2a5da92da9..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/capacitor.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["traits/environment.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/case.json
deleted file mode 100644
index d0a7fe6c55..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[{
- "includes": [
- "traits/computer.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case1.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/case1.json
deleted file mode 100644
index 5236537c8f..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case1.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["case.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case2.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/case2.json
deleted file mode 100644
index 5236537c8f..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case2.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["case.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case3.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/case3.json
deleted file mode 100644
index 5236537c8f..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/case3.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["case.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/caseCreative.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/caseCreative.json
deleted file mode 100644
index 5236537c8f..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/caseCreative.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["case.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/charger.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/charger.json
deleted file mode 100644
index 5c05e72697..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/charger.json
+++ /dev/null
@@ -1,16 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ],
- "nbt": {
- "blacklist": [
- "chargeSpeed",
- "hasPower",
- "invertSignal"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/disassembler.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/disassembler.json
deleted file mode 100644
index 9ab51a0fc5..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/disassembler.json
+++ /dev/null
@@ -1,14 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:buffer",
- "oc:queue",
- "oc:total"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/diskDrive.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/diskDrive.json
deleted file mode 100644
index 7a52c2ef3b..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/diskDrive.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json",
- "traits/rotatable.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/geolyzer.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/geolyzer.json
deleted file mode 100644
index 2a5da92da9..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/geolyzer.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["traits/environment.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram.json
deleted file mode 100644
index 5e40db6c34..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/externalData.json",
- "traits/rotatable.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram1.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram1.json
deleted file mode 100644
index e7bedbd909..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram1.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["hologram.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram2.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram2.json
deleted file mode 100644
index e7bedbd909..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/hologram2.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["hologram.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/keyboard.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/keyboard.json
deleted file mode 100644
index a1a9760b28..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/keyboard.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[{
- "includes": ["traits/rotatable.json"],
- "nbt": {
- "blacklist": [
- "oc:keyboard"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/microcontroller.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/microcontroller.json
deleted file mode 100644
index de8fbc3846..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/microcontroller.json
+++ /dev/null
@@ -1,18 +0,0 @@
-[{
- "includes": [
- "traits/computer.json",
- "traits/hub.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:info",
- "oc:snooper",
- "oc:componentNodes",
- "oc:outputs"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/motionSensor.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/motionSensor.json
deleted file mode 100644
index 2a5da92da9..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/motionSensor.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["traits/environment.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/netSplitter.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/netSplitter.json
deleted file mode 100644
index 5c133025fa..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/netSplitter.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/redstone.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/powerConverter.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/powerConverter.json
deleted file mode 100644
index 4b10cadc24..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/powerConverter.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/powerAcceptor.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/powerDistributor.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/powerDistributor.json
deleted file mode 100644
index 0ce5d96fcc..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/powerDistributor.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "oc:connector"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/printer.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/printer.json
deleted file mode 100644
index 7c1dca4816..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/printer.json
+++ /dev/null
@@ -1,16 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:active",
- "oc:amountInk",
- "oc:amountMaterial",
- "oc:limit",
- "oc:remaining",
- "oc:total"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/raid.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/raid.json
deleted file mode 100644
index 7a52c2ef3b..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/raid.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/inventory.json",
- "traits/rotatable.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/redstone.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/redstone.json
deleted file mode 100644
index f2be27863f..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/redstone.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[{
- "includes": ["traits/redstone.json"],
- "nbt": {
- "blacklist": [
- "oc:redstone/node"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/relay.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/relay.json
deleted file mode 100644
index 8853509610..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/relay.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[{
- "includes": [
- "traits/hub.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:componentNodes"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/robot.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/robot.json
deleted file mode 100644
index 53641eb9c1..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/robot.json
+++ /dev/null
@@ -1,24 +0,0 @@
-[{
- "includes": [
- "traits/computer.json",
- "traits/environment.json",
- "traits/inventory.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ],
- "nbt": {
- "blacklist": [
- "display",
- "oc:components",
- "oc:containers",
- "oc:lightColor",
- "oc:owner",
- "oc:ownerUuid",
- "oc:robot",
- "oc:robotEnergy",
- "oc:selectedSlot",
- "oc:selectedTank",
- "oc:storedEnergy"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen.json
deleted file mode 100644
index 369d342734..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen.json
+++ /dev/null
@@ -1,14 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/externalData.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:hasPower",
- "oc:hadRedstoneInput"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen1.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen1.json
deleted file mode 100644
index dadd2bf74b..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen1.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["screen.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen2.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen2.json
deleted file mode 100644
index dadd2bf74b..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen2.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["screen.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen3.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen3.json
deleted file mode 100644
index dadd2bf74b..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/screen3.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["screen.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/serverRack.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/serverRack.json
deleted file mode 100644
index 06dc5c6697..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/serverRack.json
+++ /dev/null
@@ -1,15 +0,0 @@
-[{
- "includes": [
- "traits/hub.json",
- "traits/inventory.json",
- "traits/powerAcceptor.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ],
- "nbt": {
- "blacklist": [
- "oc:servers",
- "oc:terminals"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/computer.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/computer.json
deleted file mode 100644
index d90950be10..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/computer.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "oc:computer"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/environment.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/environment.json
deleted file mode 100644
index b91cf6986e..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/environment.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "node",
- "oc:node"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/externalData.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/externalData.json
deleted file mode 100644
index c579dec594..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/externalData.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "chunkX",
- "chunkZ",
- "dimension"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/hub.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/hub.json
deleted file mode 100644
index 6994b8091a..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/hub.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "oc:plugs",
- "oc:queue"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/inventory.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/inventory.json
deleted file mode 100644
index f16d956de6..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/inventory.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[{
- "ignoreInventoryContents": true,
- "nbt": {
- "blacklist": [
- "oc:items"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/powerAcceptor.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/powerAcceptor.json
deleted file mode 100644
index 7500c660bc..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/powerAcceptor.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "oc:ae2power",
- "oc:ic2power",
- "oc:ic2cpower"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/redstone.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/redstone.json
deleted file mode 100644
index 6b28180698..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/redstone.json
+++ /dev/null
@@ -1,11 +0,0 @@
-[{
- "nbt": {
- "blacklist": [
- "oc:rs.input",
- "oc:rs.output",
- "oc:rs.bundledInput",
- "oc:rs.bundledOutput",
- "oc:rs.rednetInput"
- ]
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/rotatable.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/rotatable.json
deleted file mode 100644
index 2168077cf8..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/traits/rotatable.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "rotation": {
- "type": "nbtField",
- "tag": "oc:yaw",
- "format": "ForgeDirection"
- }
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/transposer.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/transposer.json
deleted file mode 100644
index 2a5da92da9..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/transposer.json
+++ /dev/null
@@ -1,3 +0,0 @@
-[{
- "includes": ["traits/environment.json"]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/bcbuilder/blocks/waypoint.json b/src/main/resources/assets/opencomputers/bcbuilder/blocks/waypoint.json
deleted file mode 100644
index 556f25dc77..0000000000
--- a/src/main/resources/assets/opencomputers/bcbuilder/blocks/waypoint.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{
- "includes": [
- "traits/environment.json",
- "traits/redstone.json",
- "traits/rotatable.json"
- ]
-}]
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/blockstates/accesspoint.json b/src/main/resources/assets/opencomputers/blockstates/accesspoint.json
index 617e1a249b..90e6d47100 100644
--- a/src/main/resources/assets/opencomputers/blockstates/accesspoint.json
+++ b/src/main/resources/assets/opencomputers/blockstates/accesspoint.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:accesspoint" }
+ "": { "model": "opencomputers:block/accesspoint" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/adapter.json b/src/main/resources/assets/opencomputers/blockstates/adapter.json
index 55444855fe..1893a7394b 100644
--- a/src/main/resources/assets/opencomputers/blockstates/adapter.json
+++ b/src/main/resources/assets/opencomputers/blockstates/adapter.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:adapter" }
+ "": { "model": "opencomputers:block/adapter" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/assembler.json b/src/main/resources/assets/opencomputers/blockstates/assembler.json
index b89ed2b1fd..f9cf866fce 100644
--- a/src/main/resources/assets/opencomputers/blockstates/assembler.json
+++ b/src/main/resources/assets/opencomputers/blockstates/assembler.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:assembler" }
+ "": { "model": "opencomputers:block/assembler" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/cable.json b/src/main/resources/assets/opencomputers/blockstates/cable.json
new file mode 100644
index 0000000000..dbeef9edc2
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/blockstates/cable.json
@@ -0,0 +1,5 @@
+{
+ "variants": {
+ "": { "model": "minecraft:block/air" }
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/blockstates/capacitor.json b/src/main/resources/assets/opencomputers/blockstates/capacitor.json
index 7887a194f2..ab9a30aebd 100644
--- a/src/main/resources/assets/opencomputers/blockstates/capacitor.json
+++ b/src/main/resources/assets/opencomputers/blockstates/capacitor.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:capacitor" }
+ "": { "model": "opencomputers:block/capacitor" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/carpetedcapacitor.json b/src/main/resources/assets/opencomputers/blockstates/carpetedcapacitor.json
index f6c92cb33b..43bb89c09f 100644
--- a/src/main/resources/assets/opencomputers/blockstates/carpetedcapacitor.json
+++ b/src/main/resources/assets/opencomputers/blockstates/carpetedcapacitor.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:carpetedcapacitor" }
+ "": { "model": "opencomputers:block/carpetedcapacitor" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/case1.json b/src/main/resources/assets/opencomputers/blockstates/case1.json
index 2ed08635bd..22429bafcf 100644
--- a/src/main/resources/assets/opencomputers/blockstates/case1.json
+++ b/src/main/resources/assets/opencomputers/blockstates/case1.json
@@ -1,12 +1,12 @@
{
"variants": {
- "facing=north,running=false": { "model": "opencomputers:case" },
- "facing=south,running=false": { "model": "opencomputers:case", "y": 180 },
- "facing=west,running=false": { "model": "opencomputers:case", "y": 270 },
- "facing=east,running=false": { "model": "opencomputers:case", "y": 90 },
- "facing=north,running=true": { "model": "opencomputers:case_running" },
- "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 },
- "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 },
- "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 }
+ "facing=north,running=false": { "model": "opencomputers:block/case" },
+ "facing=south,running=false": { "model": "opencomputers:block/case", "y": 180 },
+ "facing=west,running=false": { "model": "opencomputers:block/case", "y": 270 },
+ "facing=east,running=false": { "model": "opencomputers:block/case", "y": 90 },
+ "facing=north,running=true": { "model": "opencomputers:block/case_running" },
+ "facing=south,running=true": { "model": "opencomputers:block/case_running", "y": 180 },
+ "facing=west,running=true": { "model": "opencomputers:block/case_running", "y": 270 },
+ "facing=east,running=true": { "model": "opencomputers:block/case_running", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/case2.json b/src/main/resources/assets/opencomputers/blockstates/case2.json
index 2ed08635bd..22429bafcf 100644
--- a/src/main/resources/assets/opencomputers/blockstates/case2.json
+++ b/src/main/resources/assets/opencomputers/blockstates/case2.json
@@ -1,12 +1,12 @@
{
"variants": {
- "facing=north,running=false": { "model": "opencomputers:case" },
- "facing=south,running=false": { "model": "opencomputers:case", "y": 180 },
- "facing=west,running=false": { "model": "opencomputers:case", "y": 270 },
- "facing=east,running=false": { "model": "opencomputers:case", "y": 90 },
- "facing=north,running=true": { "model": "opencomputers:case_running" },
- "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 },
- "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 },
- "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 }
+ "facing=north,running=false": { "model": "opencomputers:block/case" },
+ "facing=south,running=false": { "model": "opencomputers:block/case", "y": 180 },
+ "facing=west,running=false": { "model": "opencomputers:block/case", "y": 270 },
+ "facing=east,running=false": { "model": "opencomputers:block/case", "y": 90 },
+ "facing=north,running=true": { "model": "opencomputers:block/case_running" },
+ "facing=south,running=true": { "model": "opencomputers:block/case_running", "y": 180 },
+ "facing=west,running=true": { "model": "opencomputers:block/case_running", "y": 270 },
+ "facing=east,running=true": { "model": "opencomputers:block/case_running", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/case3.json b/src/main/resources/assets/opencomputers/blockstates/case3.json
index 2ed08635bd..22429bafcf 100644
--- a/src/main/resources/assets/opencomputers/blockstates/case3.json
+++ b/src/main/resources/assets/opencomputers/blockstates/case3.json
@@ -1,12 +1,12 @@
{
"variants": {
- "facing=north,running=false": { "model": "opencomputers:case" },
- "facing=south,running=false": { "model": "opencomputers:case", "y": 180 },
- "facing=west,running=false": { "model": "opencomputers:case", "y": 270 },
- "facing=east,running=false": { "model": "opencomputers:case", "y": 90 },
- "facing=north,running=true": { "model": "opencomputers:case_running" },
- "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 },
- "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 },
- "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 }
+ "facing=north,running=false": { "model": "opencomputers:block/case" },
+ "facing=south,running=false": { "model": "opencomputers:block/case", "y": 180 },
+ "facing=west,running=false": { "model": "opencomputers:block/case", "y": 270 },
+ "facing=east,running=false": { "model": "opencomputers:block/case", "y": 90 },
+ "facing=north,running=true": { "model": "opencomputers:block/case_running" },
+ "facing=south,running=true": { "model": "opencomputers:block/case_running", "y": 180 },
+ "facing=west,running=true": { "model": "opencomputers:block/case_running", "y": 270 },
+ "facing=east,running=true": { "model": "opencomputers:block/case_running", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/casecreative.json b/src/main/resources/assets/opencomputers/blockstates/casecreative.json
index 2ed08635bd..22429bafcf 100644
--- a/src/main/resources/assets/opencomputers/blockstates/casecreative.json
+++ b/src/main/resources/assets/opencomputers/blockstates/casecreative.json
@@ -1,12 +1,12 @@
{
"variants": {
- "facing=north,running=false": { "model": "opencomputers:case" },
- "facing=south,running=false": { "model": "opencomputers:case", "y": 180 },
- "facing=west,running=false": { "model": "opencomputers:case", "y": 270 },
- "facing=east,running=false": { "model": "opencomputers:case", "y": 90 },
- "facing=north,running=true": { "model": "opencomputers:case_running" },
- "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 },
- "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 },
- "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 }
+ "facing=north,running=false": { "model": "opencomputers:block/case" },
+ "facing=south,running=false": { "model": "opencomputers:block/case", "y": 180 },
+ "facing=west,running=false": { "model": "opencomputers:block/case", "y": 270 },
+ "facing=east,running=false": { "model": "opencomputers:block/case", "y": 90 },
+ "facing=north,running=true": { "model": "opencomputers:block/case_running" },
+ "facing=south,running=true": { "model": "opencomputers:block/case_running", "y": 180 },
+ "facing=west,running=true": { "model": "opencomputers:block/case_running", "y": 270 },
+ "facing=east,running=true": { "model": "opencomputers:block/case_running", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/chameliumblock.json b/src/main/resources/assets/opencomputers/blockstates/chameliumblock.json
index b1affded73..4f4f19a937 100644
--- a/src/main/resources/assets/opencomputers/blockstates/chameliumblock.json
+++ b/src/main/resources/assets/opencomputers/blockstates/chameliumblock.json
@@ -1,20 +1,20 @@
{
"variants": {
- "color=silver": { "model": "opencomputers:chameliumblock" },
- "color=magenta": { "model": "opencomputers:chameliumblock" },
- "color=light_blue": { "model": "opencomputers:chameliumblock" },
- "color=red": { "model": "opencomputers:chameliumblock" },
- "color=yellow": { "model": "opencomputers:chameliumblock" },
- "color=gray": { "model": "opencomputers:chameliumblock" },
- "color=brown": { "model": "opencomputers:chameliumblock" },
- "color=cyan": { "model": "opencomputers:chameliumblock" },
- "color=green": { "model": "opencomputers:chameliumblock" },
- "color=blue": { "model": "opencomputers:chameliumblock" },
- "color=purple": { "model": "opencomputers:chameliumblock" },
- "color=orange": { "model": "opencomputers:chameliumblock" },
- "color=pink": { "model": "opencomputers:chameliumblock" },
- "color=black": { "model": "opencomputers:chameliumblock" },
- "color=white": { "model": "opencomputers:chameliumblock" },
- "color=lime": { "model": "opencomputers:chameliumblock" }
+ "color=light_gray": { "model": "opencomputers:block/chameliumblock" },
+ "color=magenta": { "model": "opencomputers:block/chameliumblock" },
+ "color=light_blue": { "model": "opencomputers:block/chameliumblock" },
+ "color=red": { "model": "opencomputers:block/chameliumblock" },
+ "color=yellow": { "model": "opencomputers:block/chameliumblock" },
+ "color=gray": { "model": "opencomputers:block/chameliumblock" },
+ "color=brown": { "model": "opencomputers:block/chameliumblock" },
+ "color=cyan": { "model": "opencomputers:block/chameliumblock" },
+ "color=green": { "model": "opencomputers:block/chameliumblock" },
+ "color=blue": { "model": "opencomputers:block/chameliumblock" },
+ "color=purple": { "model": "opencomputers:block/chameliumblock" },
+ "color=orange": { "model": "opencomputers:block/chameliumblock" },
+ "color=pink": { "model": "opencomputers:block/chameliumblock" },
+ "color=black": { "model": "opencomputers:block/chameliumblock" },
+ "color=white": { "model": "opencomputers:block/chameliumblock" },
+ "color=lime": { "model": "opencomputers:block/chameliumblock" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/charger.json b/src/main/resources/assets/opencomputers/blockstates/charger.json
index 54cebc64e8..6d0afd9e90 100644
--- a/src/main/resources/assets/opencomputers/blockstates/charger.json
+++ b/src/main/resources/assets/opencomputers/blockstates/charger.json
@@ -1,8 +1,8 @@
{
"variants": {
- "facing=north": { "model": "opencomputers:charger" },
- "facing=south": { "model": "opencomputers:charger", "y": 180 },
- "facing=west": { "model": "opencomputers:charger", "y": 270 },
- "facing=east": { "model": "opencomputers:charger", "y": 90 }
+ "facing=north": { "model": "opencomputers:block/charger" },
+ "facing=south": { "model": "opencomputers:block/charger", "y": 180 },
+ "facing=west": { "model": "opencomputers:block/charger", "y": 270 },
+ "facing=east": { "model": "opencomputers:block/charger", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/disassembler.json b/src/main/resources/assets/opencomputers/blockstates/disassembler.json
index 8b7823ccfa..2ce043f06c 100644
--- a/src/main/resources/assets/opencomputers/blockstates/disassembler.json
+++ b/src/main/resources/assets/opencomputers/blockstates/disassembler.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:disassembler" }
+ "": { "model": "opencomputers:block/disassembler" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/diskdrive.json b/src/main/resources/assets/opencomputers/blockstates/diskdrive.json
index c157589956..68bc7d87df 100644
--- a/src/main/resources/assets/opencomputers/blockstates/diskdrive.json
+++ b/src/main/resources/assets/opencomputers/blockstates/diskdrive.json
@@ -1,8 +1,8 @@
{
"variants": {
- "facing=north": { "model": "opencomputers:diskdrive" },
- "facing=south": { "model": "opencomputers:diskdrive", "y": 180 },
- "facing=west": { "model": "opencomputers:diskdrive", "y": 270 },
- "facing=east": { "model": "opencomputers:diskdrive", "y": 90 }
+ "facing=north": { "model": "opencomputers:block/diskdrive" },
+ "facing=south": { "model": "opencomputers:block/diskdrive", "y": 180 },
+ "facing=west": { "model": "opencomputers:block/diskdrive", "y": 270 },
+ "facing=east": { "model": "opencomputers:block/diskdrive", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/endstone.json b/src/main/resources/assets/opencomputers/blockstates/endstone.json
index 128583c89f..f14a18da61 100644
--- a/src/main/resources/assets/opencomputers/blockstates/endstone.json
+++ b/src/main/resources/assets/opencomputers/blockstates/endstone.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "minecraft:end_stone" }
+ "": { "model": "minecraft:block/end_stone" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/geolyzer.json b/src/main/resources/assets/opencomputers/blockstates/geolyzer.json
index 006954e9d3..7ee1d77440 100644
--- a/src/main/resources/assets/opencomputers/blockstates/geolyzer.json
+++ b/src/main/resources/assets/opencomputers/blockstates/geolyzer.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:geolyzer" }
+ "": { "model": "opencomputers:block/geolyzer" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/hologram1.json b/src/main/resources/assets/opencomputers/blockstates/hologram1.json
index e35d1d4984..0d567612b4 100644
--- a/src/main/resources/assets/opencomputers/blockstates/hologram1.json
+++ b/src/main/resources/assets/opencomputers/blockstates/hologram1.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:hologram1" }
+ "": { "model": "opencomputers:block/hologram1" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/hologram2.json b/src/main/resources/assets/opencomputers/blockstates/hologram2.json
index f0f48e0c77..21638bd491 100644
--- a/src/main/resources/assets/opencomputers/blockstates/hologram2.json
+++ b/src/main/resources/assets/opencomputers/blockstates/hologram2.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:hologram2" }
+ "": { "model": "opencomputers:block/hologram2" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/keyboard.json b/src/main/resources/assets/opencomputers/blockstates/keyboard.json
index 242fa77a4b..1490131bb4 100644
--- a/src/main/resources/assets/opencomputers/blockstates/keyboard.json
+++ b/src/main/resources/assets/opencomputers/blockstates/keyboard.json
@@ -1,16 +1,16 @@
{
"variants": {
- "pitch=north,yaw=north": { "model": "opencomputers:keyboard" },
- "pitch=north,yaw=east": { "model": "opencomputers:keyboard", "y": 90 },
- "pitch=north,yaw=south": { "model": "opencomputers:keyboard", "y": 180 },
- "pitch=north,yaw=west": { "model": "opencomputers:keyboard", "y": 270 },
- "pitch=up,yaw=north": { "model": "opencomputers:keyboard", "x": -90, "y": 180 },
- "pitch=up,yaw=east": { "model": "opencomputers:keyboard", "x": -90, "y": 270 },
- "pitch=up,yaw=south": { "model": "opencomputers:keyboard", "x": -90 },
- "pitch=up,yaw=west": { "model": "opencomputers:keyboard", "x": -90, "y": 90 },
- "pitch=down,yaw=north": { "model": "opencomputers:keyboard", "x": 90, "y": 180 },
- "pitch=down,yaw=east": { "model": "opencomputers:keyboard", "x": 90, "y": 270 },
- "pitch=down,yaw=south": { "model": "opencomputers:keyboard", "x": 90 },
- "pitch=down,yaw=west": { "model": "opencomputers:keyboard", "x": 90, "y": 90 }
+ "pitch=north,yaw=north": { "model": "opencomputers:block/keyboard" },
+ "pitch=north,yaw=east": { "model": "opencomputers:block/keyboard", "y": 90 },
+ "pitch=north,yaw=south": { "model": "opencomputers:block/keyboard", "y": 180 },
+ "pitch=north,yaw=west": { "model": "opencomputers:block/keyboard", "y": 270 },
+ "pitch=up,yaw=north": { "model": "opencomputers:block/keyboard", "x": -90, "y": 180 },
+ "pitch=up,yaw=east": { "model": "opencomputers:block/keyboard", "x": -90, "y": 270 },
+ "pitch=up,yaw=south": { "model": "opencomputers:block/keyboard", "x": -90 },
+ "pitch=up,yaw=west": { "model": "opencomputers:block/keyboard", "x": -90, "y": 90 },
+ "pitch=down,yaw=north": { "model": "opencomputers:block/keyboard", "x": 90, "y": 180 },
+ "pitch=down,yaw=east": { "model": "opencomputers:block/keyboard", "x": 90, "y": 270 },
+ "pitch=down,yaw=south": { "model": "opencomputers:block/keyboard", "x": 90 },
+ "pitch=down,yaw=west": { "model": "opencomputers:block/keyboard", "x": 90, "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/microcontroller.json b/src/main/resources/assets/opencomputers/blockstates/microcontroller.json
index ae4a9aa8ea..c329e47fa9 100644
--- a/src/main/resources/assets/opencomputers/blockstates/microcontroller.json
+++ b/src/main/resources/assets/opencomputers/blockstates/microcontroller.json
@@ -1,8 +1,8 @@
{
"variants": {
- "facing=north": { "model": "opencomputers:microcontroller" },
- "facing=south": { "model": "opencomputers:microcontroller", "y": 180 },
- "facing=west": { "model": "opencomputers:microcontroller", "y": 270 },
- "facing=east": { "model": "opencomputers:microcontroller", "y": 90 }
+ "facing=north": { "model": "opencomputers:block/microcontroller" },
+ "facing=south": { "model": "opencomputers:block/microcontroller", "y": 180 },
+ "facing=west": { "model": "opencomputers:block/microcontroller", "y": 270 },
+ "facing=east": { "model": "opencomputers:block/microcontroller", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/motionsensor.json b/src/main/resources/assets/opencomputers/blockstates/motionsensor.json
index 6be6d0c07a..f1181d7ab7 100644
--- a/src/main/resources/assets/opencomputers/blockstates/motionsensor.json
+++ b/src/main/resources/assets/opencomputers/blockstates/motionsensor.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:motionsensor" }
+ "": { "model": "opencomputers:block/motionsensor" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/netsplitter.json b/src/main/resources/assets/opencomputers/blockstates/netsplitter.json
new file mode 100644
index 0000000000..dbeef9edc2
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/blockstates/netsplitter.json
@@ -0,0 +1,5 @@
+{
+ "variants": {
+ "": { "model": "minecraft:block/air" }
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/blockstates/powerconverter.json b/src/main/resources/assets/opencomputers/blockstates/powerconverter.json
index 3fc72045cf..47e646e637 100644
--- a/src/main/resources/assets/opencomputers/blockstates/powerconverter.json
+++ b/src/main/resources/assets/opencomputers/blockstates/powerconverter.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:powerconverter" }
+ "": { "model": "opencomputers:block/powerconverter" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/powerdistributor.json b/src/main/resources/assets/opencomputers/blockstates/powerdistributor.json
index 3ab0491654..2194435bd2 100644
--- a/src/main/resources/assets/opencomputers/blockstates/powerdistributor.json
+++ b/src/main/resources/assets/opencomputers/blockstates/powerdistributor.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:powerdistributor" }
+ "": { "model": "opencomputers:block/powerdistributor" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/print.json b/src/main/resources/assets/opencomputers/blockstates/print.json
new file mode 100644
index 0000000000..dbeef9edc2
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/blockstates/print.json
@@ -0,0 +1,5 @@
+{
+ "variants": {
+ "": { "model": "minecraft:block/air" }
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/blockstates/printer.json b/src/main/resources/assets/opencomputers/blockstates/printer.json
index 18e8d7c5b4..e87119e7bd 100644
--- a/src/main/resources/assets/opencomputers/blockstates/printer.json
+++ b/src/main/resources/assets/opencomputers/blockstates/printer.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:printer" }
+ "": { "model": "opencomputers:block/printer" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/rack.json b/src/main/resources/assets/opencomputers/blockstates/rack.json
index 98bad44b77..27c0034d94 100644
--- a/src/main/resources/assets/opencomputers/blockstates/rack.json
+++ b/src/main/resources/assets/opencomputers/blockstates/rack.json
@@ -1,8 +1,8 @@
{
"variants": {
- "facing=north": { "model": "opencomputers:rack" },
- "facing=south": { "model": "opencomputers:rack", "y": 180 },
- "facing=west": { "model": "opencomputers:rack", "y": 270 },
- "facing=east": { "model": "opencomputers:rack", "y": 90 }
+ "facing=north": { "model": "opencomputers:block/rack" },
+ "facing=south": { "model": "opencomputers:block/rack", "y": 180 },
+ "facing=west": { "model": "opencomputers:block/rack", "y": 270 },
+ "facing=east": { "model": "opencomputers:block/rack", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/raid.json b/src/main/resources/assets/opencomputers/blockstates/raid.json
index 84de291f81..d9c02591a8 100644
--- a/src/main/resources/assets/opencomputers/blockstates/raid.json
+++ b/src/main/resources/assets/opencomputers/blockstates/raid.json
@@ -1,8 +1,8 @@
{
"variants": {
- "facing=north": { "model": "opencomputers:raid" },
- "facing=south": { "model": "opencomputers:raid", "y": 180 },
- "facing=west": { "model": "opencomputers:raid", "y": 270 },
- "facing=east": { "model": "opencomputers:raid", "y": 90 }
+ "facing=north": { "model": "opencomputers:block/raid" },
+ "facing=south": { "model": "opencomputers:block/raid", "y": 180 },
+ "facing=west": { "model": "opencomputers:block/raid", "y": 270 },
+ "facing=east": { "model": "opencomputers:block/raid", "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/redstone.json b/src/main/resources/assets/opencomputers/blockstates/redstone.json
index bd41205b87..db1ee2bed2 100644
--- a/src/main/resources/assets/opencomputers/blockstates/redstone.json
+++ b/src/main/resources/assets/opencomputers/blockstates/redstone.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:redstone" }
+ "": { "model": "opencomputers:block/redstone" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/relay.json b/src/main/resources/assets/opencomputers/blockstates/relay.json
index bb04449098..2ec907449b 100644
--- a/src/main/resources/assets/opencomputers/blockstates/relay.json
+++ b/src/main/resources/assets/opencomputers/blockstates/relay.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:relay" }
+ "": { "model": "opencomputers:block/relay" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/robot.json b/src/main/resources/assets/opencomputers/blockstates/robot.json
new file mode 100644
index 0000000000..dbeef9edc2
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/blockstates/robot.json
@@ -0,0 +1,5 @@
+{
+ "variants": {
+ "": { "model": "minecraft:block/air" }
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/blockstates/robotafterimage.json b/src/main/resources/assets/opencomputers/blockstates/robotafterimage.json
new file mode 100644
index 0000000000..dbeef9edc2
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/blockstates/robotafterimage.json
@@ -0,0 +1,5 @@
+{
+ "variants": {
+ "": { "model": "minecraft:block/air" }
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/blockstates/screen1.json b/src/main/resources/assets/opencomputers/blockstates/screen1.json
index b54966d253..63967b93f2 100644
--- a/src/main/resources/assets/opencomputers/blockstates/screen1.json
+++ b/src/main/resources/assets/opencomputers/blockstates/screen1.json
@@ -1,16 +1,16 @@
{
"variants": {
- "pitch=north,yaw=north": { "model": "opencomputers:screen" },
- "pitch=north,yaw=south": { "model": "opencomputers:screen", "y": 180 },
- "pitch=north,yaw=east": { "model": "opencomputers:screen", "y": 270 },
- "pitch=north,yaw=west": { "model": "opencomputers:screen", "y": 90 },
- "pitch=up,yaw=north": { "model": "opencomputers:screen", "x": 90 },
- "pitch=up,yaw=south": { "model": "opencomputers:screen", "x": 90, "y": 180 },
- "pitch=up,yaw=east": { "model": "opencomputers:screen", "x": 90, "y": 270 },
- "pitch=up,yaw=west": { "model": "opencomputers:screen", "x": 90, "y": 90 },
- "pitch=down,yaw=north": { "model": "opencomputers:screen", "x": -90 },
- "pitch=down,yaw=south": { "model": "opencomputers:screen", "x": -90, "y": 180 },
- "pitch=down,yaw=east": { "model": "opencomputers:screen", "x": -90, "y": 270 },
- "pitch=down,yaw=west": { "model": "opencomputers:screen", "x": -90, "y": 90 }
+ "pitch=north,yaw=north": { "model": "opencomputers:block/screen" },
+ "pitch=north,yaw=south": { "model": "opencomputers:block/screen", "y": 180 },
+ "pitch=north,yaw=east": { "model": "opencomputers:block/screen", "y": 270 },
+ "pitch=north,yaw=west": { "model": "opencomputers:block/screen", "y": 90 },
+ "pitch=up,yaw=north": { "model": "opencomputers:block/screen", "x": 90 },
+ "pitch=up,yaw=south": { "model": "opencomputers:block/screen", "x": 90, "y": 180 },
+ "pitch=up,yaw=east": { "model": "opencomputers:block/screen", "x": 90, "y": 270 },
+ "pitch=up,yaw=west": { "model": "opencomputers:block/screen", "x": 90, "y": 90 },
+ "pitch=down,yaw=north": { "model": "opencomputers:block/screen", "x": -90 },
+ "pitch=down,yaw=south": { "model": "opencomputers:block/screen", "x": -90, "y": 180 },
+ "pitch=down,yaw=east": { "model": "opencomputers:block/screen", "x": -90, "y": 270 },
+ "pitch=down,yaw=west": { "model": "opencomputers:block/screen", "x": -90, "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/screen2.json b/src/main/resources/assets/opencomputers/blockstates/screen2.json
index b54966d253..63967b93f2 100644
--- a/src/main/resources/assets/opencomputers/blockstates/screen2.json
+++ b/src/main/resources/assets/opencomputers/blockstates/screen2.json
@@ -1,16 +1,16 @@
{
"variants": {
- "pitch=north,yaw=north": { "model": "opencomputers:screen" },
- "pitch=north,yaw=south": { "model": "opencomputers:screen", "y": 180 },
- "pitch=north,yaw=east": { "model": "opencomputers:screen", "y": 270 },
- "pitch=north,yaw=west": { "model": "opencomputers:screen", "y": 90 },
- "pitch=up,yaw=north": { "model": "opencomputers:screen", "x": 90 },
- "pitch=up,yaw=south": { "model": "opencomputers:screen", "x": 90, "y": 180 },
- "pitch=up,yaw=east": { "model": "opencomputers:screen", "x": 90, "y": 270 },
- "pitch=up,yaw=west": { "model": "opencomputers:screen", "x": 90, "y": 90 },
- "pitch=down,yaw=north": { "model": "opencomputers:screen", "x": -90 },
- "pitch=down,yaw=south": { "model": "opencomputers:screen", "x": -90, "y": 180 },
- "pitch=down,yaw=east": { "model": "opencomputers:screen", "x": -90, "y": 270 },
- "pitch=down,yaw=west": { "model": "opencomputers:screen", "x": -90, "y": 90 }
+ "pitch=north,yaw=north": { "model": "opencomputers:block/screen" },
+ "pitch=north,yaw=south": { "model": "opencomputers:block/screen", "y": 180 },
+ "pitch=north,yaw=east": { "model": "opencomputers:block/screen", "y": 270 },
+ "pitch=north,yaw=west": { "model": "opencomputers:block/screen", "y": 90 },
+ "pitch=up,yaw=north": { "model": "opencomputers:block/screen", "x": 90 },
+ "pitch=up,yaw=south": { "model": "opencomputers:block/screen", "x": 90, "y": 180 },
+ "pitch=up,yaw=east": { "model": "opencomputers:block/screen", "x": 90, "y": 270 },
+ "pitch=up,yaw=west": { "model": "opencomputers:block/screen", "x": 90, "y": 90 },
+ "pitch=down,yaw=north": { "model": "opencomputers:block/screen", "x": -90 },
+ "pitch=down,yaw=south": { "model": "opencomputers:block/screen", "x": -90, "y": 180 },
+ "pitch=down,yaw=east": { "model": "opencomputers:block/screen", "x": -90, "y": 270 },
+ "pitch=down,yaw=west": { "model": "opencomputers:block/screen", "x": -90, "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/screen3.json b/src/main/resources/assets/opencomputers/blockstates/screen3.json
index b54966d253..63967b93f2 100644
--- a/src/main/resources/assets/opencomputers/blockstates/screen3.json
+++ b/src/main/resources/assets/opencomputers/blockstates/screen3.json
@@ -1,16 +1,16 @@
{
"variants": {
- "pitch=north,yaw=north": { "model": "opencomputers:screen" },
- "pitch=north,yaw=south": { "model": "opencomputers:screen", "y": 180 },
- "pitch=north,yaw=east": { "model": "opencomputers:screen", "y": 270 },
- "pitch=north,yaw=west": { "model": "opencomputers:screen", "y": 90 },
- "pitch=up,yaw=north": { "model": "opencomputers:screen", "x": 90 },
- "pitch=up,yaw=south": { "model": "opencomputers:screen", "x": 90, "y": 180 },
- "pitch=up,yaw=east": { "model": "opencomputers:screen", "x": 90, "y": 270 },
- "pitch=up,yaw=west": { "model": "opencomputers:screen", "x": 90, "y": 90 },
- "pitch=down,yaw=north": { "model": "opencomputers:screen", "x": -90 },
- "pitch=down,yaw=south": { "model": "opencomputers:screen", "x": -90, "y": 180 },
- "pitch=down,yaw=east": { "model": "opencomputers:screen", "x": -90, "y": 270 },
- "pitch=down,yaw=west": { "model": "opencomputers:screen", "x": -90, "y": 90 }
+ "pitch=north,yaw=north": { "model": "opencomputers:block/screen" },
+ "pitch=north,yaw=south": { "model": "opencomputers:block/screen", "y": 180 },
+ "pitch=north,yaw=east": { "model": "opencomputers:block/screen", "y": 270 },
+ "pitch=north,yaw=west": { "model": "opencomputers:block/screen", "y": 90 },
+ "pitch=up,yaw=north": { "model": "opencomputers:block/screen", "x": 90 },
+ "pitch=up,yaw=south": { "model": "opencomputers:block/screen", "x": 90, "y": 180 },
+ "pitch=up,yaw=east": { "model": "opencomputers:block/screen", "x": 90, "y": 270 },
+ "pitch=up,yaw=west": { "model": "opencomputers:block/screen", "x": 90, "y": 90 },
+ "pitch=down,yaw=north": { "model": "opencomputers:block/screen", "x": -90 },
+ "pitch=down,yaw=south": { "model": "opencomputers:block/screen", "x": -90, "y": 180 },
+ "pitch=down,yaw=east": { "model": "opencomputers:block/screen", "x": -90, "y": 270 },
+ "pitch=down,yaw=west": { "model": "opencomputers:block/screen", "x": -90, "y": 90 }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/switch.json b/src/main/resources/assets/opencomputers/blockstates/switch.json
index 18c289b041..24f1db9d96 100644
--- a/src/main/resources/assets/opencomputers/blockstates/switch.json
+++ b/src/main/resources/assets/opencomputers/blockstates/switch.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:switch" }
+ "": { "model": "opencomputers:block/switch" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/transposer.json b/src/main/resources/assets/opencomputers/blockstates/transposer.json
index 32bd3dad6d..eb059ab372 100644
--- a/src/main/resources/assets/opencomputers/blockstates/transposer.json
+++ b/src/main/resources/assets/opencomputers/blockstates/transposer.json
@@ -1,5 +1,5 @@
{
"variants": {
- "normal": { "model": "opencomputers:transposer" }
+ "": { "model": "opencomputers:block/transposer" }
}
}
diff --git a/src/main/resources/assets/opencomputers/blockstates/waypoint.json b/src/main/resources/assets/opencomputers/blockstates/waypoint.json
index 2b4a7f93db..1c856cd5ad 100644
--- a/src/main/resources/assets/opencomputers/blockstates/waypoint.json
+++ b/src/main/resources/assets/opencomputers/blockstates/waypoint.json
@@ -1,16 +1,16 @@
{
"variants": {
- "pitch=north,yaw=north": { "model": "opencomputers:waypoint" },
- "pitch=north,yaw=east": { "model": "opencomputers:waypoint", "y": 90 },
- "pitch=north,yaw=south": { "model": "opencomputers:waypoint", "y": 180 },
- "pitch=north,yaw=west": { "model": "opencomputers:waypoint", "y": 270 },
- "pitch=up,yaw=north": { "model": "opencomputers:waypoint", "x": -90 },
- "pitch=up,yaw=east": { "model": "opencomputers:waypoint", "x": -90, "y": 90 },
- "pitch=up,yaw=south": { "model": "opencomputers:waypoint", "x": -90, "y": 180 },
- "pitch=up,yaw=west": { "model": "opencomputers:waypoint", "x": -90, "y": 270 },
- "pitch=down,yaw=north": { "model": "opencomputers:waypoint", "x": 90 },
- "pitch=down,yaw=east": { "model": "opencomputers:waypoint", "x": 90, "y": 90 },
- "pitch=down,yaw=south": { "model": "opencomputers:waypoint", "x": 90, "y": 180 },
- "pitch=down,yaw=west": { "model": "opencomputers:waypoint", "x": 90, "y": 270 }
+ "pitch=north,yaw=north": { "model": "opencomputers:block/waypoint" },
+ "pitch=north,yaw=east": { "model": "opencomputers:block/waypoint", "y": 90 },
+ "pitch=north,yaw=south": { "model": "opencomputers:block/waypoint", "y": 180 },
+ "pitch=north,yaw=west": { "model": "opencomputers:block/waypoint", "y": 270 },
+ "pitch=up,yaw=north": { "model": "opencomputers:block/waypoint", "x": -90 },
+ "pitch=up,yaw=east": { "model": "opencomputers:block/waypoint", "x": -90, "y": 90 },
+ "pitch=up,yaw=south": { "model": "opencomputers:block/waypoint", "x": -90, "y": 180 },
+ "pitch=up,yaw=west": { "model": "opencomputers:block/waypoint", "x": -90, "y": 270 },
+ "pitch=down,yaw=north": { "model": "opencomputers:block/waypoint", "x": 90 },
+ "pitch=down,yaw=east": { "model": "opencomputers:block/waypoint", "x": 90, "y": 90 },
+ "pitch=down,yaw=south": { "model": "opencomputers:block/waypoint", "x": 90, "y": 180 },
+ "pitch=down,yaw=west": { "model": "opencomputers:block/waypoint", "x": 90, "y": 270 }
}
}
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/adapter.md b/src/main/resources/assets/opencomputers/doc/de_de/block/adapter.md
index e588bc8030..6fe53a4124 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/adapter.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/adapter.md
@@ -1,6 +1,6 @@
# Adapter
-
+
Der Adapter ermöglicht es [Computern](../general/computer.md) mit Vanilla-Minecraft-Blöcken oder Blöcken von anderen Mods zu interagieren. Unterstützte Blöcke neben dem Adapter werden als Komponenten des Computers aufgelistet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/assembler.md b/src/main/resources/assets/opencomputers/doc/de_de/block/assembler.md
index eb6f6d08a1..a845f24fdb 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/assembler.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/assembler.md
@@ -1,6 +1,6 @@
# Elektronik-Werkbank
-
+
Die Elektronik-Werkbank ist eine fortgeschrittene Maschine welche verwendet werden kann, um komplexere elektronische Geräte wie [Roboter](robot.md), [Drohnen](../item/drone.md) oder [Tablets](../item/tablet.md) zu bauen. Sie benötigen eine große Menge an Energie um Geräte zu montieren, daher wird empfohlen, sie mittels einer [Kondensatorbank (capacitor bank)](capacitor.md) mit Energie zu versorgen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/cable.md b/src/main/resources/assets/opencomputers/doc/de_de/block/cable.md
index 0316ae0e15..6d0044b160 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/cable.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/cable.md
@@ -1,6 +1,6 @@
# Kabel
-
+
Das Kabel ist eine Möglichkeit, [Computer](../general/computer.md) und Maschinen, die weit auseinander stehen zu verbinden. Kompakte Bauten, bei denen sich alle Komponenten direkt oder indirekt berühren (die meisten Blöcke verhalten sich für Kabel) benötigen in der Regel keine Kabel.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/capacitor.md b/src/main/resources/assets/opencomputers/doc/de_de/block/capacitor.md
index 54f8a3b4e8..1d968d0000 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/capacitor.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/capacitor.md
@@ -1,6 +1,6 @@
# Kondensator
-
+
Der Kondensator speichert Energie welche vom Netzwerk genutzt werden kann. Dadurch funktioniert es als Energiepuffer wenn es benötigt wird. Im Gegensatz zum Konvertieren von Energietypen anderer Mods (mittels eines [Energiekonverters](powerConverter.md)) erfolgt die Umwandlung von Energie innerhalb eines Subnetzwerkes ohne Verzögerung. Es ist nützlich, einen internen Energiepuffer für energieintensive Aufgaben (wie [Montage](assembler.md) oder das [Aufladen](charger.md) von Geräten wie [Robotern](robot.md) oder [Drohnen](../item/drone.md) zu haben.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/case1.md b/src/main/resources/assets/opencomputers/doc/de_de/block/case1.md
index de68ea0afe..7c74e5eb53 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/case1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/case1.md
@@ -1,6 +1,6 @@
# Computergehäuse
-
+
Computergehäuse gibt es in drei verschiedenen Stufen. Die Stufe bestimmt die maximale Anzahl an Komponenten, die eingesetzt werden können. Es gibt eine zusätzliche Stufe für den Kreativ-Modus. Gehäuse können ebenfalls in einer [Elektronik-Werkbank](assembler.md) platziert werden, um [Roboter](robot.md) zu bauen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/chameliumblock.md b/src/main/resources/assets/opencomputers/doc/de_de/block/chameliumblock.md
index 92f1167937..8bd97f886d 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/chameliumblock.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/chameliumblock.md
@@ -1,6 +1,6 @@
# Chamälium-Block
-
+
Einige Stücke [Chamälium](../item/chamelium.md) können kombiniert werden, um einen dekorativen Monochrom-Block zu schaffen. Chamäliumblöcke können mit einer der 16 Minecraft-Farben gefärbt werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/charger.md b/src/main/resources/assets/opencomputers/doc/de_de/block/charger.md
index 747a5b1d44..755f87ddc7 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/charger.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/charger.md
@@ -1,6 +1,6 @@
# Ladegerät
-
+
Das Ladegerät wird verwendet, um Geräte wie den [Roboter](robot.md), [Drohnen](../item/drone.md) und [Tablets](../item/tablet.md) zu laden. Ein Ladegerät muss mit einem Redstonesignal aktiviert werden. Die Ladegeschwindigkeit hängt von der Stärke des Redstonesignals ab. Eine Stärke von 15 bedeutet 100% Ladegeschwindigkeit.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/disassembler.md b/src/main/resources/assets/opencomputers/doc/de_de/block/disassembler.md
index 10bcece267..b5accf6b0f 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/disassembler.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/disassembler.md
@@ -1,6 +1,6 @@
# Recycler
-
+
Der Recycler kann verwendet werden, um die meisten Items in ihre Bestandteile aufzuteilen. Dies ist besonders nützlich um Materialien von unnütz gewordenen Bauteilen zurückzubekommen, oder um Geräte zu demontieren, die nicht länger nützlich sind oder inkorrekt gebaut wurden (z.B. [Roboter](robot.md) ohne [Betriebssystem](../general/openOS.md)).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/diskdrive.md b/src/main/resources/assets/opencomputers/doc/de_de/block/diskdrive.md
index 1317702848..8715aefd84 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/diskdrive.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/diskdrive.md
@@ -1,6 +1,6 @@
# Diskettenlaufwerk
-
+
Das Diskettenlaufwerk kann verwendet werden, um [Disketten](../item/floppy.md) mittels eines Computers auszulesen. Dies ist am Anfang nützlich, da niedrigstufige [Computergehäuse](case1.md) keinen eingebauten Diskettenslot haben. Dennoch benötigst du ein Betriebssystem um den Computer hochzufahren. Eine [OpenOS](../general/openOS.md)-Diskette kann mit einer leeren [Diskette](../item/floppy.md) und dem [Handbuch](../item/manual.md) gefertigt werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/geolyzer.md b/src/main/resources/assets/opencomputers/doc/de_de/block/geolyzer.md
index 7d3a6582ad..d48cacfce3 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/geolyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/geolyzer.md
@@ -1,6 +1,6 @@
# Geolyzer
-
+
Der Geolyzer kann von [Computern](../general/computer.md) verwendet werden, um das umgebende Terrain auf die ungefähre Härte von Blöcken zu analysieren. Dies ist nützlich um Karten der Gegend zu generieren, die auf einem [Hologrammprojektor](hologram1.md) angezeigt werden. Erze sind üblicherweise härter als Erde und Stein, daher kann man mit dem Geolyzer potenziell wertvolle Blöcke finden. Die Ergebnisse sind in der Regel etwas ungenau, theoretisch können mehrere Scans zu genaueren Ergebnissen führen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/hologram1.md b/src/main/resources/assets/opencomputers/doc/de_de/block/hologram1.md
index 990192f466..48ad70c42e 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/hologram1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/hologram1.md
@@ -1,6 +1,6 @@
# Hologrammprojektor
-
+
Der Hologrammprojektor ist ein 3D-Display, das bedeutet es stellt ein dreidimensionales Array von "Voxeln" bereit, die von einem Computer einzeln aktiviert oder deaktiviert können. Der Stufe-2-Projektor hat dieselbe Auflösung, unterstützt allerdings die Darstellung in drei verschiedenen Farben.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/keyboard.md b/src/main/resources/assets/opencomputers/doc/de_de/block/keyboard.md
index 27046aa4a9..dbf54146b7 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/keyboard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/keyboard.md
@@ -1,6 +1,6 @@
# Tastatur
-
+
Eine Tastatur wird benötigt um Text auf [Bildschirme](screen1.md) zu schreiben, egal ob in der Welt platziert oder in Geräte eingebaut (wie bei [Robotern](robot.md) oder [Tablets](../item/tablet.md)).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/motionsensor.md b/src/main/resources/assets/opencomputers/doc/de_de/block/motionsensor.md
index 0da1a476f3..3a2073c73e 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/motionsensor.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/motionsensor.md
@@ -1,6 +1,6 @@
# Bewegungssensor
-
+
Der Bewegungssensor erlaubt es [Computern](../general/computer.md) Bewegungen von lebenden Entities zu erkennen. Wenn die Geschwindigkeit eines Lebewesens einen Schwellenwert überschreitet wird ein Signal zum angeschlossenen Computer gesendet. Der Schwellwert kann mittels der Komponenten-API welche der Bewegungssensor bereitstellt verändert werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/netsplitter.md b/src/main/resources/assets/opencomputers/doc/de_de/block/netsplitter.md
index d9b2dbb477..d06dc6c550 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/netsplitter.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/netsplitter.md
@@ -1,6 +1,6 @@
# Net Splitter
-
+
Der Net Splitter ist ein Gerät das eine Kontrolle der Verbindungen zwischen Subnetzwerken ermöglicht. Im Gegensatz zum [Switch](switch.md) oder dem [Energiekonverter](powerConverter.md) verbindet es benachbarte Subnetzwerke direkt, das bedeutet, dass auf Komponenten zugegriffen werden kann. Die Verbindungen zu jeder Seite kann mit einem Schraubenschlüssel eingestellt werden (zum Beispiel den [srench](../item/wrench.md)). Wenn ein Redstonesignal an den Netzwerksplitter gesendet wird, werden alle Seiten invertiert.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/powerconverter.md b/src/main/resources/assets/opencomputers/doc/de_de/block/powerconverter.md
index 5de9f9e6d1..c92f4d3836 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/powerconverter.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/powerconverter.md
@@ -1,5 +1,5 @@
# Leistungswandler
-
+
Der Leistungswandler stellt den schnellsten Weg dar, um Energie von anderen Mods zu OpenComputers eigenem Energiesystem zu konvertieren. Wenn nur ein Computer verwendet wird, wird dieser nicht nötig sein. Bei einer großen Kondensatorbank, die nur dann und wann geleert wird, ist er ebenfalls nicht nötig. Wenn hingegen eine [Elektronik-Werkbank](assembler.md) oder eine [Ladestation](charger.md) direkt mit Energie versorgt werden soll, ist es eine gute Idee, diesen Konverter zu verwenden, anstatt sie direkt zu einer externen Energiequelle anzuschließen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/powerdistributor.md b/src/main/resources/assets/opencomputers/doc/de_de/block/powerdistributor.md
index 192d90725c..796a1e6757 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/powerdistributor.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/powerdistributor.md
@@ -1,5 +1,5 @@
# Stromverteiler
-
+
Der Stromverteiler verteilt Energie in einem geteilten Energiespeicher (wie beispielsweise in einem [Kondensator](capacitor.md). Dadurch können verschiedene Subnetzwerke dieselbe Energiequelle verwenden ohne Komponenten sichtbar zu machen. Es balanciert die Energie in allen Subnetzwerken aus, sodass sie alle die selbe relative Menge an Energie haben.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/printer.md b/src/main/resources/assets/opencomputers/doc/de_de/block/printer.md
index 5bcb842475..bfec00fa32 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/printer.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/printer.md
@@ -1,6 +1,6 @@
# 3D-Drucker
-
+
3D-Drucker erlauben es, Blöcke von jeder Form mit jeder Art von Textur zu drucken. Um mit 3D-Druckern anzufangen wird ein 3D-Drucker und ein Computer benötigt. Dadurch erhält man Zugriff auf die `printer3d`-Komponenten-API. Hiermit können [Modelle](print.md) erstellt und gedruckt werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/raid.md b/src/main/resources/assets/opencomputers/doc/de_de/block/raid.md
index 586b067c1d..ead8ba3b34 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/raid.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/raid.md
@@ -1,6 +1,6 @@
# RAID
-
+
Der RAID-Block enthält drei [Festplatten](../item/hdd1.md), welche zu einem einzelnen Dateisystem kombiniert werden. Dieses einzelne Dateisystem hat als Kapazität die Summe der einzelnen Kapazitäten. Das Dateisystem kann mit allen angeschlossenen [Computern](../general/computer.md) verwendet werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/redstone.md b/src/main/resources/assets/opencomputers/doc/de_de/block/redstone.md
index eafa6bc0fd..3bb9812fe1 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/redstone.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/redstone.md
@@ -1,6 +1,6 @@
# Redstone-I/O
-
+
Der Redstone-I/O-Block kann verwendet werden, um ferngesteuert Redstonesignale auszugeben und einzulesen. Es verhält sich wie ein Hybrid einer Stufe-1- und einer Stufe-2-[Redstonekarte](../item/redstoneCard1.md). Es kann analoge und gebündelte Signale lesen wie schreiben, aber kann keine kabellosen Redstonesignale ausgeben.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/relay.md b/src/main/resources/assets/opencomputers/doc/de_de/block/relay.md
index e2842edd65..3650db3194 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/relay.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/relay.md
@@ -1,6 +1,6 @@
# Relay
-
+
Das Relay kann verwendet werden um verschiedene Subnetzwerken das Senden von Nachrichten zueinander zu ermöglichen, ohne Komponenten Computern in anderen Netzen zugänglich zu machen. Grundsätzlich ist es eine gute Idee Komponenten lokal zu behalten, damit [Computer](../general/computer.md) nicht die falschen Komponenten ansprechen oder Komponenten-Overflows zu verursachen (welche dazu führen, dass Computer crashen und nicht hochfahren.)
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/screen1.md b/src/main/resources/assets/opencomputers/doc/de_de/block/screen1.md
index 4ad4be4fef..e7dab91e4c 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/screen1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/screen1.md
@@ -1,6 +1,6 @@
# Bildschirme
-
+
Ein Bildschirm wird in Kombinationen mit [Grafikkarten](../item/graphicsCard1.md) verwendet, um mit [Computern](../general/computer.md) Text darzustellen. Verschiedene Stufen haben unterschiedliche Fähigkeiten, wie die Unterstützung verschiedener Auflösungen und Farbtiefen. Sie reichen von geringauflösenden Monochromdisplays zu hochauflösenden Displays mit bis zu 256 Farben.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/serverrack.md b/src/main/resources/assets/opencomputers/doc/de_de/block/serverrack.md
index b7125eb7e6..575cfd1da6 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/serverrack.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/serverrack.md
@@ -1,6 +1,6 @@
# Serverschrank
-
+
Ein Serverschrank kann bis zu vier [Server](../item/server1.md) enthalten. Ein Server ist ein höherstufiger [Computer](../general/computer.md) welcher nur in einem Serverschrank laufen kann. Server können mit einer [Fernbedienung](../item/terminal.md) ferngesteuert werden. Die Anzahl der Terminals die gleichzeitig mit einem Server verbunden werden können wird von der Stufe des Servers begrenzt. Der Abstand zum Server, bis zu dem das Terminal funktioniert kann in der GUI des Serverschranks konfiguriert werden. Mehr Reichweite bedeutet mehr Energieverbrauch.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/block/waypoint.md b/src/main/resources/assets/opencomputers/doc/de_de/block/waypoint.md
index 26a4e24306..b8b23003fa 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/block/waypoint.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/block/waypoint.md
@@ -1,6 +1,6 @@
# Wegpunkt
-
+
Der Wegpunkt kann mit Hilfe des [Navigations-Upgrades](../item/navigationUpgrade.md) erkannt werden. So können Geräte mit diesem Upgrade Wegpunkte verwenden um durch die Welt zu navigieren. Dies ist besonders nützlich zum Schreiben einfach wiederverwendbarer Programme für Geräte wie [Roboter](robot.md) und [Drohnen](../item/drone.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/general/quickstart.md b/src/main/resources/assets/opencomputers/doc/de_de/general/quickstart.md
index e3e9766a0f..88225bed43 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/general/quickstart.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/general/quickstart.md
@@ -6,7 +6,7 @@ Auch bekannt als "Wie man seinen ersten Computer baut". Um deinen ersten [Comput
Zuerst wirst du ein [Computergehäuse](../block/case1.md) benötigen. Dies sit der Block der alle Komponenten benötigt und das Verhalten des gebauten Computers bestimmen.
-
+
Zum Beispiel musst du bestimmen, welche Stufe die [Grafikkarte](../item/graphicsCard1.md) du benötigst, ob eine [Netzwerkkarte](../item/lanCard.md) oder eine [Redstonekarte](../item/redstoneCard1.md) benötigt wird oder, wenn du im Creative-Mode spielst, eine [Debugkarte](../item/debugCard.md) gebraucht wird.
@@ -38,7 +38,7 @@ Wenn du, wie in den Screenshots oben, ein Stufe-2-Gehäuse verwendet hast gibt e
Es lebt! Zumindest sollte es das. Wenn es das nicht tut lief etwas falsch, und das [Analysegerät](../item/analyzer.md) wird bei der Fehlersuche helfen. Wenn der Computer jetzt läuft bist zu weitgehend fertig und der schwerste Teil ist vorbei. Du musst es nur noch mit einem
Um die Ausgabe des Computers zu lesen wird ein [Bildschirm](../block/screen1.md) und eine Grafikkarte benötigt.
-
+
Platziere den Bildschirm entweder direkt neben den Computer oder verbinde sie mit einem Kabel. Setze eine Grafikkarte deiner Wahl in den Computer ein. Nun sollte ein blinkender Cursor auf dem Bildschirm sichtbar sein. Jetzt fehlt nur noch eine [Tastatur](../block/keyboard.md) entweder direkt auf dem Bildschirm oder neben dem Bildschirm (mit Ausrichtung auf diesen).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/abstractbuscard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/abstractbuscard.md
index 5807e0ae59..e47a712465 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/abstractbuscard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/abstractbuscard.md
@@ -1,5 +1,5 @@
# Abstrakter-Bus-Karte
-
+
Diese Karte erlaubt es [Computern](../general/computer.md), [Servern](server1.md) und [Robotern](../block/robot.md) mit Abstract Busses von StargateTech2 zu interagieren. Wenn die Karte installiert ist, werden sich die entsprechenden Blöcke mit dem abstrakten Bus verbinden und eine Komponente wird für die Maschine sichtbar. Damit können Nachrichten über den Bus gesendet werden. Hereinkommende Nachrichten werden in Signale konvertiert und zur Maschine gesendet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/acid.md b/src/main/resources/assets/opencomputers/doc/de_de/item/acid.md
index f9af47bc2f..f037d67c67 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/acid.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/acid.md
@@ -1,5 +1,5 @@
# Grog
-
+
Wird nur bei Hard-Mode-Rezepten verwenden. Es ist verwendet um [Leiterplatten](circuitBoard.md) zu ätzen, bevor sie zu [gedruckten Leiterplatten](printedCircuitBoard.md) werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/alu.md b/src/main/resources/assets/opencomputers/doc/de_de/item/alu.md
index 485b93f6eb..39c6d115f6 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/alu.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/alu.md
@@ -1,5 +1,5 @@
# Arithmetic Logic Unit
-
+
Wird für rechnende Komponenten wie [CPUs](cpu1.md) und [Grafikkarten](graphicsCard1.md) benötigt.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/analyzer.md b/src/main/resources/assets/opencomputers/doc/de_de/item/analyzer.md
index ac436f7bf3..9b16a5c3a5 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/analyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/analyzer.md
@@ -1,6 +1,6 @@
# Messgerät
-
+
Das Messgerät ist ein nützliches Werkzeug um OpenComputers-Geräte auszulesen. Mittels eines Rechtsklickes (ggf. auch beim Schleichen) werden die Informationen in den Chatlog geschrieben. Darunter fallen grundlegende Dinge wie die Adresse von Komponenten, den Energiemassen im Subnetzwerk bis zu Informationen über einen Crash.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/angelupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/angelupgrade.md
index 6fff45b40a..b1d03bf383 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/angelupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/angelupgrade.md
@@ -1,5 +1,5 @@
# Engels-Upgrade
-
+
Dieses Upgrade ermöglicht es [Robotern](../block/robot.md) Blöcke mitten in die Luft zu platzieren.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/apu1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/apu1.md
index e473727a61..de11a79b34 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/apu1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/apu1.md
@@ -1,6 +1,6 @@
# Beschleunigter Prozessor (APU)
-
+
APUs sind eine Mischung aus [CPUs](cpu1.md) und [Grafikkarten](graphicsCard1.md). Diese zu nutzen ermöglicht es einen Kartenslot mehr zu verwenden. Wie eine normale CPU definiert es die Architektur des [Computers](../general/computer.md) und die Nummer der Komponenten die verwendet werden können. Es ermöglicht zudem auch grundlegende Grafikberechnungen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/arrowkeys.md b/src/main/resources/assets/opencomputers/doc/de_de/item/arrowkeys.md
index ef3b92bf4d..31dbafbc09 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/arrowkeys.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/arrowkeys.md
@@ -1,5 +1,5 @@
# Pfeiltasten
-
+
Pfeiltasten sind nötig um [Tastaturen](../block/keyboard.md) zu bauen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/batteryupgrade1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/batteryupgrade1.md
index 432d48289f..23c549b56b 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/batteryupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/batteryupgrade1.md
@@ -1,5 +1,5 @@
# Batterie-Upgrade
-
+
Dieses Upgrade erhöht den internen Energiespeicher von Geräten wie [Robotern](../block/robot.md) und [Tablets](tablet.md). Sie können damit länger verwendet werden, bevor sie mit einem [Ladegerät](../block/charger.md) geladen werden müssen. Hochstufige Upgrades haben mehr Batteriekapazität.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/buttongroup.md b/src/main/resources/assets/opencomputers/doc/de_de/item/buttongroup.md
index d6320600d0..348e9b7c21 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/buttongroup.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/buttongroup.md
@@ -1,5 +1,5 @@
# Tastengruppe
-
+
Weil du *immer* zu viele Knöpfe hast. Lüg nicht! Wir Shift-Klicken das Tastenrezept immer und immer wieder. Die Gruppen werden um Bauen von [Tastaturen](../block/keyboard.md) verwendet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/card.md b/src/main/resources/assets/opencomputers/doc/de_de/item/card.md
index b7fa57fcf9..31e29df1f7 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/card.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/card.md
@@ -1,5 +1,5 @@
# Karten
-
+
Übliches Ausgangsmaterial für kartenförmige Komponenten in OpenComputers (wie [Grafikkarten](graphicsCard1.md), [Netzwerkkarten](lanCard.md) usw.)
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/cardcontainer1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/cardcontainer1.md
index 68791181be..143b3e36d0 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/cardcontainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/cardcontainer1.md
@@ -1,5 +1,5 @@
# Kartenbehälter
-
+
Der Kartenbehälter ist ein Behälter-Upgrade für [Roboter](../block/robot.md) das es erlaubt, Karten in [Roboter](../block/robot.md) nach Bedarf einzusetzen oder zu entfernen. Die Stufe die eine Karte maximal haben darf gleicht der des Containers. Im Gegensatz zu normalen Upgrades ist die Komplexität das Doppelte seiner Stufe. Siehe [Komplexität](../block/robot.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/chamelium.md b/src/main/resources/assets/opencomputers/doc/de_de/item/chamelium.md
index e0d5a9fdbc..3055969d0b 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/chamelium.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/chamelium.md
@@ -1,6 +1,6 @@
# Chamälium
-
+
Chamälium ist ein formbares Material das für [3D-Drucke](../block/print.md) in [3D-Druckern](../block/printer.md) verwendet wird. Sonst ist es nutzlos und damit sehr nützlich um monochrome Bereiche zu erstellen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/chip1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/chip1.md
index 5f8f5f20a8..6139510a17 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/chip1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/chip1.md
@@ -1,5 +1,5 @@
# Microchips
-
+
Microchips sind die Grundlage für das Bauen von elektronischen Komponenten. Sie kommen in verschiedenen Stufen und ermöglichen unterschiedliche Komponentenstufen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/chunkloaderupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/chunkloaderupgrade.md
index 634948efff..d1c700c453 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/chunkloaderupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/chunkloaderupgrade.md
@@ -1,6 +1,6 @@
# Chunkloader-Upgrade
-
+
Das Chunkloader-Upgrade kann in Geräten wie [Robotern](../block/robot.md) oder [Mikrocontrollern](../block/microcontroller.md) installiert werden, um den Chunk in dem er sich befindet sowie umliegende Chunks geladen zu halten. Dies verbraucht jedoch Energie. Der Chunkloader kann mit der Komponenten-API ein- oder ausgeschaltet werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/circuitboard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/circuitboard.md
index d0a3154a29..24d7116594 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/circuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/circuitboard.md
@@ -1,5 +1,5 @@
# Leiterplatte
-
+
Zwischenitem das beim Herstellen von [bedruckten Leiterplatten](printedCircuitBoard.md) aus [rohen Leiterplatten](rawCircuitBoard.md) entsteht.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/componentbus1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/componentbus1.md
index e60791f68e..b1d9bc22de 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/componentbus1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/componentbus1.md
@@ -1,6 +1,6 @@
# Komponentenschnittstelle
-
+
Eine Komponentenschnittstelle ist ein [Server](server1.md)spezifisches Upgrade das es dem Server erlaubt, mit mehr Komponenten auf einmal zu kommunizieren ohne sich abzuschalten. Wie bei [CPUs](cpu1.md) auch ermöglichen höhere Stufen mehr Komponenten und höhere Stufen für Server ermöglichen mehr Slots für Komponentenschnittstellen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/controlunit.md b/src/main/resources/assets/opencomputers/doc/de_de/item/controlunit.md
index 1b270e19a2..7a0af554f6 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/controlunit.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/controlunit.md
@@ -1,5 +1,5 @@
# Kontrolleinheit
-
+
Hochstufiges Craftingitem in weiter entwickelten Schaltkreisen wie [CPUs](cpu1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/cpu1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/cpu1.md
index 3fb63ace8e..b73671cc2d 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/cpu1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/cpu1.md
@@ -1,6 +1,6 @@
# CPU
-
+
Die zentrale Recheneinheit ist das Herz eines jeden [Computers](../general/computer.md) oder [Servers](server1.md). Sie definiert die Architektur des Gerätes und die Anzahl der Komponenten die maximal mit dem Gerät verbunden werden können bevor er zu funktionieren aufhört. Hochstufige CPUs ermöglich außerdem eine schnellere Ausführung.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/craftingupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/craftingupgrade.md
index 806130c2a3..b270bba85d 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/craftingupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/craftingupgrade.md
@@ -1,5 +1,5 @@
# Crafting-Upgrade
-
+
Das Crafting-Upgrade erlaubt [Robotern](../block/robot.md) jede Art von Rezepten zu fertigen. Dabei werden Items aus dem [Inventar](../item/inventoryUpgrade.md) verwendet. Das 3x3-Netz im Inventar des Roboters wird als Werkbank verwendet. Items müssen entsprechend dem Rezept angeordnet sein. Ergebnisse werden im gewählten Slot im Inventar oder im nächsten freien Slot abgelegt, oder in die Welt geworfen, wenn kein Platz mehr übrig ist.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/cuttingwire.md b/src/main/resources/assets/opencomputers/doc/de_de/item/cuttingwire.md
index 88e76beffa..d8cdd040e9 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/cuttingwire.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/cuttingwire.md
@@ -1,5 +1,5 @@
# Schneidedraht
-
+
Dieses Item wird nur im Hard-Mode-Rezept für [Leiterplattenrohlinge](rawCircuitBoard.md) verwendet. Ineffektiv.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/databaseupgrade1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/databaseupgrade1.md
index 6cc5e5d852..867280cb4e 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/databaseupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/databaseupgrade1.md
@@ -1,6 +1,6 @@
# Datenbank-Upgrade
-
+
Das Datenbank-Upgrade kann konfiguriert werden um eine Liste von Itemstack-Repräsentationen zu speichern. Die können von anderen Komponenten verwendet werden. Das ist besonders nützlich für Items die mit ihren NBT-Daten sortiert werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/datacard1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/datacard1.md
index 6812b2cbb5..e1a4f70215 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/datacard1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/datacard1.md
@@ -1,6 +1,6 @@
# Datenkarte
-
+
Die Datenkarte ist eine Werkzeugkarte die einige Algorithmen zur Verfügung stellen die nur sehr schlecht oder sehr langsam implementierbar wären. Möglich ist Hashing und grundlegendes Inflating und Deflating.. Zudem enthält es ein angefügtes Dateisystem und stellt eine Vielzahl von Programmen zur Verfügung die die Funktionen der Karte verwenden, ähnlich der Internetkarte.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/debugcard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/debugcard.md
index 2e7cd6dae7..0cc40e7999 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/debugcard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/debugcard.md
@@ -1,6 +1,6 @@
# Debugkarte
-
+
Die Debugkarte ist ein Nur-Kreativ-Item das ursprünglich entwickelt wurde, um einige Vorgänge zu vereinfachen in dem sie einige Prozesse automatisieren. Es hat seitdem eine Vielfalt an Zusatzfunktionen erhalten.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/disk.md b/src/main/resources/assets/opencomputers/doc/de_de/item/disk.md
index e29167ac9a..4cf56b596d 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/disk.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/disk.md
@@ -1,5 +1,5 @@
# Speicherplatte
-
+
Grundlegende Komponente, die zum Bau von Speichermedien wie [Disketten](floppy.md) und [Festplatten](hdd1.md) benötigt wird.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/drone.md b/src/main/resources/assets/opencomputers/doc/de_de/item/drone.md
index 81a24f77ad..4e1bda25dd 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/drone.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/drone.md
@@ -1,5 +1,5 @@
# Drohne
-
+
Drohnen werden mit einem [Drohnengehäuse](droneCase1.md) in der [Elektronik-Werkbank](../block/assembler.md) gebaut. Sie sind entitybasierende [Roboter](../block/robot.md), allerdings ein bisschen günstiger und mit eingeschränkter Funktionalität. Sie können sich zudem weitaus schneller bewegen als [Roboter](../block/robot.md) und werden über ein Clientprogramm auf einem Computer gesteuert. Die Drohne benötigt ein konfiguriertes [EEPROM](eeprom.md) um Befehle zu empfangen oder selbst zu arbeiten.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/dronecase1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/dronecase1.md
index 01c4d37793..d4911b1a59 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/dronecase1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/dronecase1.md
@@ -1,6 +1,6 @@
# Drohnengehäuse
-
+
Das Drohnengehäuse wird verwendet um [Drohnen](drone.md) in der [Elektronik-Werkbank](../block/assembler.md) zu bauen. Drohnen sind leicht, schnell und sehr mobil, haben jedoch einen eingeschränkten Funktionenszeitraum (d.h. weniger Upgrade- und Komponentenslots sind verfügbar). Im Gegensatz zu [Robotern](../block/robot.md) können sie keine Werkzeuge verwenden und können nur indirekt mit der Welt interagieren.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/eeprom.md b/src/main/resources/assets/opencomputers/doc/de_de/item/eeprom.md
index 29953d1084..d051f64030 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/eeprom.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/eeprom.md
@@ -1,6 +1,6 @@
# EEPROM
-
+
Der EEPROM enthält den Code der verwendet wird um den Computer zu starten. Diese Daten sind als einfaches Bytearray gespeichert und können bei unterschiedlichen Architekturen andere Operationen auslösen. Das LUA-BIOS ist ein kleines Script das auf dem Dateisystem nach eine Datei namens `init.lua`. Auf anderen Architekturen kann es echter Maschinencode sein.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/experienceupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/experienceupgrade.md
index 2228289a2e..fed97371fe 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/experienceupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/experienceupgrade.md
@@ -1,6 +1,6 @@
# Erfahrungs-Upgrade
-
+
Das Erfahrungs-Upgrade ist ein sehr spezielles Upgrade, da es [Robotern](../block/robot.md) und [Drohnen](drone.md) ermöglicht, Erfahrung zu sammeln. Ein einziges Upgrade kann bis zu 30 Level speichern und ermöglicht damit kleinere Boni, wie schnellere Ausführung oder erhöhte Energiespeicherkapazität.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/floppy.md b/src/main/resources/assets/opencomputers/doc/de_de/item/floppy.md
index 945ee14a22..94e5ad504e 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/floppy.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/floppy.md
@@ -1,5 +1,5 @@
# Diskette
-
+
Die Diskette ist das günstigste und kleinste Speichermedium in OpenComputers. Es ist ein nützliches Item für das frühe Spiel um Daten zwischen den Geräten zu transferieren. Disketten mit nützlichen Programmen können in Dungeons gefunden werden (wie der OpenPrograms Package Manager, womit Programme von einem zentralen Github-Repository installiert werden können.)
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/generatorupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/generatorupgrade.md
index 3672b0a049..8958a14b5e 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/generatorupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/generatorupgrade.md
@@ -1,6 +1,6 @@
# Generator-Upgrade
-
+
Das Generator-Upgrade ermöglicht es Geräten sich im Betrieb neu aufzuladen. Zurzeit werden nur trockene Energiequellen (wie Kohle) unterstützt. Es hat ein internes Inventar welches ein Stack an Energiequellen halten kann. Überflüssige Energiequellen können über die Komponenten-API entfernt werden. Ein Upgrade von einem Roboter zu entfernen führt dazu, dass der Inhalt in die Welt geworfen wird.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/graphicscard1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/graphicscard1.md
index 770922a49b..f49dff83af 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/graphicscard1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/graphicscard1.md
@@ -1,6 +1,6 @@
# Grafikkarten
-
+
Die Grafikkarte ist essenziell für die meisten [Computer](../general/computer.md). Damit können sie Text auf einem verbundenen [Bildschirm](../block/screen1.md) darstellen. Grafikkarten kommen in verschiedenen Stufen, die zusammen mit dem Bildschirm unterschiedliche Auflösungen und Farbtiefen unterstützen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/hdd1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/hdd1.md
index 97473bf80e..9791371a83 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/hdd1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/hdd1.md
@@ -1,5 +1,5 @@
# Festplatte
-
+
Die Festplatten haben mehr Speicherplatz als andere OpenComputers-Speichermedien. Alle Medien arbeiten gleich schnell, haben allerdings unterschiedliche Speicherplatzgrößen. Es gibt auch Geräte die nur Disketten verwenden. Festplatten können in einem [RAID](../block/raid.md) platziert werden, um Geräten das Teilen des selben Dateisystems zu ermöglichen. Wenn eine Festplatte in einem RAID platziert werden, werden allerdings die Daten gelöscht.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/hoverboots.md b/src/main/resources/assets/opencomputers/doc/de_de/item/hoverboots.md
index 091a40e357..4636704fd8 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/hoverboots.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/hoverboots.md
@@ -1,6 +1,6 @@
# Schwebestiefel
-
+
Drohnen zu programmieren kann eine lange Zeit dauern. Es gibt allerdings eine Alternative dazu: Schwebestiefel.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/hoverupgrade1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/hoverupgrade1.md
index f19dc925f6..a35ee0a35d 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/hoverupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/hoverupgrade1.md
@@ -1,6 +1,6 @@
# Schwebe-Upgrade
-
+
Das Schwebe-Upgrade erlaubt es [Robotern](../block/robot.md) viel höher über dem Boden zu fliegen als normal. Im Gegensatz zu [Drohnen](drone.md) können diese nämlich standardmäßig nur 8 Block hoch schweben. Das ist normal kein großes Problem, da sie sich trotzdem an Wänden entlang bewegen können. Sie können sich so bewegen:
- Roboter können sich nur bewegen, wenn Start- und Zielposition gültig sind (z.B. um Brücken bauen zu können)
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/inkcartridge.md b/src/main/resources/assets/opencomputers/doc/de_de/item/inkcartridge.md
index d7655b3ab4..f17c0388eb 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/inkcartridge.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/inkcartridge.md
@@ -1,5 +1,5 @@
# Tintenkartusche
-
+
Tintenkartuschen sind nützlich um den Farbbuffer von [3D-Druckern·](../block/printer.md) zu füllen. Es ist auch möglich sie mit Farbmitteln direkt zu färben, das ist aber ineffizient. Am besten kaufen Sie noch heute die echten OC Tintenfarben (TM) heute! (Disclaimer: Unter Umständen könnten sie mehr als der Drucker selbst kosten.)
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/internetcard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/internetcard.md
index 5d36d5c30e..defb260596 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/internetcard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/internetcard.md
@@ -1,6 +1,6 @@
# Internetkarte
-
+
Internetkarten bieten [Computern](../general/computer.md) Internetzugriff. Einfache HTTP-Anfragen sind möglich, sowie einfache TCP-Client-Sockets die gelesen und beschrieben werden können.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/interweb.md b/src/main/resources/assets/opencomputers/doc/de_de/item/interweb.md
index 558b45f43b..9dfadb8974 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/interweb.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/interweb.md
@@ -1,5 +1,5 @@
# Internetz
-
+
Das Internetz ist eine grundlegende Komponente für alle Geräte die mit Hochdistanzkommunikation zusammenhängen. Es nutzt verrückte Mechaniken des Ends um Quantenlinienkommunikation zu ermöglichen. Wird vor allem in [Internetkarten](internetCard.md) und [verknüpften Karten](linkedCard.md) verwendet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/inventorycontrollerupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/inventorycontrollerupgrade.md
index 90f1c1c663..2414f00291 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/inventorycontrollerupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/inventorycontrollerupgrade.md
@@ -1,6 +1,6 @@
# Inventarbedienungs-Upgrade
-
+
Das Inventarbedienungs-Upgrade ermöglicht erweiterte Inventarinteraktionen für [Roboter](../block/robot.md) und [Drohnen](drone.md). Es erlaubt es dem Gerät explizit einzelne Slots in externen Inventaren zu verwenden. Es erlaubt es dem Gerät zudem detaillierte Informationen über seine Itemstacks zu lesen. Zuletzt stellt es Robotern eine Möglichkeit zur Verfügung, das Werkzeug ohne Hilfe zu wechseln.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/inventoryupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/inventoryupgrade.md
index 94ca075c90..4954d5da89 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/inventoryupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/inventoryupgrade.md
@@ -1,6 +1,6 @@
# Inventar-Upgrade
-
+
Das Inventar-Upgrade stellt Inventarslots für [Roboter](../block/robot.md) und [Drohnen](drone.md) bereit. Jedes Upgrade fügt 16 Inventarslots hinzu, bis zu einem Maximum von 64 Slots. Eine Drohne fügt 4 Slots pro Upgrade hinzu, bis zu einem Maximum von 8 Slots.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/lancard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/lancard.md
index 968a1840cf..dbbe8dddbd 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/lancard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/lancard.md
@@ -1,5 +1,5 @@
# Netzwerkkarte
-
+
Die Netzwerkkarte erlaubt es [Computern](../general/computer.md), Nachrichten vom Netzwerk zu empfangen und zum Netzwerk zu senden. Nachrichten (oder Pakete) können über das ganze Netzwerk oder zu spezifischen Knotenpunkten mit einer bestimmten Adresse gesendet werden. [Switche](../block/switch.md) und [Access Points](../block/accessPoint.md) können verwendet werden, um verschiedene Netzwerke miteinander zu verbinden. Nachrichten können dann zwischen verschiedenen Netzwerken hin- und hergesendet werden, auch zwischen unterschiedlichen Subnetzwerken.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/leashupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/leashupgrade.md
index e7d4090a6b..499acdb7f8 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/leashupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/leashupgrade.md
@@ -1,5 +1,5 @@
# Leinen-Upgrade
-
+
Das Leinen-Upgrade ermöglicht es, Leinen auf Tiere anzulegen. Das entsprechende Gerät (zum Beispiel eine [Drohne](drone.md)) kann dann Tiere führen, auch mehrere auf einmal. Es ist damit recht einfach Herden zu bewegen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/linkedcard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/linkedcard.md
index 7a8d0f030e..f205000474 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/linkedcard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/linkedcard.md
@@ -1,5 +1,5 @@
# Verlinkte Karte
-
+
Die verlinkte Karte ist eine spezialisierte und fortgeschrittene Version einer [Netzwerkkarte](lanCard.md). Gelinkte Karten treten nur im Paar auf und ermöglichen eine direkte Kommunikation zwischen den beiden Karten. Gelinkte Karten können über unbegrenzt weite Distanzen und über Dimensionen hinweg kommunizieren.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/manual.md b/src/main/resources/assets/opencomputers/doc/de_de/item/manual.md
index 994f086141..47724f5207 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/manual.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/manual.md
@@ -1,6 +1,6 @@
# Handbuch
-
+
Das Ding das du gerade liest! Das Handbuch enthält eine Vielfalt von Informationen über OpenComputers (und vielleicht mehr). Wenn du mehr Informatonen über ein Item oder einen Block im Mod benötigst, bist du hier genau richtig! Scrolle herunter für mehr Informationen (Mausrad oder Scrollbar auf der rechten Seite).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/microcontrollercase1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/microcontrollercase1.md
index 3cf502fa1d..0ce27dfccd 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/microcontrollercase1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/microcontrollercase1.md
@@ -1,6 +1,6 @@
# Mikrocontroller-Gehäuse
-
+
Das Mikrocontroller-Gehäuse ist das grundlegende Teil zum Bau von [Mikrocontrollern](../block/microcontroller.md) in der [Elektronik-Werkbank](../block/assembler.md). Mikrocontroller sind sehr primitive [Computer](../general/computer.md). Sie können nur eine bestimmte Anzahl an Komponenten enthalten und sind für sehr spezifische Anwendungsfälle gedacht, wie das Reagieren auf Redstonesignale, oder das Verarbeiten von Netzwerknachrichten.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/navigationupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/navigationupgrade.md
index f10a49b737..c0e3fe53e4 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/navigationupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/navigationupgrade.md
@@ -1,6 +1,6 @@
# Navigations-Upgrade
-
+
Das Navigation-Upgrade stellt Informationen über den Standort und zur Orientierung bereit. Die Koordinaten, die das Upgrade zur Verfügung stellt sind relativ zum Zentrum der Karte, die zum Anfertigen des Upgrades verwendet wird. Die Reichweite des Upgrades basiert auf die Größe dieser Karte.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/numpad.md b/src/main/resources/assets/opencomputers/doc/de_de/item/numpad.md
index 013e2ad12d..bc42a57348 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/numpad.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/numpad.md
@@ -1,5 +1,5 @@
# Ziffernblock
-
+
Der Ziffernblock ist Teil einer jeden [Tastatur](../block/keyboard.md). Es erlaubt es, Zahlen einzugeben.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/pistonupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/pistonupgrade.md
index 7f1861216e..d3bf89146d 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/pistonupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/pistonupgrade.md
@@ -1,6 +1,6 @@
# Kolben-Upgrade
-
+
Das Kolben-Upgrade erlaubt es einigen Geräten, ähnlich wie Vanilla-Kolben zu arbeiten. Wenn es installiert ist, wird eine Komponente mit einer einzigen Methode verfügbar, der `push()`-Methode. Wenn sie aufgerufen wird, das Gerät versuchen, den Block in der Richtung zu verschieben, in die der Block zeigt. Bei [Robotern](../block/robot.md) und [Mikrocontrollern](../block/microcontroller.md) ist das die Vorderseite, bei [Tablets](tablets.md) ist das der Block auf den der Spieler schaut.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/printedcircuitboard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/printedcircuitboard.md
index 37d78454a2..9dd7a54d56 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/printedcircuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/printedcircuitboard.md
@@ -1,5 +1,5 @@
# Gedruckte Leiterplatte (PCB)
-
+
Die bedruckte Leiterplatte ist, neben dem [Transistor](transistor.md) eine der grundlegendsten Werkstoffe in OpenComputers. Es wird als Basis für viele Komponenten verwendet, wie [Karten](card.md) und eine große Anzahl an [Blöcken](../block/index.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/ram1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/ram1.md
index e5e05ab231..5786345dea 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/ram1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/ram1.md
@@ -1,6 +1,6 @@
# Speicher (RAM)
-
+
Der Random Access Memory ist, wie die [CPU](cpu1.md) ein grundlegendes Teil in allen [Computern](../general/computer.md). Je nach der Architektur der CPU hat der RAM einen großen Effekt darauf, was ein Computer kann und was er nicht kann. In der standardmäßigen LUA-Architektur kontrolliert es die tatsächliche Menge von Memory die LUA-Scripts verwenden können. Um größere und speicherintensivere Programme zu schreiben wird mehr Speicher verwendet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/rawcircuitboard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/rawcircuitboard.md
index ebdb1da2e1..017b799ff5 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/rawcircuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/rawcircuitboard.md
@@ -1,5 +1,5 @@
# Leiterplattenrohling
-
+
Zwischenprodukt beim Fertigen. Wird verwendet, um [Leiterplatten](circuitBoard.md) (oder [gedruckte Leiterplatten](printedCircuitBoard.md), je nach dem welches Recipe-Set verwendet wird) zu fertigen.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/redstonecard1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/redstonecard1.md
index b994efbbe0..b0a5bdd9a1 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/redstonecard1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/redstonecard1.md
@@ -1,6 +1,6 @@
# Redstonekarte
-
+
Die Redstonekarte ermöglicht [Computern](../general/computer.md) das Lesen und Senden von analogen Redstonesignalen zu benachbarten Blöcken. Wenn sich ein eingehendes Signal ändert wird dies dem Computer gemeldet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/server1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/server1.md
index 26245e30fe..a1153aa485 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/server1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/server1.md
@@ -1,6 +1,6 @@
# Server
-
+
Server sind eine Form von hochstufigen [Computern](../general/computer.md). Sie können mit Rechtsklick konfiguriert werden, wenn sie in der Hand liegen. Nach dem Einsetzen von [CPU](cpu1.md), [RAM](ram1.md) und Erweiterungskarten muss der Server in einem [Serverschrank](../block/serverRack.md) platziert werden. Für Informationen siehe [Eintrag des Serverschranks](../block/serverRack.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/signupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/signupgrade.md
index 95101e687f..7281ef6d38 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/signupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/signupgrade.md
@@ -1,5 +1,5 @@
# Schilder-I/O
-
+
Dieses Upgrade ermöglicht es Geräten mit Schildern in der Welt zu interagieren. Es erlaubt das Lesen von Schildern sowie das Ändern des Schildes (wenn möglich).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/solargeneratorupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/solargeneratorupgrade.md
index 49fd11ae08..7339361206 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/solargeneratorupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/solargeneratorupgrade.md
@@ -1,6 +1,6 @@
# Solargenerator-Upgrade
-
+
Das Solargenerator-Upgrade kann in Geräten wie [Robotern](../block/robot.md), [Drohnen](drone.md) und [Tablets](tablet.md) dazu verwendet werden, passiv Energie zu generieren. Es funktioniert nur, wenn das Gerät direktem Sonnenlicht ausgesetzt ist und keine Wetterereignisse stören.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/tablet.md b/src/main/resources/assets/opencomputers/doc/de_de/item/tablet.md
index ca3ec45db0..b8339f353a 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/tablet.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/tablet.md
@@ -1,6 +1,6 @@
# Tablet
-
+
Tablets werden gebaut, indem ein [Tabletgehäuse](tabletCase1.md) in einer [Elektronik-Werkbank](../block/assembler.md) eingesetzt, konfiguriert und montiert wird. Tablets sind tragbare Computer die nicht direkt mit der Welt interagieren können. Das bedeutet, dass beispielsweise [Redstonekarten](redstoneCard1.md) nicht darin funktionieren. Eine Vielfalt von Upgrades funktionieren schon, wie das [Schild-I/O](signUpgrade.md) oder das [Kolbenupgrade](pistonUpgrade.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/tabletcase1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/tabletcase1.md
index 5c82c1b68d..4772f57fb2 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/tabletcase1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/tabletcase1.md
@@ -1,6 +1,6 @@
# Tabletgehäuse
-
+
Das Tabletgehäuse ist das grundlegende Teil um [Tablets](tablet.md) in der [Elektronik-Werkbank](../block/assembler.md) zu bauen. Tablets sind sehr kompakte, tragbare [Computer](../general/computer.md). Sie können eine kleine Nummer von ausgewählten Upgrades halten und nicht mit der Welt interagieren (wie [Computergehäuse](../block/case1.md) mit [Netzwerkkarten](lanCard.md) oder [Redstonekarten](redstoneCard1.md) es können).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/tankcontrollerupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/tankcontrollerupgrade.md
index f8bb5a9652..71dea2b6a8 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/tankcontrollerupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/tankcontrollerupgrade.md
@@ -1,6 +1,6 @@
# Tankcontroller
-
+
Das Tankcontroller-Upgrade ist das [Inventarcontroller-Upgrade](inventoryControllerUpgrade.md) für Tanks. Es können detaillierte Informationen über Tanks abgefragt werden.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/tankupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/tankupgrade.md
index 94dc204a3e..4c9fda0e25 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/tankupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/tankupgrade.md
@@ -1,5 +1,5 @@
# Tank Upgrade
-
+
Das Tank-Upgrade ermöglicht es Geräten, Flüssigkeiten zu halten. Jeder Tank kann nur eine einzige Art von Flüssigkeit halten und stellt ein Volumen von 16 Eimern (16.000mB) zur Verfügung. [Roboter](../block/robot.md) und [Drohnen] können Flüssigkeiten aus der Welt aufnehmen und die Flüssigkeit dann in Tanks oder, wenn die Flüssigkeit das ermöglicht, wieder in der Welt platzieren. Es gibt kein Maximum an installierten Tanks in einem Gerät.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/terminal.md b/src/main/resources/assets/opencomputers/doc/de_de/item/terminal.md
index 71f0712c33..407e5f1eee 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/terminal.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/terminal.md
@@ -1,6 +1,6 @@
# Fernbedienungsterminal
-
+
Das Fernbedienungsterminal kann verwendet werden um [Server](server1.md) fernzusteuern. Um es zu verwenden reicht ein Rechtsklick (im Schleichen) auf einen Server in einem [Serverschrank](../block/serverRack.md). (Dabei muss auf den Server im Block gezeigt werden. Das Terminal wird dann auf den Server gebunden):
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/texturepicker.md b/src/main/resources/assets/opencomputers/doc/de_de/item/texturepicker.md
index 881dbdf38b..aae7acfbc4 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/texturepicker.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/texturepicker.md
@@ -1,6 +1,6 @@
# Texturleser
-
+
Der Texturleser ist sehr nützlich beim Anfertigen von Modellen für den [3D-Drucker](../block/printer.md). Es erlaubt das Abfragen der Texturnamen, die bei Blöcken in der Welt verwendet werden. Dies kann Probleme bei bestimmten Blöcken mit speziellem Rendering verursachen (wie z.B. bei Kisten)
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/tractorbeamupgrade.md b/src/main/resources/assets/opencomputers/doc/de_de/item/tractorbeamupgrade.md
index 975e72b638..c68b312e46 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/tractorbeamupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/tractorbeamupgrade.md
@@ -1,5 +1,5 @@
# Traktorstrahl-Upgrade
-
+
Das Traktorstrahl-Upgrade erlaubt es Geräten Items in einem Drei-Block-Radius um sie herum aufzusammeln. Dies kann besonders nützlich sein, wenn [Roboter](../block/robot.md) in Baum- oder anderen Farmen eingesetzt werden, oder wenn sie verschiedene Werkzeuge um Abbau von unterschiedlichen Blöcken einsetzen. Jeder Einsatz saugt einen einzelnen Itemstack auf und verbraucht Energie.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/transistor.md b/src/main/resources/assets/opencomputers/doc/de_de/item/transistor.md
index 93ca0c966e..636f4b3f98 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/transistor.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/transistor.md
@@ -1,5 +1,5 @@
# Transistor
-
+
Der Transistor ist einer der grundlegendsten Crafting-Materialien in OpenComputers. Es wird hauptsächlich für [Microchips](chip1.md) und andere elektronische Kleinigkeiten verwendet.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/upgradecontainer1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/upgradecontainer1.md
index 21abefdc7d..58ca6bb859 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/upgradecontainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/upgradecontainer1.md
@@ -1,5 +1,5 @@
# Upgrade-Container
-
+
Der Upgrade-Container ist ein Container-Upgrade für [Roboter](../block/robot.md). Es stellt einen Slot im Roboter zur Verfügung, in dem normale Upgrades platziert werden können. Die höchste Stufe das ein Upgrade haben darf gleicht der Stufe des Containers. Im Gegensatz zu normalen Upgrades ist die Komplexität des Containers doppelt so groß wie die Stufe. Für mehr Informationen über Komplexität siehe [Roboter](../block/robot.md) und [Elektronik-Werkbank](../block/assembler.md).
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/wlanCard1.md b/src/main/resources/assets/opencomputers/doc/de_de/item/wlanCard1.md
index ca07529a34..4f64ad72d2 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/wlanCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/wlanCard1.md
@@ -1,6 +1,6 @@
# Drahtlosnetzwerkkarte
-
+
Die kabellose Netzwerkkarte ist eine aufgewertete [Netzwerkkarte](lanCard.md) die, zusätzlich zu verkabelten Nachrichten, zudem das Senden von Nachrichten über kabellose Netzwerke ermöglicht. Die Signalstärke kontrolliert die Distanz über die Nachrichten versendet werden können. Die Signalstärke gleicht der Distanz in Blöcken.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/worldsensorcard.md b/src/main/resources/assets/opencomputers/doc/de_de/item/worldsensorcard.md
index bf63e2330b..30768e009a 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/worldsensorcard.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/worldsensorcard.md
@@ -1,5 +1,5 @@
# Weltsensorkarte
-
+
Die Weltsensorkarte ermöglicht es Informationen über die Atmosphäre und Gravitation von verschiedenen Planeten in GalactiCraft zu lesen. Das kann für [Roboter](../block/robot.md) oder [Drohnen](drone.md) im Weltraum nützlich sein.
diff --git a/src/main/resources/assets/opencomputers/doc/de_de/item/wrench.md b/src/main/resources/assets/opencomputers/doc/de_de/item/wrench.md
index 6312b9a64d..6b7e995050 100644
--- a/src/main/resources/assets/opencomputers/doc/de_de/item/wrench.md
+++ b/src/main/resources/assets/opencomputers/doc/de_de/item/wrench.md
@@ -1,5 +1,5 @@
# Schraubenziehschlüssel
-
+
Wie fast jede andere Technologie-Modifikation hat OpenComputer seine eigene Version eines Schraubenschlüssels. In diesem Fall ist es ein Schraubendreher-Schraubenschlüssel-Hybdrid, das unglaublich merkwürdig aussieht. Damit können die meisten Blöcke gedreht werden und ist mit den meisten Mods kompatibel.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/accesspoint.md b/src/main/resources/assets/opencomputers/doc/en_us/block/accesspoint.md
index 78bacc26c5..f6e5c1976a 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/accesspoint.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/accesspoint.md
@@ -1,6 +1,6 @@
# Access Point
-
+
*This block is deprecated and will be removed in a future version.* Craft it into a [relay](relay.md) to avoid losing it.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/adapter.md b/src/main/resources/assets/opencomputers/doc/en_us/block/adapter.md
index 4e6bb63710..6e7b6eabbe 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/adapter.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/adapter.md
@@ -1,6 +1,6 @@
# Adapter
-
+
The adapter allows [computers](../general/computer.md) to interact with blocks from vanilla Minecraft or other mods. Supported blocks adjacent to the adapter will show up as components in [computers](../general/computer.md) connected to the adapter.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/assembler.md b/src/main/resources/assets/opencomputers/doc/en_us/block/assembler.md
index cb25ceb76e..a6785ac6c0 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/assembler.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/assembler.md
@@ -1,6 +1,6 @@
# Assembler
-
+
The assembler is an advanced workstation that can be used to build more complex electronic devices, such as [robots](robot.md), [drones](../item/drone.md) and [tablets](../item/tablet.md). They require a large amount of energy to assemble devices, so it is recommended to power them sufficiently with a [capacitor bank](capacitor.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/cable.md b/src/main/resources/assets/opencomputers/doc/en_us/block/cable.md
index 8b4c7028ec..8e81a38fb0 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/cable.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/cable.md
@@ -1,6 +1,6 @@
# Cable
-
+
The cable serves as a way of connecting [computers](../general/computer.md) and machines that are far apart. If you have a compact build where all components touch each other (directly or indirectly, most blocks also behave the same way as cables) you will usually not need cables.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/capacitor.md b/src/main/resources/assets/opencomputers/doc/en_us/block/capacitor.md
index 5714f14839..73ddb08746 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/capacitor.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/capacitor.md
@@ -1,6 +1,6 @@
# Capacitor
-
+
The capacitor stores energy to be used by the network, acting as an energy buffer when needed. Unlike conversion from other mod's energy to OpenComputers' internal energy type (using a [power converter](powerConverter.md) for example), transferring energy inside a single subnetwork is instantaneous. Having an internal energy buffer will be useful for tasks that require a lot of energy, such as [assembling](assembler.md) and/or [charging](charger.md) devices such as [robots](robot.md) or [drones](../item/drone.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/case1.md b/src/main/resources/assets/opencomputers/doc/en_us/block/case1.md
index aa9c465721..0bbafd7df9 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/case1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/case1.md
@@ -1,6 +1,6 @@
# Computer Case
-
+
Computer cases come in three different tiers, which limits the components that can be inserted into them. An additional tier also exists for use in creative mode only. Computer cases can also be placed inside an [assembler](assembler.md) to build [robots](robot.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/chameliumblock.md b/src/main/resources/assets/opencomputers/doc/en_us/block/chameliumblock.md
index 99012ba02c..0521f4124b 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/chameliumblock.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/chameliumblock.md
@@ -1,6 +1,6 @@
# Block of Chamelium
-
+
A few pieces of [chamelium](../item/chamelium.md) can be combined to provide a monochrome block for decorative purposes. Chamelium blocks can also be dyed with any of the 16 Minecraft colors.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/charger.md b/src/main/resources/assets/opencomputers/doc/en_us/block/charger.md
index e8d3db1b47..060d089893 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/charger.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/charger.md
@@ -1,6 +1,6 @@
# Charger
-
+
The charger is used to charge devices such as [robots](robot.md), [drones](../item/drone.md) and [tablets](../item/tablet.md). A charger has to be activated by applying a redstone signal to it. The charge speed is based on the applied redstone signal's strength, with a strength of 15 meaning a charge speed of 100%.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/disassembler.md b/src/main/resources/assets/opencomputers/doc/en_us/block/disassembler.md
index 770376b9d9..0f5863d38a 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/disassembler.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/disassembler.md
@@ -1,6 +1,6 @@
# Disassembler
-
+
The disassembler can be used to deconstruct most items in OpenComputers into their original parts. This is mostly useful to reclaim materials from old parts that are no longer useful, or to deconstruct devices that are either no longer needed or were incorrectly built (e.g. [robots](robot.md) without an [operating system](../general/openOS.md)).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/diskdrive.md b/src/main/resources/assets/opencomputers/doc/en_us/block/diskdrive.md
index 5b844adca8..9c5ed502d0 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/diskdrive.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/diskdrive.md
@@ -1,6 +1,6 @@
# Disk Drive
-
+
The disk drive can be used to read [floppy disks](../item/floppy.md) using a [computer](../general/computer.md) connected to the disk drive. This is useful to get started, since the lower tier [computer cases](case1.md) do not have a built-in floppy slot, and you'll need an operating system to boot up the [computer](../general/computer.md). An [OpenOS](../general/openOS.md) disk can be crafted using an empty [floppy disk](../item/floppy.md) and a [manual](../item/manual.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/geolyzer.md b/src/main/resources/assets/opencomputers/doc/en_us/block/geolyzer.md
index e7c190a69f..b8c409caa1 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/geolyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/geolyzer.md
@@ -1,6 +1,6 @@
# Geolyzer
-
+
The geolyzer can be used by [computers](../general/computer.md) to scan the terrain surrounding the geolyzer for the blocks' approximate hardness. This can be useful to generate maps of the area to display on [hologram projectors](hologram1.md) as well as to detect potentially valuable blocks (ores are usually harder than dirt and stone). Geolyzer scan results have a certain amount of noise added; in theory, multiple scans can be performed to determine a more accurate reading of a block's hardness level.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/hologram1.md b/src/main/resources/assets/opencomputers/doc/en_us/block/hologram1.md
index 0e6d897692..8191ff017f 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/hologram1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/hologram1.md
@@ -1,6 +1,6 @@
# Hologram Projector
-
+
The hologram projector is a volumetric display, i.e. it provides a three dimensional array of voxels that can be individually enabled or disabled by a connected [computer](../general/computer.md). The second tier projector, while having the same resolution as the tier 1 projector, supports displaying the individual voxels in three different user-definable colors.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/keyboard.md b/src/main/resources/assets/opencomputers/doc/en_us/block/keyboard.md
index 485cc6942f..20327f920a 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/keyboard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/keyboard.md
@@ -1,6 +1,6 @@
# Keyboard
-
+
A keyboard is needed to type text on [screens](screen1.md), be they in the world or built into devices such as [robots](robot.md) or [tablets](../item/tablet.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/motionsensor.md b/src/main/resources/assets/opencomputers/doc/en_us/block/motionsensor.md
index 37225ec63e..5f6e78a218 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/motionsensor.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/motionsensor.md
@@ -1,6 +1,6 @@
# Motion Sensor
-
+
The motion sensor allows [computers](../general/computer.md) to detect movement of living entities. If an entity moves faster than a set threshold, a signal will be injected into [computers](../general/computer.md) connected to the motion sensor. The threshold can be configured using the component API that the motion sensor exposes to connected computers.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/netsplitter.md b/src/main/resources/assets/opencomputers/doc/en_us/block/netsplitter.md
index f6c02a7526..9122b71c45 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/netsplitter.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/netsplitter.md
@@ -1,6 +1,6 @@
# Net Splitter
-
+
The net splitter is a device that allows controlling connectivity between subnetworks. Unlike the [relay](relay.md) or [power converter](powerConverter.md) it directly connects adjacent subnetworks, i.e. components can be accessed. Each side's connectivity can be toggled using a wrench (e.g. the [scrench](../item/wrench.md)). When a redstone signal is applied to the net splitter, all sides' connectivity is inverted.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/powerconverter.md b/src/main/resources/assets/opencomputers/doc/en_us/block/powerconverter.md
index 07728c8922..735937e8af 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/powerconverter.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/powerconverter.md
@@ -1,5 +1,5 @@
# Power Converter
-
+
The power converter serves as the fastest way to convert energy from other mods' power systems to OpenComputers' internal energy. If you only run a simple computer, you probably won't need a converter. If you have a large capacitor bank that you only drain every now and then, you probably won't need one, either. However, if you wish to directly power an [assembler](assembler.md) or [charger](charger.md), it is usually a good idea to use a converter instead of directly connecting them to external power.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/powerdistributor.md b/src/main/resources/assets/opencomputers/doc/en_us/block/powerdistributor.md
index 70ec54adf4..13a4586fc4 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/powerdistributor.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/powerdistributor.md
@@ -1,5 +1,5 @@
# Power Distributor
-
+
The power distributor distributes a shared power storage (such as a [capacitor](capacitor.md)), allowing several subnetworks to share their energy without components being exposed to computers in other networks. It operates by regularly "balancing" the energy in all subnetworks it is connected to, so that the *relative* amount of energy is the same in them.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/printer.md b/src/main/resources/assets/opencomputers/doc/en_us/block/printer.md
index 3fdb09cae1..7e856fee6b 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/printer.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/printer.md
@@ -1,6 +1,6 @@
# 3D Printer
-
+
3D printers allow you to print any block of any shape, with any type of texture. To get started with 3D printers, you will need to place down a 3D printer block next to a computer. This will give access to the `printer3d` component API, allowing you to set up and print [models](print.md) using the provided functions.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/rack.md b/src/main/resources/assets/opencomputers/doc/en_us/block/rack.md
index 528344aba7..5c2c308f9a 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/rack.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/rack.md
@@ -1,6 +1,6 @@
# Rack
-
+
A rack houses up to four rack mountables such as [servers](../item/server1.md), [terminal servers](../item/terminalServer.md) and [mountable disk drives](../item/diskDriveMountable.md). Connectivity of mountables in a rack can be configured in detail via the GUI. In particular, if [servers](../item/server1.md) contain components that support it, such as [network cards](../item/lanCard.md), network-only connections can be defined for those components. These connections will serve purely for passing along network messages, components will not be visible through them. Such network-only connections are differentiated by the lines being slimmer than the "main" connections, which also allow component access. Each internal connection must be between a mountable / component in a mountable and a bus connected to a side of the rack. To connect multiple mountables to each other, connect them to the same bus.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/raid.md b/src/main/resources/assets/opencomputers/doc/en_us/block/raid.md
index 87eda27777..3ccb0efe3b 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/raid.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/raid.md
@@ -1,6 +1,6 @@
# Raid
-
+
The raid block houses three [hard drives](../item/hdd1.md) which will be combined into a single file system. This combined file system has the size of the sum of the capacities of the individual [hard drives](../item/hdd1.md) and is available to all [computers](../general/computer.md) connected to the raid.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/redstone.md b/src/main/resources/assets/opencomputers/doc/en_us/block/redstone.md
index 8978fc8842..df2b737c92 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/redstone.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/redstone.md
@@ -1,6 +1,6 @@
# Redstone I/O
-
+
The redstone I/O block can be used to remotely read and emit redstone signals. It behaves like a hybrid of a tier 1 and 2 [redstone card](../item/redstoneCard1.md): it can read and emit simple analog as well as bundled signals, but cannot read or emit wireless redstone signals.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/relay.md b/src/main/resources/assets/opencomputers/doc/en_us/block/relay.md
index 94fc589c28..ac8b585185 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/relay.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/relay.md
@@ -1,6 +1,6 @@
# Relay
-
+
The relay can be used to allow different subnetworks to send network messages to each other, without exposing components to [computers](../general/computer.md) in other networks. Keeping components local is usually a good idea, to avoid [computers](../general/computer.md) using the wrong [screen](screen1.md) or to avoid component overflows to happen (causing [computers](../general/computer.md) to crash and refuse to boot up).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/screen1.md b/src/main/resources/assets/opencomputers/doc/en_us/block/screen1.md
index 75710fb6b1..8781f5d52a 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/screen1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/screen1.md
@@ -1,6 +1,6 @@
# Screens
-
+
A screen is used in combination with a [graphics card](../item/graphicsCard1.md), to allow [computers](../general/computer.md) to display text. Different screen tiers have different capabilities, such as supporting different resolutions and color depths. Screens range from low-resolution, monochrome displays to high-resolution displays with up to 256 colors.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/switch.md b/src/main/resources/assets/opencomputers/doc/en_us/block/switch.md
index cff609e1c3..08164952e3 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/switch.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/switch.md
@@ -1,6 +1,6 @@
# Switch
-
+
*This block is deprecated and will be removed in a future version.* Craft it into a [relay](relay.md) to avoid losing it.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/transposer.md b/src/main/resources/assets/opencomputers/doc/en_us/block/transposer.md
index f666883bbe..840dfe7383 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/transposer.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/transposer.md
@@ -1,6 +1,6 @@
# Transposer
-
+
The transposer bridges the gap between redstone controlled hoppers and [robots](robot.md), allowing [computer](../general/computer.md)-controlled transferral of items and fluids between adjacent blocks.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/block/waypoint.md b/src/main/resources/assets/opencomputers/doc/en_us/block/waypoint.md
index 00dab81a44..bb6893ea1d 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/block/waypoint.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/block/waypoint.md
@@ -1,6 +1,6 @@
# Waypoint
-
+
The waypoint's use lies not in itself, but in how it can be used. [Navigation upgrades](../item/navigationUpgrade.md) can detect waypoints, so devices with a navigation upgrade can use these waypoints to navigate the world. This is particularly useful for writing easily reusable programs for devices such as [robots](robot.md) and [drones](../item/drone.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/general/example.md b/src/main/resources/assets/opencomputers/doc/en_us/general/example.md
index 3bdda70bc6..8db963f6c1 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/general/example.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/general/example.md
@@ -4,13 +4,13 @@ This is some test text for the subset of Markdown supported by the planned ingam


*This* is *italic* text, ~~strikethrough~~ maybe abc-ter **some** text **in bold**. Is _this underlined_? Oh, no, _it's also italic!_ Well, this [a link](../index.md).
-
+
## Smaller headline [also with *link* but this __one__ longer](../block/adapter.md)
-
+
some text directly above the item stack renderer to test spacing
-
+
some text directly below the item stack renderer to test spacing
This is *italic
@@ -42,9 +42,9 @@ asdasd  qweqwe
And finally, [this is a link!](https://avatars1.githubusercontent.com/u/514903).
-
-
-
+
+
+
wrap testing
12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
@@ -53,17 +53,17 @@ wrap testing
* 12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
- `123456789012345678901234567890.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890`
-this is a test for anan inline image kakakakalalsd 123 as
+this is a test for anan inline image kakakakalalsd 123 as
-this is a test for an
+this is a test for an
an image with a break after it
this is a test for an
-
+
an image between two lines
this is a test for an
-
+
an image between two blank lines
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/general/quickstart.md b/src/main/resources/assets/opencomputers/doc/en_us/general/quickstart.md
index fe5d776758..42c6038ec1 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/general/quickstart.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/general/quickstart.md
@@ -6,7 +6,7 @@ Also know as "how to build your first computer". To get your first [computer](co
First off, you will need a [computer case](../block/case1.md). This is the block which will contain all of the components, defining the behavior of the computer you are building.
-
+
For example, you will need to choose what tier of [graphics card](../item/graphicsCard1.md) you wish to use, if you need a [network card](../item/lanCard.md), a [redstone card](../item/redstoneCard1.md) or, if you're just playing around in creative mode, maybe even a [debug card](../item/debugCard.md).
@@ -37,7 +37,7 @@ Now, if you used a tier 2 [computer case](../block/case2.md) as in the screensho
It lives! Or should, anyway. If it doesn't something went wrong, and you'll want to investigate using the [analyzer](../item/analyzer.md). But assuming it's running now, you're pretty much done. The hardest part is over. All that's left is to make it take input and show some output.
To allow the [computer](computer.md) to show some output, you'll want to grab a [screen](../block/screen1.md) and a [graphics card](../item/graphicsCard1.md).
-
+
Place the [screen](../block/screen1.md) adjacent to your [computer case](../block/case1.md), or, again, connect it using some [cable](../block/cable.md). Then place a [graphics card](../item/graphicsCard1.md) of your choice into the [computer case](../block/case1.md). You should now see a blinking cursor on the [screen](../block/screen1.md). Finally, place a [keyboard](../block/keyboard.md) either on the [screen](../block/screen1.md) itself, or in a way so that it faces the [screen](../block/screen1.md), to enable [keyboard](../block/keyboard.md) input.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/abstractbuscard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/abstractbuscard.md
index 4263adfe2d..081e0788f0 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/abstractbuscard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/abstractbuscard.md
@@ -1,5 +1,5 @@
# Abstract Bus Card
-
+
This card allows [computers](../general/computer.md), [servers](server1.md) and [robots](../block/robot.md) to interact with StargateTech2's abstract bus. When the card is installed, these blocks will connect to the abstract bus and a component becomes available to the machine that can be used to send messages across the abstract bus. Incoming abstract bus messages are converted to signals that are injected into the machine.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/acid.md b/src/main/resources/assets/opencomputers/doc/en_us/item/acid.md
index a8020c0da1..d7d8ef0ba5 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/acid.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/acid.md
@@ -1,6 +1,6 @@
# Acid
-
+
This tasty [citation needed] concoction can be consumed if you ever feel the need for some... fun. Or ruining your digestive tract. Or both. It can also serve as ingredient in other, more useful items.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/alu.md b/src/main/resources/assets/opencomputers/doc/en_us/item/alu.md
index d429cb4045..3625a3e602 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/alu.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/alu.md
@@ -1,5 +1,5 @@
# Arithmetic Logic Unit
-
+
Used for crafting components that perform calculations, such as [CPUs](cpu1.md) and [graphics cards](graphicsCard1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/analyzer.md b/src/main/resources/assets/opencomputers/doc/en_us/item/analyzer.md
index b185704af1..92f8e0ee30 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/analyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/analyzer.md
@@ -1,6 +1,6 @@
# Analyzer
-
+
The analyzer is a handy tool for reading information about OpenComputers-related blocks in the world. Simply (sneak-)activate a block to get some information printed to the chat box. This ranges from basic things like the address of components, to power levels in the subnetwork the block is in, and information on the error lead to a [computer](../general/computer.md) to crash, for example.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/angelupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/angelupgrade.md
index 611146a39c..badae522c2 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/angelupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/angelupgrade.md
@@ -1,5 +1,5 @@
# Angel Upgrade
-
+
This upgrade allows [robots](../block/robot.md) to place blocks in thin air, without a reference block.
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/apu1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/apu1.md
index 674851e7af..872e4a46ca 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/apu1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/apu1.md
@@ -1,6 +1,6 @@
# APU
-
+
These parts are the merry marriage of a [CPU](cpu1.md) and [graphics card](graphicsCard1.md). Using one of these essentially gives you one more card slot to work with. Like a normal CPU, it defines the architecture of the [computer](../general/computer.md), and the number of components that can be connected to the [computer](../general/computer.md) before it stops working. In addition it also provides basic graphical capabilities.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/arrowkeys.md b/src/main/resources/assets/opencomputers/doc/en_us/item/arrowkeys.md
index 8357b596c5..9d46464710 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/arrowkeys.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/arrowkeys.md
@@ -1,5 +1,5 @@
# Arrow Keys
-
+
At the risk of repeating myself: it's a button sink. Because the button economy has seen some serious inflation in recent years. It is used as a component for building [keyboards](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/batteryupgrade1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/batteryupgrade1.md
index d1c06b34c5..c7ea13cd9b 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/batteryupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/batteryupgrade1.md
@@ -1,5 +1,5 @@
# Battery Ugrade
-
+
This upgrade increases the internal energy buffer of devices, such as [robots](../block/robot.md) and [tablets](tablet.md), allowing them to operate longer without having to return to a [charger](../block/charger.md). Higher tier battery upgrades can store more energy.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/buttongroup.md b/src/main/resources/assets/opencomputers/doc/en_us/item/buttongroup.md
index 373d7cdc3b..1080f7f8fa 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/buttongroup.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/buttongroup.md
@@ -1,5 +1,5 @@
# Button Group
-
+
Because you *always* have too many buttons lying around somewhere. Don't lie. We all shift-click that button recipe time and again. Button groups are used to build [keyboards](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/card.md b/src/main/resources/assets/opencomputers/doc/en_us/item/card.md
index 55c5021b7a..d8479bcd9d 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/card.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/card.md
@@ -1,5 +1,5 @@
# Card
-
+
Common crafting material for card components in OpenComputers (such as [graphics cards](graphicsCard1.md), [network cards](lanCard.md), etc).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/cardcontainer1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/cardcontainer1.md
index 64698c7df8..519e17b88e 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/cardcontainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/cardcontainer1.md
@@ -1,5 +1,5 @@
# Card Container
-
+
The card container is a container upgrade for [robots](../block/robot.md) allowing cards to be inserted/removed to/from [robots](../block/robot.md) on-the-fly. The maximum tier of card that the slot can hold is equal to the tier of the container. Unlike normal upgrades, the complexity of containers is twice their tier. See [here](../block/robot.md) for details on robot complexity.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/chamelium.md b/src/main/resources/assets/opencomputers/doc/en_us/item/chamelium.md
index 18fabca864..7c2eb60c68 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/chamelium.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/chamelium.md
@@ -1,6 +1,6 @@
# Chamelium
-
+
Chamelium is a shape-shifting material that is used when creating [3D prints](../block/print.md) in a [3D printer](../block/printer.md). On its own, it is featureless and therefore very useful for creating simple, plain and monochrome areas.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/chip1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/chip1.md
index 945b9a8d82..bb4d72cdf4 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/chip1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/chip1.md
@@ -1,5 +1,5 @@
# Microchips
-
+
Microchips are the bread and butter of electronic component crafting. They come in different tiers, for crafting different tiers of components.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/chunkloaderupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/chunkloaderupgrade.md
index 7f7e8210bc..dbbafe00c6 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/chunkloaderupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/chunkloaderupgrade.md
@@ -1,6 +1,6 @@
# Chunk Loader Upgrade
-
+
The chunk loader upgrade can be installed in devices (such as [robots](../block/robot.md) and [microcontrollers](../block/microcontroller.md)) to allow them to keep the chunk they are in - as well as the surrounding chunks - loaded. This consumes energy, however. The chunk loader can be turned on and off using the component API exposed to the device.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/circuitboard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/circuitboard.md
index 28ad8ecf7f..e2f0493d60 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/circuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/circuitboard.md
@@ -1,5 +1,5 @@
# Circuit Board
-
+
Intermediate crafting item made from [raw circuit boards](rawCircuitBoard.md) and used to make [printed circuit boards](printedCircuitBoard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/componentbus1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/componentbus1.md
index b6d2990e30..622cf9079e 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/componentbus1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/componentbus1.md
@@ -1,6 +1,6 @@
# Component Bus
-
+
A component bus is a [server](server1.md)-specific upgrade that allows the [server](server1.md) to communicate with more components at the same time, without shutting down. Like with [CPUs](cpu1.md), higher tier buses provide higher component limits. Higher tier [servers](server1.md) are also capable of taking more component buses, allowing for communication with many more components.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/controlunit.md b/src/main/resources/assets/opencomputers/doc/en_us/item/controlunit.md
index 8935aeb967..493a6eeee3 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/controlunit.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/controlunit.md
@@ -1,5 +1,5 @@
# Control Unit
-
+
Higher tier crafting item used in more advanced circuitry, such as [CPUs](cpu1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/cpu1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/cpu1.md
index 7ff2673948..4fc4547181 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/cpu1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/cpu1.md
@@ -1,6 +1,6 @@
# CPU
-
+
The central processing unit is a core part for each [computer](../general/computer.md) or [server](server1.md). It defines the architecture of the [computer](../general/computer.md), and the number of components that can be connected to the [computer](../general/computer.md) before it stops working. Higher tier CPUs also provide a higher per-tick direct call limit to the [computer](../general/computer.md) - in simpler terms: better CPUs run faster.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/craftingupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/craftingupgrade.md
index 43320ee5ea..2d726ab3f4 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/craftingupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/craftingupgrade.md
@@ -1,5 +1,5 @@
# Crafting Upgrade
-
+
The crafting upgrade allows [robots](../block/robot.md) to craft shaped and shapeless recipes using items in their [inventory](../item/inventoryUpgrade.md). When crafting, the top-left 3x3 grid in the [robot](../block/robot.md)'s [inventory](../item/inventoryUpgrade.md) is used as the crafting grid. Items have to be arranged according to the recipe. Results will be placed back into the [robot](../block/robot.md)'s [inventory](../item/inventoryUpgrade.md). As with picking up items, the result will be placed into the selected slot; failing to do so will place the item in the next available empty slot. If no inventory space remains, the result will be dropped into the world.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/cuttingwire.md b/src/main/resources/assets/opencomputers/doc/en_us/item/cuttingwire.md
index 8f532bc68e..12942c96e5 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/cuttingwire.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/cuttingwire.md
@@ -1,5 +1,5 @@
# Cutting Wire
-
+
An item encountered when using hard-mode recipes, it is used for crafting [raw circuit boards](rawCircuitBoard.md). Very inefficiently.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/databaseupgrade1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/databaseupgrade1.md
index ff4b4cfd5c..b1b1d7228c 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/databaseupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/databaseupgrade1.md
@@ -1,6 +1,6 @@
# Database Upgrade
-
+
The database upgrade can be configured to store a list of item stack representations, which can then be used by other components. This is particularly useful for items that are differentiated purely based on their NBT data, which is not part of the item stack descriptor returned by callbacks.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/datacard1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/datacard1.md
index de4e1798bd..6888647813 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/datacard1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/datacard1.md
@@ -1,6 +1,6 @@
# Data Card
-
+
The data card is a utility card that provides a couple of algorithms which would be either hard to implement on an architecture, or run relatively slowly on them. It provides hashing functionalities, as well as basic inflate/deflate. Additionally it comes with an embedded file system that provides a number of programs using the functionality provided by the card, similar to the internet card.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/debugcard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/debugcard.md
index aa35df5a79..ee40ba57b1 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/debugcard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/debugcard.md
@@ -1,6 +1,6 @@
# Debug Card
-
+
The debug card is a creative-only item that was originally only intended to make debugging things easier, by automating some processes. It has since gotten a bunch more functionality, making it quite useful for custom map-making.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/disk.md b/src/main/resources/assets/opencomputers/doc/en_us/item/disk.md
index 55a6e9c13d..c99793fc9b 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/disk.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/disk.md
@@ -1,5 +1,5 @@
# Disc
-
+
Basic crafting component used in crafting storage media such as [floppies](floppy.md) and [hard drives](hdd1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/diskdrivemountable.md b/src/main/resources/assets/opencomputers/doc/en_us/item/diskdrivemountable.md
index eecb3e7c5f..d5cf0f3165 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/diskdrivemountable.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/diskdrivemountable.md
@@ -1,5 +1,5 @@
# Mountable Disk Drive
-
+
This device is functionally equivalent to a regular [disk drive](../block/diskDrive.md), except that it is installed in a [rack](../block/rack.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/drone.md b/src/main/resources/assets/opencomputers/doc/en_us/item/drone.md
index e639c1982a..981f6cbd35 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/drone.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/drone.md
@@ -1,5 +1,5 @@
# Drone
-
+
Drones are built using a [drone case](droneCase1.md) in the [assembler](../block/assembler.md). They are entity-based [robots](../block/robot.md), a little cheaper with limited functionality. They are also capable of moving differently and much quicker than [robots](../block/robot.md), and are usually controlled using a client program on a [computer](../general/computer.md). The drone will need a configured [EEPROM](eeprom.md) to listen for commands to be executed or act on its own.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/dronecase1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/dronecase1.md
index 3cb50e9f7f..661e889059 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/dronecase1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/dronecase1.md
@@ -1,6 +1,6 @@
# Drone Case
-
+
The drone case is used to build [drones](drone.md) in the [assembler](../block/assembler.md). [Drones](drone.md) are light-weight, fast and very mobile machines with limited functionality (fewer upgrade and component slots available). Unlike [robots](../block/robot.md) they cannot use tools, and can interact with the world only in a relatively limited manner.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/eeprom.md b/src/main/resources/assets/opencomputers/doc/en_us/item/eeprom.md
index e4019afbbf..583dbdafd7 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/eeprom.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/eeprom.md
@@ -1,6 +1,6 @@
# EEPROM
-
+
The EEPROM is what contains the code used to initialize a computer when it is being booted. This data is stored as a plain byte array, and may mean different things to different [CPU](cpu1.md) architectures. For example, for Lua it is usually a small script that searches for file systems with an init script, for other architectures it may be actual machine code.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/experienceupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/experienceupgrade.md
index 5112fee915..6b9082770e 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/experienceupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/experienceupgrade.md
@@ -1,6 +1,6 @@
# Experience Upgrade
-
+
The experience upgrade is a very special upgrade, as it allows [robots](../block/robot.md) and [drones](drone.md) to collect experience by performing various actions, such as digging up ores and killing entities. A single upgrade can store up to 30 levels, providing passive bonuses with each level, including faster harvest speeds and increased energy buffer capacity.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/floppy.md b/src/main/resources/assets/opencomputers/doc/en_us/item/floppy.md
index ae60719558..d41d980e63 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/floppy.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/floppy.md
@@ -1,5 +1,5 @@
# Floppy Disk
-
+
The floppy disk is the cheapest and smallest type of storage medium in OpenComputers. It is a handy early-game way of storing data and transferring it between [computers](../general/computer.md) and [robots](../block/robot.md). You may also find floppy disks with useful programs on them in dungeon chests (OpenPrograms Package Manager is a good example, allowing easy install of programs from a central GitHub repository).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/generatorupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/generatorupgrade.md
index 27c5dca641..0d402d8a8e 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/generatorupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/generatorupgrade.md
@@ -1,6 +1,6 @@
# Generator Upgrade
-
+
The generator upgrade allows devices to re-fuel on the go. Currently it only supports solid fuels, such as coal. It has an internal inventory that can store one item stack of fuel. Surplus fuel can be removed from the generator using the appropriate component API method. When removing a generator upgrade from a [robot](../block/robot.md), its contents will be dropped into the world.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/graphicscard1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/graphicscard1.md
index e72fc5c6c0..b9174280a3 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/graphicscard1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/graphicscard1.md
@@ -1,6 +1,6 @@
# Graphics Card
-
+
The graphics card is an essential part for most [computers](../general/computer.md) and allows the [computer](../general/computer.md) to display text on a connected [screen](../block/screen1.md). Graphics cards come in several tiers, and like [screens](../block/screen1.md), support different resolutions and color depths.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/hdd1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/hdd1.md
index c873304a48..3693e08691 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/hdd1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/hdd1.md
@@ -1,5 +1,5 @@
# Hard Disk Drive
-
+
The hard disk drives are a higher tier storage medium in OpenComputers. All storage media perform at the same speed; higher tier storage provides more space. There are also some devices that can only use disk drives (although servers could use an external [disk drive](../block/diskDrive.md), for example). Hard drives can be placed inside a [raid](../block/raid.md), allowing multiple drives to share the same file system. Note that placing a hard drive in a [raid](../block/raid.md) wipes the drive of its contents.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/hoverboots.md b/src/main/resources/assets/opencomputers/doc/en_us/item/hoverboots.md
index 8ff8a375d5..ff600be336 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/hoverboots.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/hoverboots.md
@@ -1,6 +1,6 @@
# Hover Boots
-
+
If you can't be bothered to program [drones](drone.md), here's an alternative use for them: stepping stones! Or glorified inline skates. Something like that.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/hoverupgrade1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/hoverupgrade1.md
index 5406e23dda..a5a9bfdb82 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/hoverupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/hoverupgrade1.md
@@ -1,6 +1,6 @@
# Hover Upgrade
-
+
The hover upgrade allows [robots](../block/robot.md) to fly much higher above the ground than they normally could. Unlike [drones](drone.md), they are by default limited to a flight height of 8. This is usually not a big problem, because they can still move up or along walls. Their general movement rules can be summarized like this:
- Robots may only move if the start or target position is valid (e.g. to allow building bridges).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/inkcartridge.md b/src/main/resources/assets/opencomputers/doc/en_us/item/inkcartridge.md
index 14ae30e03c..574e3db117 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/inkcartridge.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/inkcartridge.md
@@ -1,5 +1,5 @@
# Ink Cartridge
-
+
Ink cartridges come in handy when refilling the color buffer of [3D printers](../block/printer.md). While it is also possible to refill them using dyes directly, this is messy and very inefficient. It is strongly recommended to invest into a real OC Ink Cartridge (TM), today! (Disclaimer: they may or may cost more than the printer itself).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/internetcard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/internetcard.md
index fa80e6d7f9..33190a8a40 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/internetcard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/internetcard.md
@@ -1,6 +1,6 @@
# Internet Card
-
+
The internet card grants [computers](../general/computer.md) access to the internet. It provides ways to perform simple HTTP requests, as well as to open plain TCP client sockets that can be read and written to.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/interweb.md b/src/main/resources/assets/opencomputers/doc/en_us/item/interweb.md
index 91520ca79b..8d482a060f 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/interweb.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/interweb.md
@@ -1,5 +1,5 @@
# Interweb
-
+
The interweb is a basic component for all things related to long distance communication. It uses the strange mechanics of all things End to allow something along the lines of quantum communication. Used most notably in [internet cards](internetCard.md) and [linked cards](linkedCard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/inventorycontrollerupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/inventorycontrollerupgrade.md
index 8cad6000e1..8cddea326d 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/inventorycontrollerupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/inventorycontrollerupgrade.md
@@ -1,6 +1,6 @@
# Inventory Controller
-
+
The inventory controller upgrade provides extended inventory interaction to [robots](../block/robot.md) and [drones](drone.md). It allows the device to explicitly target slots in external inventories when dropping or sucking items. It also allows devices to read detailed information about item stacks. Lastly it provides [robots](../block/robot.md) with a means to change their equipped tool without external help.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/inventoryupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/inventoryupgrade.md
index a451f184c7..a7d18f7dd8 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/inventoryupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/inventoryupgrade.md
@@ -1,6 +1,6 @@
# Inventory Upgrade
-
+
The inventory upgrade provides inventory slots to [robots](../block/robot.md) and [drones](drone.md). For each inventory upgrade a [robot](../block/robot.md) will gain an addition 16 inventory slots, up to a maximum of 64 slots in total; a [drone](drone.md) will gain 4 slots per upgrade, up to a total of 8 slots.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/lancard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/lancard.md
index fc730e0359..d14fa8039e 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/lancard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/lancard.md
@@ -1,5 +1,5 @@
# Network Card
-
+
The network card allows [computers](../general/computer.md) to send and receive network messages. Messages (or packets) can be broadcasted to all receiving nodes in a subnetwork, or sent to a specific node with a specified address. [Relays](../block/relay.md) can be used to bridge multiple subnetworks by relaying messages between the subnetworks they are connected to. It is also possible to send a targeted message if the receiver is in another subnetwork, if the networks are connected via one or more [relays](../block/relay.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/leashupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/leashupgrade.md
index 0f2914abc6..8f745a7cbe 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/leashupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/leashupgrade.md
@@ -1,5 +1,5 @@
# Leash Upgrade
-
+
The Leash upgrade allows putting animals on a leash, bound to the entity that hosts the device the component is used by, for example [drones](drone.md). Using this upgrade, multiple animals can be leashed at the same time, which makes this quite useful for moving herds.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/linkedcard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/linkedcard.md
index ec3dc820c7..1ea92aab6c 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/linkedcard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/linkedcard.md
@@ -1,5 +1,5 @@
# Linked Card
-
+
The linked card is a specialized but advanced version of a [network card](lanCard.md). It can only operate in pairs, providing a point-to-point communication between the paired cards. Linked cards can communicate over large (unlimited) distances and across dimensions.
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/manual.md b/src/main/resources/assets/opencomputers/doc/en_us/item/manual.md
index b8b7323c22..22aa2f3584 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/manual.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/manual.md
@@ -1,6 +1,6 @@
# Manual
-
+
The thing you're reading right now! The manual contains a wealth of information about OpenComputers (and possibly more). If you need information on an item or block in the mod, look no further! Scroll down to learn how to use (mouse wheel or the scroll bar to the right).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/mfu.md b/src/main/resources/assets/opencomputers/doc/en_us/item/mfu.md
index e288f6653b..6b03de96b7 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/mfu.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/mfu.md
@@ -1,6 +1,6 @@
# MFU
-
+
This upgrade acts as a remote [adapter](../block/adapter.md). Click while sneaking onto any side of any block to bind it to a specific position. Then, place it into an adapter nearby (the range is very limited) and it will act as if the adapter was placed right next to the specific side you bound it to!
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/microcontrollercase1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/microcontrollercase1.md
index 92045902be..f029e76db4 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/microcontrollercase1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/microcontrollercase1.md
@@ -1,6 +1,6 @@
# Microcontroller Case
-
+
The Microcontroller case is the base part when building [microcontrollers](../block/microcontroller.md) in the [assembler](../block/assembler.md). [Microcontrollers](../block/microcontroller.md) are very primitive [computers](../general/computer.md). They may only contain a very limited number of components, and are intended to be used in very specific use-cases, such as transforming or reacting to redstone signals, or processing network messages.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/nanomachines.md b/src/main/resources/assets/opencomputers/doc/en_us/item/nanomachines.md
index aa1f48ce76..4130f339ab 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/nanomachines.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/nanomachines.md
@@ -1,6 +1,6 @@
# Nanomachines
-
+
These little guys interface with your nervous system to make you harder, better, faster, stronger, or kill you. Sometimes both at the same time! Put simply, nanomachines provide a power driven system for applying buffs (and debuffs) to the player they reside in. To "install" nanomachines, eat them!
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/navigationupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/navigationupgrade.md
index 4ce1d4ef5d..63f3ef0636 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/navigationupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/navigationupgrade.md
@@ -1,6 +1,6 @@
# Navigation Upgrade
-
+
The navigation upgrade provides location and orientation information to devices it is installed in. The coordinates the upgrade provides are relative to the center of the map that was used to craft the upgrade, and the functional range is based on the size of that map.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/numpad.md b/src/main/resources/assets/opencomputers/doc/en_us/item/numpad.md
index 05ff6ade73..4eaf74dd19 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/numpad.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/numpad.md
@@ -1,5 +1,5 @@
# Numeric Keypad
-
+
The Numeric keypad is part of every [keyboard](../block/keyboard.md). It allows you to enter numbers.
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/pistonupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/pistonupgrade.md
index 85c62dd44b..c12ea3f1c3 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/pistonupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/pistonupgrade.md
@@ -1,6 +1,6 @@
# Piston Upgrade
-
+
The piston upgrade allows some devices to act very much like a vanilla piston. When installed, a component with a single method, `push()`, becomes available. When called the device will then try to push the block in its forward facing direction. For [robots](../block/robot.md) and [microcontrollers](../block/microcontroller.md), this is the front face; for [tablets](tablet.md), it will use the player's facing direction.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/printedcircuitboard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/printedcircuitboard.md
index fdd266165b..53eda41e34 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/printedcircuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/printedcircuitboard.md
@@ -1,5 +1,5 @@
# Printed Circuit Board
-
+
The printed circuit board is, next to the [transistor](transistor.md), one of the most basic crafting materials in OpenComputers. It is used as a basis for many components, such as [cards](card.md) and a large number of [blocks](../block/index.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/ram1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/ram1.md
index cd54adc4eb..9636b4ea1f 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/ram1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/ram1.md
@@ -1,6 +1,6 @@
# Memory
-
+
Memory is, like the [CPU](cpu1.md), an essential part in all [computers](../general/computer.md). Depending on the [CPU](cpu1.md)'s architecture, the memory has a very essential effect on what a [computer](../general/computer.md) can and cannot do. For the standard Lua architecture, for example, it controls the actual amount of memory Lua scripts can use. This means that to run larger and more memory-intensive programs, you will need more memory.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/rawcircuitboard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/rawcircuitboard.md
index ac00250eab..0366c08be5 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/rawcircuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/rawcircuitboard.md
@@ -1,5 +1,5 @@
# Raw Circuit Board
-
+
Intermediary crafting material, used for crafting [circuit boards](circuitBoard.md) (or [printed circuit boards](printedCircuitBoard.md), depending on the recipe set being used).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/redstonecard1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/redstonecard1.md
index 2110c6b84f..7b6067383f 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/redstonecard1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/redstonecard1.md
@@ -1,6 +1,6 @@
# Redstone Card
-
+
The redstone card allows [computers](../general/computer.md) to read and emit analog redstone signal in adjacent blocks. When an incoming signal strength changes, a signal is injected into the [computer](../general/computer.md).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/server1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/server1.md
index 00c3544753..be7aafb537 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/server1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/server1.md
@@ -1,6 +1,6 @@
# Server
-
+
Servers are a form of higher tier [computer](../general/computer.md). They can be configured by holding them in the hand and using them - like opening a backpack or Ender pouch, for example. Servers can also be configured after having been installed into a [rack](../block/rack.md) by activating them (aiming at the corresponding position on the front face on the [rack](../block/rack.md)). To operate, the server has to be placed inside a [rack](../block/rack.md). For more information see the [rack](../block/rack.md) entry.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/signupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/signupgrade.md
index 944bd24b64..7fdb9944b1 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/signupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/signupgrade.md
@@ -1,5 +1,5 @@
# Sign I/O
-
+
This upgrade allows devices to interact with signs in the world. It allows reading the current message on the sign as well as changing the message on the sign (if permitted.
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/solargeneratorupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/solargeneratorupgrade.md
index 6740d5e693..c382e71479 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/solargeneratorupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/solargeneratorupgrade.md
@@ -1,6 +1,6 @@
# Solar Generator
-
+
The solar generator upgrade can be installed in devices such as [robots](../block/robot.md), [drones](drone.md) and [tablets](tablet.md) to passively generate energy. It will only work while the device is exposed to direct sunlight; a device in an enclosed area or an area affected by weather will not generate energy.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/stickypistonupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/stickypistonupgrade.md
index 318622ad3e..c1edfea4e7 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/stickypistonupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/stickypistonupgrade.md
@@ -1,6 +1,6 @@
# Sticky Piston Upgrade
-
+
The sticky piston upgrade is an upgrade to the [Piston Upgrade](pistonupgrade.md) which allows some devices to act very much like a vanilla sticky piston. When installed, a piston component becomes available. Its methods are `push()` and `pull()`. When these are called the device will act like a vanilla sticky piston and try to push or pull the block in its forward facing direction. For [robots](../block/robot.md) and [microcontrollers](../block/microcontroller.md), this is the front face; for [tablets](tablet.md), it will use the player's facing direction.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/tablet.md b/src/main/resources/assets/opencomputers/doc/en_us/item/tablet.md
index eab94a8166..3d66013e9c 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/tablet.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/tablet.md
@@ -1,6 +1,6 @@
# Tablet
-
+
Tablets are built by placing a [tablet case](tabletCase1.md) into an [assembler](../block/assembler.md), configuring as desired and assembling it. Tablets act as portable computers that cannot directly interact with the world - for example, basic [redstone cards](redstoneCard1.md) do not work in them. A number of upgrades do, such as the [sign i/o](signUpgrade.md) upgrade or the [piston](pistonUpgrade.md) upgrade.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/tabletcase1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/tabletcase1.md
index 923c02aac4..3ee4513c20 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/tabletcase1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/tabletcase1.md
@@ -1,6 +1,6 @@
# Tablet Case
-
+
The tablet case is the base part when building [tablets](tablet.md) in the [assembler](../block/assembler.md). [Tablets](tablet.md) are very compact and portable [computers](../general/computer.md). They can host a small number of select upgrades, but cannot interact with the world like [computer cases](../block/case1.md) can (using simple [network cards](lanCard.md) or [redstone cards](redstoneCard1.md) for example).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/tankcontrollerupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/tankcontrollerupgrade.md
index 57bbda9b72..0de4182bb6 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/tankcontrollerupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/tankcontrollerupgrade.md
@@ -1,6 +1,6 @@
# Tank Controller
-
+
The tank controller upgrade is to fluid tanks what the [inventory controller upgrade](inventoryControllerUpgrade.md) is to normal inventories. It allows devices to query more detailed information about tanks inside and next to them.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/tankupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/tankupgrade.md
index 23745e61a0..f83b74e3c9 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/tankupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/tankupgrade.md
@@ -1,5 +1,5 @@
# Tank Upgrade
-
+
The tank upgrade allows devices to store fluids. Each tank can only hold a single type of fluid, and provides a volume of 16 buckets (16000mB). [Robots](../block/robot.md) and [drones](drone.md) can drain liquids from the world and from other fluid tanks, and can fill the fluids back into fluid tanks, and when supported by the fluid, place them back into the world. There is no limit to the number of tanks that can be installed in a device.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/terminal.md b/src/main/resources/assets/opencomputers/doc/en_us/item/terminal.md
index 8091c1dd18..f6b6247705 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/terminal.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/terminal.md
@@ -1,6 +1,6 @@
# Remote Terminal
-
+
The remote terminal can be used to remotely control computers via [terminal servers](terminalServer.md). To use it, activate a [terminal server](terminalServer.md) that is installed in a [rack](../block/rack.md) (click on the [rack](../block/rack.md) block in the world, targeting the [terminal server](terminalServer.md) to bind the terminal to).
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/terminalserver.md b/src/main/resources/assets/opencomputers/doc/en_us/item/terminalserver.md
index 53cedf2e32..f009b00145 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/terminalserver.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/terminalserver.md
@@ -1,5 +1,5 @@
# Terminal Server
-
+
Terminal servers provides a virtual [screen](../block/screen1.md) and [keyboard](../block/keyboard.md) which can be controlled via [remote terminals](terminal.md). See the [remote terminal](terminal.md) manual entry for more information. Terminal servers must be installed in a [rack](../block/rack.md) to function.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/texturepicker.md b/src/main/resources/assets/opencomputers/doc/en_us/item/texturepicker.md
index 9a3e183fbd..1297d3d2e1 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/texturepicker.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/texturepicker.md
@@ -1,6 +1,6 @@
# Texture Picker
-
+
The texture picker is very useful when making models for your [3D printer](../block/printer.md). It allows getting the texture name of textures used by blocks in the world, simply by (sneak-)activating them with the tool. Disclaimer: for blocks that use special rendering, such as chests, this may not work.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/tractorbeamupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/tractorbeamupgrade.md
index ea1535f2e8..98329e081f 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/tractorbeamupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/tractorbeamupgrade.md
@@ -1,5 +1,5 @@
# Tractor Beam
-
+
The tractor beam upgrade allows devices to pick up items in a three block radius around them. This can be highly useful when using [robots](../block/robot.md) in tree or other farms, or when having them use tools that break multiple blocks around them (such as Tinker's Construct tools). Each operation will try to suck a single item stack in range and consume some energy.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/tradingupgrade.md b/src/main/resources/assets/opencomputers/doc/en_us/item/tradingupgrade.md
index 8a599707cb..2671d4c439 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/tradingupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/tradingupgrade.md
@@ -1,5 +1,5 @@
# Trading Upgrade
-
+
The trading upgrade enables automatic trading with merchants, such as villagers. It can be used in agents such as [robots](../block/robot.md) and [drones](drone.md) and provides capabilities to identify available trades from nearby merchants, retrieve information on individual trade offers, and finally for performing trades.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/transistor.md b/src/main/resources/assets/opencomputers/doc/en_us/item/transistor.md
index edef8d4b9e..8d3e75f42b 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/transistor.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/transistor.md
@@ -1,5 +1,5 @@
# Transistor
-
+
The transistor is one of the most basic crafting ingredients in OpenComputers. It is mainly used to craft [microchips](chip1.md) and other electronic goodies.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/upgradecontainer1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/upgradecontainer1.md
index 2a704973ad..dd847a1916 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/upgradecontainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/upgradecontainer1.md
@@ -1,5 +1,5 @@
# Upgrade Container
-
+
The upgrade container is a container type upgrade for [robots](../block/robot.md), that provides a slot in the finished [robots](../block/robot.md) into which normal upgrades can be placed. The maximum tier of upgrade that slot can hold is equal to the tier of the container. Unlike normal upgrades, the complexity of containers is twice their tier. Refer to [robot](../block/robot.md) and [assembler](../block/assembler.md) documentation on complexity.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/wlancard1.md b/src/main/resources/assets/opencomputers/doc/en_us/item/wlancard1.md
index c6b69aed85..669547f0db 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/wlancard1.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/wlancard1.md
@@ -1,6 +1,6 @@
# WLAN Card
-
+
The wireless network card is an upgraded [network card](lanCard.md) that can send and receive wireless network messages. Tier two cards can also send and receive wired messages. The signal strength directly controls the distance up to which a sent message can be received, where the strength is equal to the distance in blocks.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/worldsensorcard.md b/src/main/resources/assets/opencomputers/doc/en_us/item/worldsensorcard.md
index 168d1e93d6..b101dd009a 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/worldsensorcard.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/worldsensorcard.md
@@ -1,5 +1,5 @@
# World Sensor Card
-
+
The world sensor card allows reading of atmospheric information as well as gravity on different planets added by Galacticraft. This can be useful for [robots](../block/robot.md) or [drones](drone.md) operating in space.
diff --git a/src/main/resources/assets/opencomputers/doc/en_us/item/wrench.md b/src/main/resources/assets/opencomputers/doc/en_us/item/wrench.md
index b26d7922e5..696c1cf4bc 100644
--- a/src/main/resources/assets/opencomputers/doc/en_us/item/wrench.md
+++ b/src/main/resources/assets/opencomputers/doc/en_us/item/wrench.md
@@ -1,5 +1,5 @@
# Scrench
-
+
Like pretty much any other technology-focused mod, OpenComputers has it's own version of a wrench tool. In this case, it is a hybrid of a screwdriver and a wrench, that looks like it's incredibly awkward to use. It can be used to rotate most blocks, and is also compatible with most other mods' blocks that can be interacted with by using wrench-like tools.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/accessPoint.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/accessPoint.md
index cda879aa04..a53c9bb19c 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/accessPoint.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/accessPoint.md
@@ -1,6 +1,6 @@
# Point d'accès
-
+
*Ce bloc est déprécié et sera retiré dans une version future.* Transformez les en [relai](relay.md) pour éviter de les perdre.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/adapter.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/adapter.md
index e451559f6d..c3614096fb 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/adapter.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/adapter.md
@@ -1,6 +1,6 @@
# Adaptateur
-
+
L'adaptateur permet aux [ordinateurs](../general/computer.md) d'interagir avec des blocs de Minecraft Vanilla ou d'autres mods. Les blocs supportés placés contre l'adaptateur s'afficheront en tant que composants sur les [ordinateurs](../general/computer.md) connectés à l'adaptateur.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/assembler.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/assembler.md
index fe84927051..7662f7d703 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/assembler.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/assembler.md
@@ -1,6 +1,6 @@
# Assembleur électronique
-
+
L'assembleur est une table avancée qui peut être utilisée pour construire des appareils électroniques plus complexes, comme les [robots](robot.md), les [drones](../item/drone.md) et les [tablettes](../item/tablet.md). Il nécessite une grande quantité d'énergie pour assembler des appareils, il est donc recommandé de lui fournir suffisament d'énergie avec un [capaciteur](capacitor.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/cable.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/cable.md
index 573434e902..1753f9cd55 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/cable.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/cable.md
@@ -1,6 +1,6 @@
# Câble
-
+
Le câble à connecter des [ordinateurs](../general/computer.md) et des machines éloignés les uns des autres. Si vous avez un système compact où tous les composants sont en contact (directement ou indirectement, la plupart des blocs du mod se comportent également de la même manière que les câbles), vous n'aurez généralement pas besoin de câbles.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/capacitor.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/capacitor.md
index 5304cc37b0..1af8e18174 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/capacitor.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/capacitor.md
@@ -1,6 +1,6 @@
# Capaciteur
-
+
Le capaciteur emmagasine de l'énergie qui sera utilisée par le réseau, en se comportant comme un tampon d'énergie au besoin. Contrairement à la conversion de l'énergie d'autres mods vers l'énergie interne à OpenComputers (en utilisant un [convertisseur énergétique](powerConverter.md) par exemple), le transfert d'énergie dans un sous-réseau est instantané. Posséder un tampon d'énergie interne sera utile pour des tâches qui nécessitent beaucoup d'énergie, comme l'[assemblage](assembler.md) et/ou la [charge](charger.md) d'appareils comme les [robots](robot.md) ou les [drones](../item/drone.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/case1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/case1.md
index d76af8b20f..0221c16ade 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/case1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/case1.md
@@ -1,6 +1,6 @@
# Boîtier d'ordinateur
-
+
Les boîtiers d'ordinateur existent en 3 niveaux différents, ce qui limite les composants qui peuvent y être insérés. Un niveau supplémentaire existe aussi, seulement pour le mode créatif. Les boîtiers d'ordinateur peuvent également être placés dans un [assembleur électronique](assembler.md) pour construire des [robots](robot.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/chameliumBlock.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/chameliumBlock.md
index e437c066eb..73bf1ed82b 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/chameliumBlock.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/chameliumBlock.md
@@ -1,6 +1,6 @@
# Bloc de Chamélium
-
+
Quelques morceaux de [chamélium](../item/chamelium.md) peuvent être combinés pour fournir un bloc monochrome à des fins décoratives. Les blocs de chamélium peuvent aussi être teintés avec n'importe laquelle des 16 couleurs de Minecraft.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/charger.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/charger.md
index 824302c285..e3580c106e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/charger.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/charger.md
@@ -1,6 +1,6 @@
# Chargeur
-
+
Le chargeur est utilisé pour charger des appareils comme les [robots](robot.md), les [drones](../item/drone.md) et les [tablettes](../item/tablet.md). Un chargeur doit être activé en lui appliquant un signal de redstone. La vitesse de charge est basée sur la force du signal de redstone appliqué, avec une force de 15 donnant une vitesse de charge de 100%.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/disassembler.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/disassembler.md
index 8273de5f46..2fdcaeeb8b 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/disassembler.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/disassembler.md
@@ -1,6 +1,6 @@
# Désassembleur
-
+
Le désassembleur peut être utilisé pour déconstruire la plupart des objets d'OpenComputers en leurs éléments d'origine. C'est particulièrement utile pour récupérer des matériaux à partir d'anciens éléments qui ne sont plus utiles, ou pour déconstruire des appareils qui ne sont plus nécessaire ou qui ont été mal montés (ex : un [robot](robot.md) sans [système d'exploitation](../general/openOS.md)).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/diskDrive.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/diskDrive.md
index e369473cce..53df9ef779 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/diskDrive.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/diskDrive.md
@@ -1,6 +1,6 @@
# Lecteur de disquettes
-
+
Le lecteur de disquettes peut être utilisé pour lire des [disquettes](../item/floppy.md) en se servant d'un [ordinateur](../general/computer.md) connecté au lecteur de disquette. C'est très utile pour démarrer, car les niveaux les plus inférieurs de [boîtier d'ordinateur](case1.md) n'ont pas d'emplacement pour disquettes pré-construit, et vous aurez besoin d'un système d'exploitation pour démarrer l'[ordinateur](../general/computer.md). Un disque d'[OpenOS](../general/openOS.md) peut être fabriqué en utilisant une [disquette](../item/floppy.md) vierge et un [manuel](../item/manual.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/geolyzer.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/geolyzer.md
index b4cb8067bb..45edb2d187 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/geolyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/geolyzer.md
@@ -1,6 +1,6 @@
# Géolyseur
-
+
Le géolyseur peut être utilisé par les [ordinateurs](../general/computer.md) pour scanner le terrain autour du géolyseur par la dureté approximative des blocs. Cela peut être utile pour générer des cartes du terrain à afficher sur un [projecteur d'hologramme](hologram1.md) ou pour détecter des blocs potentiellement précieux (les minerais sont généralement plus durs que la terre et la pierre). Les résultats du scan du géolyseur ont une certaine quantité de bruit ajoutée; en théorie, de nombreux scans peuvent être effectués pour obtenir une meilleure lecture du niveau de dureté d'un bloc.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/hologram1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/hologram1.md
index 482d069853..e78309301a 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/hologram1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/hologram1.md
@@ -1,6 +1,6 @@
# Projecteur d'hologramme
-
+
Le projecteur d'hologramme est un afficheur volumétrique, c'est à dire qu'il fournit un tableau de voxels en trois dimensions qui peuvent être contrôlés individuellement par un [ordinateur](../general/computer.md) auquel il serait connecté. Le deuxième niveau de projecteur, même s'il a la même résolution que le projecteur de niveau 1, gère l'affichage de chaque voxel avec trois couleurs définissable par l'utilisateur.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/keyboard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/keyboard.md
index b587ed71ea..c9ca8b535d 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/keyboard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/keyboard.md
@@ -1,6 +1,6 @@
# Clavier
-
+
Un clavier est requis pour saisir du texte sur l'[écran](screen1.md), qu'ils existent physiquement dans le monde ou intégrés à un appareil comme un [robot](robot.md) ou une [tablette](../item/tablet.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/motionSensor.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/motionSensor.md
index 21cbacb66f..544fbbf5df 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/motionSensor.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/motionSensor.md
@@ -1,6 +1,6 @@
# Détecteur de mouvement
-
+
Le détecteur de mouvement permet aux [ordinateurs](../general/computer.md) de détecter le mouvement des entités vivantes. Si une entité se déplace plus vite qu'un seuil défini, un signal sera injecté dans les [ordinateurs](../general/computer.md) connectés au détecteur de mouvement. Le seuil peut être configuré en utilisant l'API des composants que le détecteur de mouvement expose aux ordinateurs connectés.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/netSplitter.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/netSplitter.md
index 0b395c0142..7b71c9435e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/netSplitter.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/netSplitter.md
@@ -1,6 +1,6 @@
# Répartiteur réseau
-
+
Le répartiteur réseau est un appareil qui permet de contrôler la connectivité entre des sous-réseaux. A la différence du [relai](relay.md) ou du [convertisseur énergétique](powerConverter.md), il connecte directement entre eux des sous-réseaux voisins, c'est à dire qu'il est possible d'accéder aux composants des sous-réseaux. La connectivité de chaque face peut être activée en utilisant une clé (ex: le [crisseur](../item/wrench.md)). Quand un signal de redstone est appliqué au répartiteur réseau, la connectivité de toutes les faces est inversée.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerConverter.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerConverter.md
index 91592a8638..fc6a583c6e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerConverter.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerConverter.md
@@ -1,5 +1,5 @@
# Convertisseur énergétique
-
+
Le convertisseur énergétique est la manière la plus rapide de convertir de l'énergie provenant d'autres mods en énergie interne à OpenComputers. Si vous utilisez un seul ordinateur, vous n'aurez probablement pas besoin de convertisseur. Si vous avez un grand groupe de capaciteurs dont vous utilisez l'énergie de temps en temps, vous n'en aurez sûrement pas besoin non plus. Cependant, si vous souhaitez alimenter directement un [assembleur électronique](assembler.md) ou un [chargeur](charger.md), c'est généralement une bonne idée d'utiliser un convertiseeur au lieu de les connecter directement à une source externe d'énergie.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerDistributor.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerDistributor.md
index fa717d3b5b..2b98941257 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerDistributor.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/powerDistributor.md
@@ -1,5 +1,5 @@
# Distributeur énergétique
-
+
Le distributeur énergétique distribue l'énergie d'un espace de stockage partagé (comme un [capaciteur](capacitor.md)), permettant à de nombreux sous-réseaux de partager leur énergie sans que leurs composants soient exposés aux ordinateurs des autres sous-réseaux. Il fonctionne en répartissant équitablement l'énergie dans tous les sous-réseaux auquel il est connecté, de façon à ce que la quantité *relative* d'énergie est la même dans chacun.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/printer.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/printer.md
index 9b47a78b07..7582613551 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/printer.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/printer.md
@@ -1,6 +1,6 @@
# Imprimante 3D
-
+
Les imprimantes 3D vous permettent d'imprimer n'importe quel bloc de n'importe forme, avec n'importe quelle texture. Pour démarrer avec les imprimantes 3D, vous devrez placer un bloc d'imprimante 3D à côté d'un ordinateur. Cela vous donnera accès à l'API de composant `printer3d`, ce qui permet de paramétrer et d'imprimer des [modèles](print.md) en utilisant les fonction fournies.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/raid.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/raid.md
index 6a849e991e..b8b0fa5d59 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/raid.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/raid.md
@@ -1,6 +1,6 @@
# Raid
-
+
Le bloc de RAID peut accueillir 3 [disques dur](../item/hdd1.md) qui seront combinés en un seul système de fichiers. Ce système de fichiers combinés a la taille de la somme des capacités des [disques dur](../item/hdd1.md) individuels, et est disponible pour tous les [ordinateurs](../general/computer.md) connectés au RAID.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/redstone.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/redstone.md
index ae35bfc29c..f8d72aeb82 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/redstone.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/redstone.md
@@ -1,6 +1,6 @@
# Redstone E/S
-
+
Le bloc d'E/S de redstone peut être utilisé pour lire et émettre des signaux de redstone à distance. Il se comporte comme un hybride des [cartes de redstone](../item/redstoneCard1.md) de niveau 1 et 2 : il peut aussi bien lire et émettre des signaux analogiques que des signaux empaquetés (bundle), mais il ne peut pas lire ou émettre de signaux redstone sans-fil.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/relay.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/relay.md
index 6e70c3eee3..bcad6afe33 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/relay.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/relay.md
@@ -1,6 +1,6 @@
# Relai
-
+
Le relai peut être utilisé pour permettre à différents sous-réseaux de s'envoyer des messages réseau entre eux, sans exposer leurs composants aux [ordinateurs](../general/computer.md) des autres réseaux. Maintenir l'état "local" d'un composant est généralement une bonne idée, pour éviter aux [ordinateurs](../general/computer.md) d'utiliser le mauvais [écran](screen1.md) ou pour éviter qu'une surcharge de composants survienne (ce qui provoque le crash de l'[ordinateur](../general/computer.md) et l'empêche de démarrer).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/screen1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/screen1.md
index e58a88981e..f8822c8033 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/screen1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/screen1.md
@@ -1,6 +1,6 @@
# Ecrans
-
+
Un écran est utilisé en combinaison avec une [carte graphique](../item/graphicsCard1.md), pour permettre aux [ordinateurs](../general/computer.md) d'afficher du texte. Les différents niveaux d'écrans ont différentes capacités, comme le support de différentes résolutions et couleurs. La qualité des écrans va d'une faible résolution en affichage monochrome à une haute résolution en 256 couleurs.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/serverRack.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/serverRack.md
index 681fcc50f6..288a0f4197 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/serverRack.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/serverRack.md
@@ -1,6 +1,6 @@
# Support de serveur
-
+
Un support de serveur peut contenir jusqu'à 4 [serveurs](../item/server1.md). Un [serveur](../item/server1.md) est un [ordinateur](../general/computer.md) de plus haut niveau, qui peut seulement être lancé dans un support de serveur. Les [serveurs](../item/server1.md) peuvent être contrôlés à distance avec un [terminal à distance](../item/terminal.md). Le nombre de [terminaux à distance](../item/terminal.md) qui peuvent être connectés à un seul [serveur](../item/server1.md) à la fois dépend du niveau du [serveur](../item/server1.md). La distance jusqu'à laquelle le [terminal à distance](../item/terminal.md) fonctionne peut être configurée dans l'interface du support. De plus grandes valeurs nécessitent plus d'énergie.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/switch.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/switch.md
index c5421f8985..beb888c171 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/switch.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/switch.md
@@ -1,6 +1,6 @@
# Routeur
-.](oredict:oc:switch)
+.](oredict:opencomputers:switch)
*Ce bloc est déprécié et sera retiré dans une version future.* Transformez les en [relai](relay.md) pour éviter de les perdre.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/transposer.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/transposer.md
index 1d743969d5..a83ece0a8e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/transposer.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/transposer.md
@@ -1,6 +1,6 @@
# Transposeur
-
+
Le transposeur fait le lien entre les entonnoirs controlés par la redstone et les [robots](robot.md), ce qui permet le transfert d'objets et de fluides entre des blocs voisins contrôlé par [ordinateur](../general/computer.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/block/waypoint.md b/src/main/resources/assets/opencomputers/doc/fr_fr/block/waypoint.md
index de69a8be8b..4ea7bdfb07 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/block/waypoint.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/block/waypoint.md
@@ -1,6 +1,6 @@
# Point de passage
-
+
Le point de passage n'a aucune utilité en soi, mais dans la façon dont il peut être utilisé. Les [améliorations de navigation](../item/navigationUpgrade.md) peuvent détecter les points de passage, ainsi les appareils équipés d'une amélioration de navigation peuvent utiliser ces points de passage pour parcourir le monde. C'est particulièrement utile pour écrire des programmes facilement ré-utilisables par des appreils comme les [robots](robot.md) et les [drones](../item/drone.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/general/example.md b/src/main/resources/assets/opencomputers/doc/fr_fr/general/example.md
index c0937a7a79..8c17aeea08 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/general/example.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/general/example.md
@@ -4,13 +4,13 @@ Voici un peu de texte de test pour la version de Markdown supportée par le syst


*Ceci* est du texte en *italique*, ~~barré~~ peut-être **un peu** de texte **en gras**. Est-ce que _c'est souligné _? Oh, non, _c'est aussi en italique!_ Bon, c'est [un lien](../index.md).
-
+
## Entête plus petite [avec un *lien* aussi mais cette __fois__ plus long](../block/adapter.md)
-
+
un peu de texte directement au dessus de l'afficheur d'objet pour tester l'espacement
-
+
un peu de texte directement en dessous de l'afficheur d'objet pour tester l'espacement
Ceci est en *italique
@@ -42,9 +42,9 @@ asdasd  qweqwe
Et finalement, [c'est un lien !](https://avatars1.githubusercontent.com/u/514903).
-
-
-
+
+
+
tests de retour à la ligne
12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
@@ -53,17 +53,17 @@ tests de retour à la ligne
* 12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
- `123456789012345678901234567890.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890`
-c'est un test pour uneune image dans une lignekakakakalalsd 123 as
+c'est un test pour uneune image dans une lignekakakakalalsd 123 as
-c'est un test pour une
+c'est un test pour une
une image avec un retour à la ligne après
c'est un test pour une
-
+
une image entre deux lignes
c'est un test pour une
-
+
une image entre deux lignes vides
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/general/quickstart.md b/src/main/resources/assets/opencomputers/doc/fr_fr/general/quickstart.md
index 133f50ec5b..9eba8fb45f 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/general/quickstart.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/general/quickstart.md
@@ -6,7 +6,7 @@ Aussi connu en tant que "comment construire votre premier ordinateur". Pour fair
Premièrement, vous aurez besoin d'un [boîtier](../block/case1.md). C'est le bloc qui contiendra tous les composants, en définissant le comportement de l'ordinateur que vous construisez.
-
+
Par exemple, vous aurez besoin de choisir quel niveau de [carte graphique](../item/graphicsCard1.md) vous voulez utiliser, si vous avez besoin d'une [carte réseau](../item/lanCard.md), une [carte de redstone](../item/redstoneCard1.md) ou, si vous faites des essais en mode créatif, peut être même une [carte de débogueur](../item/debugCard.md).
@@ -39,7 +39,7 @@ Maintenant, si vous avez utilisé un [boîtier](../block/case2.md) de niveau 2 c
Il vit ! Ou il devrait, en tout cas. Si ce n'est pas le cas quelque chose ne va pas, et vous devriez investiguer en utilisant l'[analyzer](../item/analyzer.md). Mais en supposant qu'il fonctionne maintenant, vous avez presque fini. La partie la plus compliquée est terminée. Tout ce qui reste à faire est de lui permettre d'accepter des entrées, et d'afficher des sorties.
Pour permettre à l'[ordinateur](computer.md) d'afficher des informations, vous devrez vous munir d'un [écran](../block/screen1.md) et d'une [carte graphique](../item/graphicsCard1.md).
-
+
Placez l'[écran](../block/screen1.md) à côté de votre [boîtier](../block/case1.md) ou, à nouveau, connectez le en utilisant des [câbles](../block/cable.md). Puis placez une [carte graphique](../item/graphicsCard1.md) de votre choix dans le [boîtier](../block/case1.md). Vous devriez maintenant voir un curseur clignotant sur l'[écran](../block/screen1.md). Finalement, placez un [clavier](../block/keyboard.md) soit sur l'[écran](../block/screen1.md) lui-même, soit juste en face de l'[écran](../block/screen1.md), pour activer l'entrée de données au [clavier](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/abstractBusCard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/abstractBusCard.md
index bd5e7d93f6..3c957c25b5 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/abstractBusCard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/abstractBusCard.md
@@ -1,5 +1,5 @@
# Carte de bus abstraite
-
+
Cette carte permet aux [ordinateurs](../general/computer.md), aux [serveurs](server1.md) et aux [robots](../block/robot.md) d'interagir avec le bus d'abstraction de StargateTech2. Quand la carte est installée, ces blocs se connecteront au bus d'abstraction et un composant devient disponible aux machines, pour envoyer des messages à travers le bus d'abstraction. Les messages entrants du bus d'abstraction sont convertis en signaux qui sont injectés dans la machine.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/acid.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/acid.md
index 93b20ef3f2..9020586237 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/acid.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/acid.md
@@ -1,6 +1,6 @@
# Grog
-
+
Cette délicieuse [citation nécessaire] mixture peut être consommée si jamais vous ressentez le besoin de vous... amuser. Ou de détruire votre tube digestif. Ou les deux. Il peut également servir en tant qu'ingrédient pour d'autres objets beaucoup plus utiles.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/alu.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/alu.md
index ed6a818835..4d6f93f2c6 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/alu.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/alu.md
@@ -1,5 +1,5 @@
# Unité de Logique Arithmétique
-
+
Elle est utilisée pour fabriquer des composants effectuant des calculs, comme les [processeurs](cpu1.md) et les [cartes graphiques](graphicsCard1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/analyzer.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/analyzer.md
index 5d7bd945bf..09d6d5e7c4 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/analyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/analyzer.md
@@ -1,6 +1,6 @@
# Analyseur
-
+
L'analyseur est un outil très pratique pour afficher des informations les blocs liés à OpenComputers. Cliquez simplement sur un bloc (en étant éventuellement accroupi) pour afficher quelques informations dans la zone de chat. Cela va de choses basiques comme l'adresse des composants, aux niveaux d'énergie du sous-réseau dont le bloc fait partie, jusqu'aux informations sur l'erreur qui a mené un [ordinateur](../general/computer.md) à planter, par exemple.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/angelUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/angelUpgrade.md
index 2384a61d86..e8e7283602 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/angelUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/angelUpgrade.md
@@ -1,5 +1,5 @@
# Amélioration Ange
-
+
Cette amélioration permet aux [robots](../block/robot.md) de placer des blocs en l'air, sans bloc de soutien.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/apu1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/apu1.md
index 9ab4090c17..f999898618 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/apu1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/apu1.md
@@ -1,6 +1,6 @@
# Unité de Traitement Accélérée (UTA)
-
+
Cet élément est la parfaite union d'un [processeur](cpu1.md) et d'une [carte graphique](graphicsCard1.md). En utiliser une revient à vous laisser un emplacement de carte supplémentaire. Comme un processeur normal, elle définit l'architecture de l'[ordinateur](../general/computer.md), et le nombre de composants qui peuvent être connectés à l'[ordinateur](../general/computer.md) avant qu'il ne puisse plus fonctionner. De plus, elle fournit des fonctionnalités graphiques de base.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/arrowKeys.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/arrowKeys.md
index 1c272ae924..1911ffd3fc 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/arrowKeys.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/arrowKeys.md
@@ -1,5 +1,5 @@
# Touches directionnelles
-
+
Au risque de me répéter : c'est la crise des touches. Parce que l'économie des touches a connu une sérieuse inflation ces dernières années. Elles sont utilisées pour fabriquer des [claviers](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/batteryUpgrade1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/batteryUpgrade1.md
index ac291754bb..dc51781a6a 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/batteryUpgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/batteryUpgrade1.md
@@ -1,5 +1,5 @@
# Amélioration de batterie
-
+
Cette amélioration augmente la quantité maximale d'énergie stockée par les appareils, comme les [robots](../block/robot.md) et les [tablettes](tablet.md), ce qui leur permet de fonctionner plus longtemps sans devoir revenir vers un [chargeur](../block/charger.md). Les améliorations de batterie de niveau supérieur peuvent stocker plus d'énergie.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/buttonGroup.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/buttonGroup.md
index 87d5208f4e..a3f9049dd0 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/buttonGroup.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/buttonGroup.md
@@ -1,5 +1,5 @@
# Groupe de boutons
-
+
Parce que vous avez *toujours* plein de boutons qui trainent quelque part. Ne mentez pas. Nous avons tous à faire un Maj-clic sur ce bouton de recette, encore et encore. Les groupes de boutons sont utilisés pour fabriquer des [claviers](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/card.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/card.md
index 27550f6da1..2b3894aec7 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/card.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/card.md
@@ -1,5 +1,5 @@
# Base de carte
-
+
C'est un matériau communément utilisé pour fabriquer des cartes dans OpenComputers (comme les [cartes graphiques](graphicsCard1.md), les [cartes réseau](lanCard.md), etc.).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/cardContainer1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/cardContainer1.md
index ae60a4532f..007b110add 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/cardContainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/cardContainer1.md
@@ -1,5 +1,5 @@
# Conteneur de carte
-
+
Le conteneur de carte est une amélioration de conteneur pour que des cartes puissent être insérées ou retirées d'un [robot](../block/robot.md) à la volée. Le niveau maximum de la carte que l'emplacement peut contenir est égal au niveau du conteneur. Contrairement aux amélioration classiques, la complexité des conteneurs est de deux fois leur niveau. Regardez [par là](../block/robot.md) pour avoir des détails sur la complexité des robots.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/chamelium.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/chamelium.md
index 4c3e4b214a..d6a4b76730 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/chamelium.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/chamelium.md
@@ -1,6 +1,6 @@
# Chamélium
-
+
Le chamélium est un matériau métamorphe qui est utilisé pour créer des [impressions 3D](../block/print.md) dans une [imprimante 3D](../block/printer.md). De lui même, il n'a aucune utilité, mais est très pratique pour créer des zones simples et entièrement monochromes.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/chip1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/chip1.md
index 5f6a89e2e4..9229704abf 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/chip1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/chip1.md
@@ -1,5 +1,5 @@
# Puce électronique
-
+
Les puces électroniques sont le pain quotidien de la fabrication de composants électroniques. Elles existent en différents niveaux, pour fabriquer différents niveaux de composants.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/chunkloaderUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/chunkloaderUpgrade.md
index f7acaaac48..9816731f3a 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/chunkloaderUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/chunkloaderUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration chargement de chunk
-
+
L'amélioration de chargement de chunk peut être installée sur des appareils (comme les [robots](../block/robot.md) et les [microcontrôleurs](../block/microcontroller.md)) pour leur permettre de garder le chunk dans lequel ils sont - ainsi que les chunks environnants - chargés. Cela consomme de l'énergie, cependant. Le chargeur de chunks peut être activé et désactivé par l'API du composant exposé à l'appareil.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/circuitBoard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/circuitBoard.md
index e6657ab101..7cf16a1f8e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/circuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/circuitBoard.md
@@ -1,5 +1,5 @@
# Plaque de circuit imprimé
-
+
C'est un objet intermédiaire fait à partir de [plaques de circuit imprimé brutes](rawCircuitBoard.md) et utilisé pour fabriquer des [circuits imprimés](printedCircuitBoard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/componentBus1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/componentBus1.md
index 7a61997a07..f2cf2634cf 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/componentBus1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/componentBus1.md
@@ -1,6 +1,6 @@
# Bus des composants
-
+
Un bus des composants est une amélioration dédiée aux [serveurs](server1.md) qui permet à un [serveur](server1.md) de communiquer avec plus de composants à la fois, sans s'éteindre. Comme avec les [processeurs](cpu1.md), un bus de plus haut niveau augmente la limite des composants. Les [serveurs](server1.md) de plus haut niveau sont également capables d'accepter plus de bus de composants, ce qui permet de communiquer avec encore plus de composants.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/controlUnit.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/controlUnit.md
index 8a90625280..0ca45d940d 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/controlUnit.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/controlUnit.md
@@ -1,5 +1,5 @@
# Unité de contrôle
-
+
Un objet de fabrication de haut niveau utilisé dans des circuits avancés, comme les [processeurs](cpu1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/cpu1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/cpu1.md
index dfcab698a0..eec640073c 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/cpu1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/cpu1.md
@@ -1,6 +1,6 @@
# Processeur
-
+
L'unité centrale de traitement (ou *central processing unit (CPU)* en anglais) est un composant essentiel à chaque [ordinateur](../general/computer.md) ou [serveur](server1.md). Il définit l'architecture de l'[ordinateur](../general/computer.md), et le nombre de composants qui peuvent être connectés à l'[ordinateur](../general/computer.md) avant qu'il ne cesse de fonctionner. Un processeur de plus haut niveau permet également d'avoir plus d'appels par tick à l'[ordinateur](../general/computer.md) - en d'autres termes : plus le processeur est puissant, plus il est rapide.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/craftingUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/craftingUpgrade.md
index 8c0420354c..22a4d0daa9 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/craftingUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/craftingUpgrade.md
@@ -1,5 +1,5 @@
# Amélioration d'artisanat
-
+
L'amélioration d'artisanat permet aux [robots](../item/inventoryUpgrade.md) de réaliser des recettes avec et sans forme en utilisant leur [inventaire](../item/inventoryUpgrade.md). Pour fabriquer, la grille de 3x3 en haut à gauche de l'[inventaire](../item/inventoryUpgrade.md) du [robot](../block/robot.md) est utilisée comme grille de fabrication. Les objets doivent être arrangés selon la recette. Les résultats seront replacés dans l'[inventaire](../item/inventoryUpgrade.md) du [robot](../block/robot.md). Comme pour les objets ramassés par terre, le résultat sera placé dans l'emplacement sélectionné; s'il n'y arrive pas, l'objet sera placé dans l'emplacement vide suivant. S'il n'y a plus de place libre, le résultat sera lâché par terre.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/cuttingWire.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/cuttingWire.md
index d5aa5385ea..7e70cbe7e6 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/cuttingWire.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/cuttingWire.md
@@ -1,5 +1,5 @@
# Fil de coupe
-
+
Un objet qui n'existe que si vous utilisez les recettes difficiles, il est utilisé pour fabriquer des [plaques de circuit imprimé brutes](rawCircuitBoard.md). Très inefficacement.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/dataCard1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/dataCard1.md
index 422df92d9d..9bacb6ad9a 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/dataCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/dataCard1.md
@@ -1,6 +1,6 @@
# Carte de données
-
+
La carte de données est une carte utilitaire qui fournit quelques algorithmes qui seraient soit compliqués à implémenter sur une architecture, soit lent à l'exécution. Elle fournit des fonctionnalités de hachage, ainsi que des fonctionnalités d'inflation/déflation. De plus, elle contient un système de fichiers qui fournit un certain nombre de programmes en utilisant les fonctionnalités de la carte, comme la carte internet.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/databaseUpgrade1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/databaseUpgrade1.md
index 64b34c2e8e..fc58ed5928 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/databaseUpgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/databaseUpgrade1.md
@@ -1,6 +1,6 @@
# Amélioration de base de données
-
+
L'amélioration de base de données peut être configurée pour stocker une liste de représentations de groupes d'objets, qui peuvent ensuite être utilisés par d'autres composants. C'est particulièrement utile pour les objets qui sont uniquement distinguables par leurs données NBT, ce qui ne fait pas partie des données affichées de base pour un groupe d'objets.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/debugCard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/debugCard.md
index 092dfc1e93..9fc2084468 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/debugCard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/debugCard.md
@@ -1,6 +1,6 @@
# Carte de débogueur
-
+
La carte de débogueur est un objet à usage créatif seulement, qui a été créé à l'origine pour rendre le débogage plus facile, en automatisant certains processus. Depuis, elle a obtenu beaucoup d'autres fonctionnalités, ce qui la rend très utile pour la création de cartes personnalisées.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/disk.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/disk.md
index 57f96b5bfa..5eec5867ee 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/disk.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/disk.md
@@ -1,5 +1,5 @@
# Disque
-
+
Un composant de fabrication de base, utilisé pour fabriquer des moyens de stockage de données, comme des [disquettes](floppy.md) et des [disques durs](hdd1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/drone.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/drone.md
index b917b54fbc..0953a7a15e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/drone.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/drone.md
@@ -1,5 +1,5 @@
# Drone
-
+
Les drones sont faits en mettant un [boîtier de drone](droneCase1.md) dans un [assembleur](../block/assembler.md). Ce sont des [robots](../block/robot.md) sous forme d'entité, moins chers mais avec moins de fonctionnalités. Ils sont également capables de se déplacer différemment et beaucoup plus vite que les [robots](../block/robot.md), et ils sont généralement controlés en utilisant un programme client sur un [ordinateur](../general/computer.md). Le drone devra avoir une [EEPROM](eeprom.md) configurée pour écouter les commandes entrantes à exécuter, ou pour agir de lui même.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/droneCase1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/droneCase1.md
index 08b8b686fe..eacfaf5fe0 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/droneCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/droneCase1.md
@@ -1,6 +1,6 @@
# Boitier de drone
-
+
Le boitier de drone est utilisé pour construire des [drones](drone.md) dans l'[assembler](../block/assembler.md). Les [drones](drone.md) sont des machines légères, rapides et très mobiles avec des fonctionnalités réduites (moins d'améliorations et d'emplacements de composant disponibles). Contrairement aux [robots](../block/robot.md), ils ne peuvent pas utiliser d'outils, et peuvent seulement interagir avec le monde de manière relativement limitée.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/eeprom.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/eeprom.md
index 678207bf74..61550d9bde 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/eeprom.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/eeprom.md
@@ -1,6 +1,6 @@
# EEPROM
-
+
L'EEPROM est ce qui contient le code utilisé pour initialiser un ordinateur quand il démarre. Les données sont stockées dans un tableau d'octets, et peuvent avoir différentes significations pour différentes architectures de [processeur](cpu1.md). Par exemple, pour Lua, c'est généralement un petit script qui recherche les systèmes de fichier avec un script d'initialisation, pour d'autres architectures ça pourrait être du code machine.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/experienceUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/experienceUpgrade.md
index 3ae09f216d..73614b348e 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/experienceUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/experienceUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration d'expérience
-
+
L'amélioration d'expérience est une amélioration très spéciale, puisqu'elle permet aux [robots](../block/robot.md) et aux [drones](drone.md) pour collecter l'expérience en accomplissant de nombreuses actions, comme de casser des blocs de minerai ou de tuer des entités. Une simple amélioration peut stocker jusqu'à 30 niveaux, en fournissant un bonus passif par niveau d'expérience, comme de plus grandes vitesses de récolte et une capacité d'énergie accrue.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/floppy.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/floppy.md
index 0e6c7aa256..b83d6a0316 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/floppy.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/floppy.md
@@ -1,5 +1,5 @@
# Disquette
-
+
La disquette est le moyen de stockage de données le moins cher et le plus petit dans OpenComputers. C'est une manière très pratique de stocker des données et de les transférer entre les [ordinateurs](../general/computer.md) et les [robots](../block/robot.md) dès le début de la partie. Vous pourrez également trouver des disquettes avec des programmes utiles dans des coffres de donjons (le gestionnaire de paquets Open Programs est un bon exemple, ce qui permet d'installer facilement des programmes à partir d'un dépôt GitHub central).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/generatorUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/generatorUpgrade.md
index 40750c39c5..a1714e8185 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/generatorUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/generatorUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration de générateur
-
+
L'amélioration de générateur permet aux appareils de se recharcher à la volée. Pour le moment elle supporte seulement les carburants solides, comme le charbon. Elle a un inventaire interne qui peut stocker un groupe plein de carburant. Le carburant en surplus peut être retiré du générateur en utilisant la méthode appropriée de l'API du composant. En retirant une amélioration du générateur d'un [robot](../block/robot.md), son contenu sera lâché par terre.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/graphicsCard1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/graphicsCard1.md
index 014d083140..9d5641f830 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/graphicsCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/graphicsCard1.md
@@ -1,6 +1,6 @@
# Carte graphique
-
+
La carte graphique est un composant essentiel pour la plupart des [ordinateurs](../general/computer.md), elle leur permet d'afficher du texte sur un [écran](../block/screen1.md) qui leur est connecté. La carte graphique a plusieurs niveaux, et comme les [écrans](../block/screen1.md), elle supporte différentes résolutions et profondeurs de couleur.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/hdd1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/hdd1.md
index 5580dd8b3b..6c6edc9e49 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/hdd1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/hdd1.md
@@ -1,5 +1,5 @@
# Disque dur
-
+
Le disque dur est un moyen de stockage de données de haut niveau dans OpenComputers. Tous les moyens de stockage de données fonctionnent à la même vitesse ; un moyen de stockage de plus haut niveau fournit juste plus d'espace. Il y a également quelques appareils qui peuvent seulement utiliser les disques durs (bien que les serveurs pourraient utiliser un [lecteur de disquettes](../block/diskDrive.md) externe, par exemple). Les disques durs peuvent être placés dans un [raid](../block/raid.md), ce qui permet à plusieurs disques de partager le même système de fichiers. Remarquez que placer un disque dur dans un [raid](../block/raid.md) efface le contenu du disque.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverBoots.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverBoots.md
index c6be248c72..9acaa25da2 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverBoots.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverBoots.md
@@ -1,6 +1,6 @@
# Bottes de vol plané
-
+
Si vous ne voulez pas vous embêter à programmer un [drone](drone.md), voici un usage alternatif : un tremplin ! Ou de glorieux patins à roulettes. Un truc du genre.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverUpgrade1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverUpgrade1.md
index 0ae92f3f69..6133141cba 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverUpgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/hoverUpgrade1.md
@@ -1,6 +1,6 @@
# Amélioration de vol plané
-
+
L'amélioration de vol plané permet aux [robots](../block/robot.md) de voler beaucoup plus au dessus du sol que ce qu'ils pourraient le faire normalement. Contrairement aux [drones](drone.md), ils sont limités par défaut à une hauteur de vol de 8 blocs. Ca n'est généralement pas un problème, parce qu'ils peuvent tout de même monter aux murs. Leurs règles de déplacement peuvent être résumées ainsi :
- Les robots peuvent seulement bouger si la position de départ ou d'arrivée est valide (par exemple pour un pont).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/inkCartridge.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/inkCartridge.md
index 6a8b603c19..8162b64f38 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/inkCartridge.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/inkCartridge.md
@@ -1,5 +1,5 @@
# Cartouche d'encre
-
+
Les cartouches d'encre sont faites pour recharger le tampon encreur des [imprimantes 3D](../block/printer.md). Même s'il est possible de les recharger directement avec les pigments, c'est désordonné et inefficace. Il est vivement recommandé d'investir dans une véritable cartouche d'encre OpenComputers (TM), dès aujourd'hui ! (Annonce : elles pourraient coûter plus cher que l'imprimante elle-même, ou pas).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/internetCard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/internetCard.md
index 0f8f415fb2..fe084bcc38 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/internetCard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/internetCard.md
@@ -1,6 +1,6 @@
# Carte internet
-
+
La carte internet donne accès à Internet aux [ordinateurs](../general/computer.md). Elle permet d'exécuter de simples requêtes HTTP, et aussi d'ouvrir des sockets client TCP dans lesquels vous pouvez lire et écrire.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/interweb.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/interweb.md
index aae00aad14..0f88875d09 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/interweb.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/interweb.md
@@ -1,5 +1,5 @@
# Interweb
-
+
L'interweb est un composant de base pour tout ce qui est lié à des communications à longue distance. Il utilise les mécaniques bizarres de tous les trucs liés au Néant pour permettre la communication via des tunnels quantiques. Il est utilisé notamment pour les [cartes internet](internetCard.md) et les [cartes liées](linkedCard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryControllerUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryControllerUpgrade.md
index d872e38942..fbabc489cd 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryControllerUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryControllerUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration du contrôleur d'inventaire
-
+
L'amélioration du contrôleur d'inventaire donne aux [robots](../block/robot.md) et aux [drones](drone.md) des capacités d'interactions étendues avec les inventaires. Elle permet à un appareil de viser spécifiquement un emplacement dans un inventaire externe quand il lâche ou ramasse un objet. Elle permet également à un appareil de lire des informations détaillées à propos d'un objet. Enfin, elle fournit aux [robots](../block/robot.md) un moyen de changer leur outil équipé sans aide extérieure.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryUpgrade.md
index c1b94d3e2e..ca3c5aea26 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/inventoryUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration d'inventaire
-
+
L'amélioration d'inventaire fournit des emplacements d'inventaire supplémentaires pour les [robots](../block/robot.md) et les [drones](drone.md). Pour chaque amélioration d'inventaire, un [robot](../block/robot.md) gagnera 16 emplacements d'inventaire supplémentaires, pour un maximum de 64 emplacements au total ; un [drone](drone.md) gagnera 4 emplacements par amélioration, pour un total de 8 emplacements.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/lanCard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/lanCard.md
index 5a7fc0794a..faafb5c06f 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/lanCard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/lanCard.md
@@ -1,5 +1,5 @@
# Carte réseau
-
+
La carte réseau permet aux [ordinateurs](../general/computer.md) d'envoyer et de recevoir des messages réseau. Les messages (ou paquets) peuvent être diffusés à tous les noeuds de réception dans un sous-réseau, ou envoyés à un noeud spécifique avec une certaine adresse. Un [relai](../block/relay.md) peut être utilisé pour relier plusieurs sous-réseaux pour relayer des messages entre les sous-réseaux auxquels il est connecté. Il est également possible d'envoyer un message ciblé si le receveur est dans un autre sous-réseau, et si les réseaux sont connectés par un ou plusieurs [relais](../block/relay.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/leashUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/leashUpgrade.md
index bf9b22a91a..52c87d60b4 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/leashUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/leashUpgrade.md
@@ -1,5 +1,5 @@
# Amélioration de laisse
-
+
L'amélioration de laisse permet de mettre les animaux en laisse, attachés à l'entité contenue dans l'appareil qui héberge le composant, par exemple un [drone](drone.md). En utilisant cette amélioration, plusieurs animaux peuvent être attachés en même temps, ce qui la rend assez utile pour déplacer des troupeaux.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/linkedCard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/linkedCard.md
index 4095d496c4..0ccf61c6b6 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/linkedCard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/linkedCard.md
@@ -1,5 +1,5 @@
# Carte liée
-
+
La carte liée est une version spécialisée et avancée de la [carte réseau](lanCard.md). Elle peut seulement fonctionner par paires, en fournissant une communication en point à point entre les cartes appairées. Les cartes liées peuvent communiquer sur de longues (illimité) distances, et même à travers les dimensions.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/manual.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/manual.md
index bba03165f5..71c156926a 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/manual.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/manual.md
@@ -1,6 +1,6 @@
# Manuel
-
+
Ce que vous êtes en train de lire en ce moment même ! Le manuel contient une mine d'informations à propos d'OpenComputers (et sûrement plus). Si vous avez besoin d'information sur un objet ou un bloc, ne cherchez pas plus loin ! Descendez pour apprendre comment l'utiliser (avec la souris ou la barre d'ascenseur sur la droite).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/microcontrollerCase1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/microcontrollerCase1.md
index 438f776f09..fdf45d35b7 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/microcontrollerCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/microcontrollerCase1.md
@@ -1,6 +1,6 @@
# Boitier de microcontrôleur
-
+
Le boitier de microcontrôleur est la base de construction des [microcontrôleurs](../block/microcontroller.md) grâce à l'[assembleur](../block/assembler.md). Les [microcontrôleurs](../block/microcontroller.md) sont des [ordinateurs](../general/computer.md) très primitifs. Ils peuvent seulement contenir une quantité très limitée de composants, et sont faits pour être avoir une utilisation très spécifique, comme la transformation de signaux de redstone, ou le traitement de messages réseaux.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/nanomachines.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/nanomachines.md
index e283b9792d..4ad8e3e860 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/nanomachines.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/nanomachines.md
@@ -1,6 +1,6 @@
# Nanomachines
-
+
Ces petits bonhommes créent une interface avec votre système nerveux pour vous faire aller toujours plus loin, toujours plus haut, toujours plus fort ! Ou vous tuer. Parfois les deux en même temps ! En clair, les nanomachines fournissent un système basé sur de l'énergie pour appliquer des effets (bons ou mauvais) sur le joueur dans lequel elles résident. Pour "installer" des nanomachines, mangez les !
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/navigationUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/navigationUpgrade.md
index eb13c10b99..c4195fa4e5 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/navigationUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/navigationUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration de navigation
-
+
L'amélioration de navigation fournit des informations de localisation et d'orientation aux appareils sur lesquels elle est installée. Les coordonnées que l'amélioration fournit sont relatives au centre de la carte qui a été utilisée pour fabriquer l'amélioration, et la portée fonctionnelle est basée sur la taille de la carte.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/numPad.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/numPad.md
index 3112bfeb2d..32f3c24c86 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/numPad.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/numPad.md
@@ -1,5 +1,5 @@
# Pavé numérique
-
+
Le pavé numérique est une partie de chaque [clavier](../block/keyboard.md). Il vous permet de saisir des nombres.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/pistonUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/pistonUpgrade.md
index b4945e9f96..572aa83be2 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/pistonUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/pistonUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration de piston
-
+
L'amélioration de piston permet à certains appareils de se comporter comme un piston de base. Une fois installée, un composant avec une seule méthode, `push()`, devient disponible. Si elle est appelée, l'appareil essayera de pousser le bloc qui lui fait face. Pour les [robots](../block/robot.md) et les [microcontrôleurs](../block/microcontroller.md), c'est la face avant; pour les [tablettes](tablet.md), elle utilisera la face avant du joueur.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/printedCircuitBoard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/printedCircuitBoard.md
index 03d035dceb..157d727b2a 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/printedCircuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/printedCircuitBoard.md
@@ -1,5 +1,5 @@
# Circuit imprimé
-
+
Le circuit imprimé est, avec le [transistor](transistor.md), l'un des matériaux les plus basiques d'OpenComputers. Il est utilisé en tant que base pour beaucoup de composants, comme les [bases de carte](card.md) et un grand nombre de [blocs](../block/index.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/ram1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/ram1.md
index 5dad065207..4752f69b17 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/ram1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/ram1.md
@@ -1,6 +1,6 @@
# Mémoire
-
+
La mémoire est, au même titre que le [processeur](cpu1.md), un composant essentiel à chaque [ordinateur](../general/computer.md). En fonction de l'architecture du [processeur](cpu1.md), la mémoire a un effet important sur ce que l'[ordinateur](../general/computer.md) peut ou ne peut pas faire. Pour l'architecture Lua standard, par exemple, elle contrôle la quantité réelle de mémoire que les scripts Lua peuvent utiliser. Cela signifie que pour exécuter des programmes demandant plus de ressources, vous aurez besoin de plus de mémoire.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/rawCircuitBoard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/rawCircuitBoard.md
index dc64cebe8b..efcc446f38 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/rawCircuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/rawCircuitBoard.md
@@ -1,5 +1,5 @@
# Plaque de circuit imprimé brute
-
+
C'est un matériau de fabrication intermédiaire, utilisé pour fabriquer des [plaques de circuit imprimé](circuitBoard.md) (ou des [circuits imprimés](printedCircuitBoard.md), en fonction de l'ensemble de recettes utilisé).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/redstoneCard1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/redstoneCard1.md
index 5f818f81b5..04b8f1d641 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/redstoneCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/redstoneCard1.md
@@ -1,6 +1,6 @@
# Carte de Redstone
-
+
La carte de redstone permet aux [ordinateurs](../general/computer.md) de lire et émettre des signaux de redstone analogiques dans les blocs adjacents. Quand la force d'un signal entrant change, un signal est injecté dans l'[ordinateur](../general/computer.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/server1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/server1.md
index e2b9e9100b..ccb737b181 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/server1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/server1.md
@@ -1,6 +1,6 @@
# Serveur
-
+
Les serveurs sont une sorte d'[ordinateur](../general/computer.md) de haut niveau. Ils peuvent être configurés en les tenant en main et en les utilisant en même temps - comme pour ouvrir un sac à dos ou une Bourse du Néant (d'EnderStorage), par exemple. Après avoir inséré un [processeur](cpu1.md), de la [mémoire](ram1.md) et des cartes d'extension, le serveur doit être placé dans un [support de serveur](../block/serverRack.md). Pour plus d'informations, allez voir l'entrée sur le [support de serveur](../block/serverRack.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/signUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/signUpgrade.md
index b886cb3259..930bc45632 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/signUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/signUpgrade.md
@@ -1,5 +1,5 @@
# Amélioration de panneau d'E/S
-
+
Cette amélioration permet d'interagir avec les panneaux dans le monde. Elle permet de lire le message actuel sur le panneau, ainsi que de changer le message sur le panneau (si c'est autorisé).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/solarGeneratorUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/solarGeneratorUpgrade.md
index 63d691f623..d5d2858b47 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/solarGeneratorUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/solarGeneratorUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration du générateur solaire
-
+
L'amélioration du générateur solaire peut être installée sur des appareils comme les [robots](../block/robot.md), les [drones](drone.md) et les [tablettes](tablet.md) pour générer passivement de l'énergie. Elle fonctionnera seulement si l'appareil est directement exposé à la lumière du soleil ; un appareil dans un endroit fermé ou une zone affectée par la météo ne génèrera pas d'énergie.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tablet.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tablet.md
index e200eb873c..646f36923f 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tablet.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tablet.md
@@ -1,6 +1,6 @@
# Tablette
-
+
Les tablettes sont faites en mettant un [boîtier de tablette](tabletCase1.md) dans un [assembleur](../block/assembler.md), en le configurant comme vous le voulez et en assemblant. Les tablettes se comportent comme des ordinateurs portables qui ne peuvent pas interagir directement avec le monde - par exemple, les [cartes de redstone](redstoneCard1.md) de base ne fonctionnent pas avec une tablette. Cependant, un certain nombre d'améliorations fonctionne, comme l'[amélioration de panneau d'E/S](signUpgrade.md) ou l'[amélioration de piston](pistonUpgrade.md).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tabletCase1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tabletCase1.md
index bba691e488..1b2e5e0bd3 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tabletCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tabletCase1.md
@@ -1,6 +1,6 @@
# Boitier de tablette
-
+
Le boitier de tablette est la base de construction des [tablettes](tablet.md), grâce à l'[assembleur](../block/assembler.md). Les [tablettes](tablet.md) sont des [ordinateurs](../general/computer.md) portables très compacts. Elles peuvent accueillir un petit nombre d'améliorations, mais ne peuvent pas interagir avec le monde de la même manière qu'un [boitier d'ordinateur](../block/case1.md) (ce n'est pas aussi simple qu'avec une [carte réseau](lanCard.md) ou une [carte redstone](redstoneCard1.md) par exemple).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankControllerUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankControllerUpgrade.md
index 6e115a0b24..076b8359dd 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankControllerUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankControllerUpgrade.md
@@ -1,6 +1,6 @@
# Amélioration du contrôleur de réservoir
-
+
L'amélioration du contrôleur de réservoir est aux réservoirs de fluides ce que l'[amélioration de contrôleur d'inventaire](inventoryControllerUpgrade.md) est aux inventaires. Elle permet aux appareils d'obtenir plus d'informations sur les réservoirs internes et adjacents.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankUpgrade.md
index 5af40ea890..af37cf6908 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tankUpgrade.md
@@ -1,5 +1,5 @@
# Amélioration de réservoir
-
+
L'amélioration de réservoir permet aux appareils de stocker des liquides. Chaque réservoir peut contenir un seul type de liquide, et fournit un volume de 16 seaux (16000mB). Les [robots](../block/robot.md) et les [drones](drone.md) peuvent aspirer des liquides dans le monde et à partir d'autres réservoirs, et peuvent remplir les réservoirs externes, et si le liquide le supporte, ils peuvent également en placer dans le monde. Il n'y a pas de limite au nombre de réservoirs qui peuvent être installés sur un appareil.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/terminal.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/terminal.md
index 8dc7db009f..a006484469 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/terminal.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/terminal.md
@@ -1,6 +1,6 @@
# Terminal à distance
-
+
Le terminal à distance peut être utilisé pour contrôler à distance des [serveurs](server1.md). Pour l'utiliser, faites un clic droit en étant accroupi sur un serveur installé dans un [support de serveur](../block/serverRack.md) (cliquez sur le bloc du [support de serveur](../block/serverRack.md), en visant le [serveur](server1.md) pour y lier le terminal).
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/texturePicker.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/texturePicker.md
index 0c1e341e1b..b6e9b87a1c 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/texturePicker.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/texturePicker.md
@@ -1,6 +1,6 @@
# Ramasseur de texture
-
+
Le ramasseur de texture est très utile pour réaliser des modèles pour votre [imprimante 3D](../block/printer.md). Il vous permet de récupérer le nom de la texture utilisé par un bloc, simplement en l'utilisant (et en étant éventuellement accroupi) sur le bloc. Avertissement : pour les blocs qui utilisent un rendu spécial, comme les coffres, cela peut ne pas marcher.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tractorBeamUpgrade.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tractorBeamUpgrade.md
index c82cea939f..939ad46422 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/tractorBeamUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/tractorBeamUpgrade.md
@@ -1,5 +1,5 @@
# Amélioration du rayon tracteur
-
+
L'amélioration du rayon tracteur permet aux appareils de ramasser des objets dans un rayon de 3 blocs autour d'eux. Cela peut être très utile quand vous vous servez de [robots](../block/robot.md) dans un ferme à bois ou à quoi que ce soit d'autre, ou quand vous leur faites utiliser des outils qui cassent plusieurs blocs autour d'eux (comme les outils de Tinker's Construct). Chaque opération essayera d'aspirer une pile d'objets à portée, et consommera un peu d'énergie.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/transistor.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/transistor.md
index 859c9d50d4..5da62abd92 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/transistor.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/transistor.md
@@ -1,5 +1,5 @@
# Transistor
-
+
Le transistor est l'un des ingrédients pour la fabrication les plus basiques d'OpenComputers. Il est principalement utilisé pour fabriquer des [puces électroniques](chip1.md) et d'autres bidules électroniques.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/upgradeContainer1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/upgradeContainer1.md
index 91ab378dc9..5bbdcb2719 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/upgradeContainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/upgradeContainer1.md
@@ -1,5 +1,5 @@
# Amélioration de conteneur
-
+
L'amélioration de conteneur est une amélioration d'espace pour les [robots](../block/robot.md), qui fournit un emplacement dans les [robots](../block/robot.md) terminés dans lequel des améliorations classiques peuvent être insérées. Le niveau maximal des améliorations que cet emplacement peut contenir est égal au niveau du conteneur. Contrairement aux améliorations classiques, la complexité du conteneur est de deux fois son niveau. Allez voir la page des [robots](../block/robot.md) et de l'[assembleur](../block/assembler.md) pour plus d'informations sur la complexité.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/wlanCard1.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/wlanCard1.md
index e6f6eefeea..ee041925bd 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/wlanCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/wlanCard1.md
@@ -1,6 +1,6 @@
# Carte de réseau sans-fil
-
+
La carte de réseau sans fil est une [carte réseau](lanCard.md) améliorée qui, en plus de gérer les messages réseaux filaires, peut également envoyer et recevoir des messages réseaux sans fil. La force du signal contrôle directement la distance jusqu'à laquelle un message peut être reçu, avec cette force étant égale à la distance en blocs.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/worldSensorCard.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/worldSensorCard.md
index d0fd8a6bcb..320b85b247 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/worldSensorCard.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/worldSensorCard.md
@@ -1,5 +1,5 @@
# Carte de capteur du monde
-
+
La carte de capteur du monde permet de lire les informations atmosphériques ainsi que la gravité des différentes planètes ajoutées par Galacticraft. Cela peut être utile pour les [robots](../block/robot.md) ou les [drones](drone.md) travaillant dans l'espace.
diff --git a/src/main/resources/assets/opencomputers/doc/fr_fr/item/wrench.md b/src/main/resources/assets/opencomputers/doc/fr_fr/item/wrench.md
index 95b523841a..e4aa05a9c3 100644
--- a/src/main/resources/assets/opencomputers/doc/fr_fr/item/wrench.md
+++ b/src/main/resources/assets/opencomputers/doc/fr_fr/item/wrench.md
@@ -1,5 +1,5 @@
# Crisseur
-
+
Un peu comme n'importe quel autre mod technologique, OpenComputers a sa propre version d'une clé anglaise. En l'occurrence, c'est un hybride entre un tournevis et une clé anglaise, ce qui a l'air d'être incroyablement compliqué à l'usage. Il peut être utilisé pour faire tourner la plupart des blocs, et il est également compatible avec les blocs de la plupart des autres mods qui réagissent aux outils de type clé.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/accessPoint.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/accessPoint.md
index 6607601f95..1fea56379b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/accessPoint.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/accessPoint.md
@@ -1,6 +1,6 @@
# Точка доступа
-
+
*Этот блок устарел и будет удален в следующих версиях.* Замените его на [ретранслятор](relay.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/adapter.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/adapter.md
index 9e45e2a238..4d5d753809 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/adapter.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/adapter.md
@@ -1,6 +1,6 @@
# Адаптер
-
+
Адаптеры позволяют [компьютерам](../general/computer.md) взаимодействовать с блоками Minecraft или из других модов. Поддерживаемые блоки, прилегающие к адаптеру, будут отображаться как компоненты [компьютера](../general/computer.md), подключенного к адаптеру.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/assembler.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/assembler.md
index bc6a27b4a7..ff01b0e2d2 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/assembler.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/assembler.md
@@ -1,6 +1,6 @@
# Сборщик роботов
-
+
Сборщик роботов - это продвинутая рабочая станция, позволяющая собирать такие сложные устройства, как [роботы](robot.md), [дроны](../item/drone.md) и [планшеты](../item/tablet.md). Они требуют для сборки большое количество энергии, поэтому рекомендуется использовать их совместно с [конденсатором энергии](capacitor.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/cable.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/cable.md
index 3399bdb38a..9664410d50 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/cable.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/cable.md
@@ -1,6 +1,6 @@
# Кабель
-
+
Кабель служит для соединения [компьютеров](../general/computer.md) и машин, которые далеки друг от друга. Если вы используете компактную сборку, где все компоненты касаются друг друга (напрямую или нет, большинство блоков ведут себя как кабели), вам они обычно не понадобятся.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/capacitor.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/capacitor.md
index 38cd3a6fa7..b73f04f1a1 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/capacitor.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/capacitor.md
@@ -1,6 +1,6 @@
# Конденсатор энергии
-
+
Конденсатор хранит энергию, используемую в сети, действуя в качестве буфера энергии, когда это необходимо. В отличие от конвертации энергии других модов во внутреннюю энергию OpenComputers (с помощью [конвертера энергии](powerConverter.md), к примеру), передача энергии внутри одной подсети мгновенна. Наличие энергобуфера полезно в случаях, когда необходимо большое количество энергии, например, для [сборки](assembler.md) или [зарядки](charger.md) [роботов](robot.md) или [дронов](../item/drone.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/case1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/case1.md
index 34328b566b..10b34b30b5 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/case1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/case1.md
@@ -1,6 +1,6 @@
# Системный блок
-
+
Системные блоки бывают 3 различных уровней, различающихся количеством компонентов, которые могут быть в них вставлены. Также есть креативный системный блок. Системные блоки могут быть помещены в [сборщик](assembler.md) для создания [робота](robot.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/chameliumBlock.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/chameliumBlock.md
index d630d12432..d6a8e4f586 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/chameliumBlock.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/chameliumBlock.md
@@ -1,6 +1,6 @@
# Блок хамелиума
-
+
Несколько кусочков [хамелиума](../item/chamelium.md) могут быть объединены для получения одноцветный блок — его можно использовать в качестве декорации. Блоки хамелиума могут быть окрашены в любой из 16 стандартных цветов Minecraft.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/charger.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/charger.md
index fd5443d90f..7e9a833371 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/charger.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/charger.md
@@ -1,6 +1,6 @@
# Зарядное устройство
-
+
Зарядное устройство предназначено для зарядки устройств, таких как [роботы](robot.md), [дроны](../item/drone.md) и [планшеты](../item/tablet.md). Зарядное устройство активируется редстоун-сигналом. Скорость заряда зависит от силы редстоун-сигнала: так, при силе 15, скорость заряда будет 100%.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/disassembler.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/disassembler.md
index 1984b95c79..ed7ed9862b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/disassembler.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/disassembler.md
@@ -1,6 +1,6 @@
# Разборщик
-
+
Разборщик используется, чтобы разбирать большинство блоков OpenComputers на исходные компоненты. Это удобно для сборки новых деталей из частей старых и ненужных, а таже для разборки устройств, которые вам больше не нужны или были собраны неправильно (например, [роботы](robot.md) без [операционной системы](../general/openOS.md)).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/diskDrive.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/diskDrive.md
index c87b2c411b..31da6f0614 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/diskDrive.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/diskDrive.md
@@ -1,6 +1,6 @@
# Дисковод
-
+
Дисковод может быть использован для чтения [дискет](../item/floppy.md) при работе с подключённым к нему [компьютером](../general/computer.md). Это удобно на начальных этапах, потому что низкоуровневые [системные блоки](case1.md) не имеют встроенного дисковода, а вам нужна будет операционная система для запуска [компьютера](../general/computer.md). Дискета с [OpenOS](../general/openOS.md) может быть создана из пустой [дискеты](../item/floppy.md) и [данного руководства](../item/manual.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/geolyzer.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/geolyzer.md
index cb8197fed2..da25f247fc 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/geolyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/geolyzer.md
@@ -1,6 +1,6 @@
# Геоанализатор
-
+
Геоанализатор используется [компьютерами](../general/computer.md) для сканирования плотностей блоков вокруг него. Это можно использовать для генерации карт местности и показа их на [голографическом проекторе](hologram1.md) или для обнаружения полезных блоков (руды обычно тверже земли и камня). В результаты работы анализатора добавляется некоторое количество шума. Теоретически, можно провести несколько сканирований, чтобы получить более точные результаты.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/hologram1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/hologram1.md
index b15b4e2a38..987c940fda 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/hologram1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/hologram1.md
@@ -1,6 +1,6 @@
# Голографический проектор
-
+
Голографический проектор отображает трёхмерный массив вокселей, каждый из которых может быть включен или выключен с помощью подключенного [компьютера](../general/computer.md). Проектор второго уровня имеет такое же разрешение, что и у первого уровня, но может окрасить воксели в один из трёх указанных пользователем цветов.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/keyboard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/keyboard.md
index a733d77cff..2859bc8a49 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/keyboard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/keyboard.md
@@ -1,6 +1,6 @@
# Клавиатура
-
+
Клавиатура необходима для набора текста на [мониторе](screen1.md), и могут стоять отдельным блоком в мире или быть встроены в такие устройства, как [роботы](robot.md) или [планшеты](../item/tablet.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/motionSensor.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/motionSensor.md
index 91a1412f66..0b70f29741 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/motionSensor.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/motionSensor.md
@@ -1,6 +1,6 @@
# Датчик движения
-
+
Датчик движения позволяет [компьютерам](../general/computer.md) замечать движение живых существ. Если существо двигается быстрее, чем заданный порог чувствительности, то будет подан сигнал в [компьютер](../general/computer.md), соединенный с датчиком движения. Вы можете задать порог срабатывания датчика через API, доступный компьютерам.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/netSplitter.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/netSplitter.md
index ae3b43a3db..1ce21141bd 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/netSplitter.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/netSplitter.md
@@ -1,6 +1,6 @@
# Сетевой переключатель
-
+
Сетевой переключатель позволяет контролировать соединение между подсетями. В отличие от [ретранслятора](relay.md) или [конвертера энергии](powerConverter.md), позволяет непосредственно соединить подсети, делая при этом доступными все компоненты. Соединение каждой стороны переключается [ключом](../item/wrench.md). При подаче сигнала красного камня все соединения инвертируются.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerConverter.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerConverter.md
index c284b3233c..00a120f6f6 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerConverter.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerConverter.md
@@ -1,5 +1,5 @@
# Конвертер энергии
-
+
Конвертер энергии - это самый быстрый способ преобразования энергии других модов во внутреннюю энергию OpenComputers. Если вы запустите простой компьютер, вероятно, вам не понадобится конвертер. Если у вас есть большой конденсатор, который разражается только время от времени, вам тоже он может не понадобиться. Однако если вы хотите подвести энергию к [сборщику](assembler.md) или [зарядному устройству](charger.md), хорошей идеей будет подключить их через конвертер, чем напрямую.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerDistributor.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerDistributor.md
index 23c2b550cd..4e344d6d7c 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerDistributor.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/powerDistributor.md
@@ -1,5 +1,5 @@
# Распределитель энергии
-
+
Распределитель энергии распределяет энергию в хранилищах (таких как [конденсатор](capacitor.md)) между подсетями, что позволяет им обмениваться энергией без подключения компонентов к омьпютерам других подсетей. Это достигается "балансированием" энергии во всех подключенных подсетях, поддерживая одинаковым *относительное* количество энергии в них.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/printer.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/printer.md
index 93c423eb60..7dba3c37d7 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/printer.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/printer.md
@@ -1,6 +1,6 @@
# 3D принтер
-
+
3D принтеры позвляют распечатать любой блок любой формы и текстуры. Для начала работы с 3D принтерами вы должны поместить блок 3D принтера рядом с компьютером. Это предоставит доступ к API компонента `printer3d`, позволяющего создавать и печатать [3D модели](print.md) с использованием предоставленные функции.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/rack.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/rack.md
index e0b4be02ce..50de71c993 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/rack.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/rack.md
@@ -1,6 +1,6 @@
# Стойка
-
+
Стойка может содержать до 4 подключемых устройств, как: [серверы](../item/server1.md), [серверы терминалов](../item/terminalServer.md) и [подключаемые дисководы](../item/diskDriveMountable.md). Соединение между монтируемыми устройствами может быть настроено с помощью интерфейса стойки. В частности, если [серверы](../item/server1.md) содержат компоненты, которые поддерживают работу с сетью, такие как [сетевые карты](../item/lanCard.md), то можно установить стороны сетевых соединений. Такие соединения будут служить только для передачи сетевых сообщений, компоненты через них доступны не будут. Они отличаются более тонкой линией, чем у "основных", которые предоставляют доступ к компонентам. Каждое внутреннее соединение должно быть между монтируемым устройством (или компонентом в нем) и шиной, соединенной со стороной стойки. Для соеднинения вместе нескольких подключаемых устройств подключите их на одну общую шину.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/raid.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/raid.md
index cb4fd9dc70..00ff822665 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/raid.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/raid.md
@@ -1,6 +1,6 @@
# RAID
-
+
Блок RAID может содержать 3 [жестких диска](../item/hdd1.md), объединенных в единую файловую систему. Объединённая файловая система имеет размер, равный сумме объемов памяти отдельных [жестких дисков](../item/hdd1.md), и доступна всех [компьютеров](../general/computer.md), подключенных к RAID.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/redstone.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/redstone.md
index 73e2ce0c7c..3edc00160c 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/redstone.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/redstone.md
@@ -1,6 +1,6 @@
# Красный контроллер
-
+
Красный контроллер используется для считывания и подачи сигнала красного камня. Он ведет себя как гибрид [плат на красном камне](../item/redstoneCard1.md) 1 и 2 уровней: может работать с обычными аналоговыми сигналами и с многожильными кабелями, но не может считывать и подавать беспроводные сигналы красного камня.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/relay.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/relay.md
index 0645ca5229..e7f4b1118f 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/relay.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/relay.md
@@ -1,6 +1,6 @@
# Ретранслятор
-
+
Ретранслятор используется для передачи сообщений между несколькими подсетями без предоставления компонентов [компьютерам](../general/computer.md) в других подсетях. Как правило, изоляция компонентов - хорошая идея, чтобы не позволить [компьютерам](../general/computer.md) использовать не тот [монитор](screen1.md) или избежать достижения лимита компонентов (в результате чего [компьютеры](../general/computer.md) выключатся и отказываются загружаться).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/screen1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/screen1.md
index 7d57166600..39456ae687 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/screen1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/screen1.md
@@ -1,6 +1,6 @@
# Монитор
-
+
Монитор используется совместно с [видеокартой](../item/graphicsCard1.md), чтобы позволить [компьютеру](../general/computer.md) отображатьа текст. Разные уровни мониторов имеют разные возможности, такие как разное разрешение и глубина цвета. Они варьируются от монохромных мониторов низкого разрешения до мониторы высокого разрешения, поддерживающих 256 цветов соответственно.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/switch.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/switch.md
index 559d2f3ae2..5e3b8ca1ba 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/switch.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/switch.md
@@ -1,6 +1,6 @@
# Коммутатор
-
+
*Этот блок устарел и будет удален в следующих версиях.* Замените его на [ретранслятор](relay.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/transposer.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/transposer.md
index 9ebae6c138..b4e2441175 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/transposer.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/transposer.md
@@ -1,6 +1,6 @@
# Транспозер
-
+
Транспозер заполняет пробел между воронками, контролируемыми сигналом красного камня, и [роботами](robot.md), позволяя [компьютерам](../general/computer.md) контролировать перемещение предметов и жидкостей между соседними блоками.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/block/waypoint.md b/src/main/resources/assets/opencomputers/doc/ru_ru/block/waypoint.md
index 013f7f9057..4bcfa00a3d 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/block/waypoint.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/block/waypoint.md
@@ -1,6 +1,6 @@
# Путевая точка
-
+
[Навигационное улучшение](../item/navigationUpgrade.md) может обнаруживать путевые точки, что позволяет устройствам с этим улучшением ориентироваться в игровом мире. Это можно использовать для написания программ для [роботов](robot.md) и [дронов](../item/drone.md), которые просто могут быть переиспользованы.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/general/example.md b/src/main/resources/assets/opencomputers/doc/ru_ru/general/example.md
index 6804e5b741..dac2b44b6a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/general/example.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/general/example.md
@@ -4,13 +4,13 @@


*Это* текст *курсивом*, ~~зачеркнутый~~, может быть, **немного** текста **жирным**. Это _подчеркнутый текст_? А, нет, _снова курсив!_ Хорошо, вот [ссылка](../index.md).
-
+
## Заголовок второго уровня [снова со *ссылкой*, но __немного__ длиннее](../block/adapter.md)
-
+
какой-то текст прямо над изображением для тестирования отступов
-
+
какой-то текст сразу под изображением для тестирования отступов
Это *две
@@ -42,9 +42,9 @@ asdasd  qweqwe
И наконец, [это ссылка!](https://avatars1.githubusercontent.com/u/514903).
-
-
-
+
+
+
тест переносов
12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
@@ -53,17 +53,17 @@ asdasd  qweqwe
* 12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
- `123456789012345678901234567890.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890`
-Это тест картинки в тексте kakakakalalsd 123 as
+Это тест картинки в тексте kakakakalalsd 123 as
-Это один тест
+Это один тест
картинки, после которой переход на следующую строку
Это один тест
-
+
изображения между двумя пустыми строками
Тест
-
+
картинками между двумя пустыми строками
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/general/quickstart.md b/src/main/resources/assets/opencomputers/doc/ru_ru/general/quickstart.md
index 949024b1c5..2ff4e8499c 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/general/quickstart.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/general/quickstart.md
@@ -6,7 +6,7 @@
Вначале вам понадобится [системный блок](../block/case1.md). Этот блок будет содержать все компоненты, определяющие поведение собираемого компьютера.
-
+
Например, вам потребуется выбрать, какого уровня [видеокарту](../item/graphicsCard1.md) вы будете использовать, нужна ли вам [сетевая](../item/lanCard.md) карта, [плата на красном камне](../item/redstoneCard1.md) или даже [карта отладки](../item/debugCard.md), если вы играете в творческом режиме.
@@ -37,7 +37,7 @@
Он ожил! В любом случае, должен был. Если этого не произошло, значит, что-то пошло не так, и нужно искать ошибку с помощью [анализатора](../item/analyzer.md). Но предпологая, что компьютер заработал, вы почти закончили. Самая сложная часть позади. Теперь осталось заставить его принимать ввод и выводить какой-то результат.
Чтобы [компьютер](computer.md) мог выводить информацию, вы должны установить [монитор](../block/screen1.md) и [видеокарту](../item/graphicsCard1.md).
-
+
Установите [монитор](../block/screen1.md) рядом с [системным блоком](../block/case1.md) или, опять же, подключите его с помощью [кабеля](../block/cable.md). После чего установите [видеокарту](../item/graphicsCard1.md) по вашему выбору в [системный блок](../block/case1.md). Теперь вы должны увидеть мигающий курсор на [мониторе](../block/screen1.md). Наконец, поставьте [клавиатуру](../block/keyboard.md) перед [монитором](../block/screen1.md) или на одну из его сторон, чтобы получить возможность вводить текст с [клавиатуры](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/abstractBusCard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/abstractBusCard.md
index b1cf6f50ca..a924e6e4af 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/abstractBusCard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/abstractBusCard.md
@@ -1,5 +1,5 @@
# Карта абстрактной шины
-
+
Карта позволяет [компьютерам](../general/computer.md), [серверам](server1.md) и [роботам](../block/robot.md) взаимодействовать с абстрактной шиной из мода StargateTech2. При установке карты устройства подключаются к абстрактной шине и получают доступ к компонента, который позволяет передавать сообщения через шину. Входящие сообщения шины конвертируются в сигналы, которые получают устройства.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/acid.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/acid.md
index 52a2ebf757..d18b613fb8 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/acid.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/acid.md
@@ -1,6 +1,6 @@
# Кислота
-
+
Это вкусное [нет авторитетного источника] варево можно употребить, когда вам когда-либо вдруг захочется немного... веселья. Или пищевого отравления. Или и того и другого. Также может служить ингредиентом в других, более полезных вещах.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/alu.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/alu.md
index 82b3ce1769..8d84c5b309 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/alu.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/alu.md
@@ -1,5 +1,5 @@
# Арифметико-логическое устройство
-
+
Используется для крафта компонентов, выполняющие вычисления, например, [процессоров](cpu1.md) и [видеокарт](graphicsCard1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/analyzer.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/analyzer.md
index bcee402e6c..bc4e41602d 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/analyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/analyzer.md
@@ -1,6 +1,6 @@
# Анализатор
-
+
Анализатор - это ручной инструмент, предназначенный для получения информации о блоках OpenComputers. Просто нажмите по блоку (приседая, если требуется), и информация будет выведена в чат. В зависимости от блока вы можете получить от адреса компонента до уровня энергии в подсети, в которой находится блок, и, например, ошибки, приведшей к сбою [компьютера](../general/computer.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/angelUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/angelUpgrade.md
index 81eacb3c64..d8ab8444e2 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/angelUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/angelUpgrade.md
@@ -1,5 +1,5 @@
# "Ангельское" улучешение
-
+
Данное улучшение позволяет [роботам](../block/robot.md) ставить блоки прямо в воздухе, без соседнего блока.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/apu1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/apu1.md
index ee5d488bd2..7cab16580c 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/apu1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/apu1.md
@@ -1,6 +1,6 @@
# Процессор с видеокартой (APU)
-
+
Это результат объединения [процессора](cpu1.md) и [видеокарты](graphicsCard1.md). Позволяет вам освободить один слот для карт в устройстве. Как и обычный процессор, он определяет архитектуру [компьютера](../general/computer.md) и максимальное количество компонентов, которые могут быть подключены к [компьютеру](../general/computer.md). Помимо этого, он предоставляет функции видеокарты.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/arrowKeys.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/arrowKeys.md
index bc2f5434c3..33f8de7455 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/arrowKeys.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/arrowKeys.md
@@ -1,5 +1,5 @@
# Клавиши со стрелками
-
+
Это необходимый элемент для крафта [клавиатуры](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/batteryUpgrade1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/batteryUpgrade1.md
index 4d8aef90be..a53368c876 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/batteryUpgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/batteryUpgrade1.md
@@ -1,5 +1,5 @@
# Улучшение "Ёмкость"
-
+
Данное улучшение увеличивает емкость внутреннего энергохранилища, что позволяет [роботам](../block/robot.md) и [планшетам](tablet.md) работать гораздо дольше без [зарядки](../block/charger.md). Чем выше уровень улучешния, тем больше энергии он может хранить.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/buttonGroup.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/buttonGroup.md
index 0774888dfc..442053f360 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/buttonGroup.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/buttonGroup.md
@@ -1,5 +1,5 @@
# Группа кнопок
-
+
Необходимый компонент для крафта [клавиатуры](../block/keyboard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/card.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/card.md
index d24d9c28dc..7e714e929b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/card.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/card.md
@@ -1,5 +1,5 @@
# Карта
-
+
Обычный компонент для крафта карт в OpenComputers (например, [видеокарт](graphicsCard1.md), [сетевых карт](lanCard.md) и т. д.).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/cardContainer1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/cardContainer1.md
index e3d4afb361..2ac73a976a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/cardContainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/cardContainer1.md
@@ -1,5 +1,5 @@
# Контейнер для карт
-
+
Контейнер для карт - улучшение-контейнер для [роботов](../block/robot.md), позволящее вставлять и извлекать карты из [роботов](../block/robot.md) без пересборки. Максимальный уровень карты равен уровню контейнера. В отличие от обычных улучшений, требуемая сложность сборки двойная. Подробнее о сложности сборки смотрите [здесь](../block/robot.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/chamelium.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/chamelium.md
index f3fcb6d078..fcbb0aa6af 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/chamelium.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/chamelium.md
@@ -1,6 +1,6 @@
# Хамелиум
-
+
Хамелиум - основной материал, используемый для создания [3D моделей](../block/print.md) на [3D принтерах](../block/printer.md). Сам по себе он однороден, а потому очень полезен для создания простых гладких одноцветных поверхностей.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/chip1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/chip1.md
index 9b74bd5493..433547a3c5 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/chip1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/chip1.md
@@ -1,5 +1,5 @@
# Микрочипы
-
+
Микрочипы - основа всех электронных компонентов в OpenComputers. Они имеют различные уровни для крафта компонентов разных уровней.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/chunkloaderUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/chunkloaderUpgrade.md
index 37153d017d..b18e991646 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/chunkloaderUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/chunkloaderUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Загрузчик чанков"
-
+
Это улучшение может быть установлено в устройства (например, в [роботов](../block/robot.md) и [микроконтроллеры](../block/microcontroller.md)), чтобы они могли загружать чанки, в которых они находятся, а также соседние чанки. Однако на это требуется энергия. Загрузчик чанков может быть включен или выключен через API компонента.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/circuitBoard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/circuitBoard.md
index 8dd3874677..66a0fc8962 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/circuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/circuitBoard.md
@@ -1,5 +1,5 @@
# Нетравленая печатная плата
-
+
Промежуточный предмет, сделанный из [основы для печатной платы](rawCircuitBoard.md). Используется для создания [печатной платы](printedCircuitBoard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/componentBus1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/componentBus1.md
index d3d38c6d15..9e1eb5e392 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/componentBus1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/componentBus1.md
@@ -1,6 +1,6 @@
# Компонентая шина
-
+
Компонентная шина - это [серверное](server1.md) улучшение, которое позволяет подключать к [серверу](server1.md) большее количество компонентов. Как и с [процессорами](cpu1.md), чем выше уровень шины, тем большее число компонентов можно подключить. Кроме того, чем выше уровень [сервера](server1.md), тем больше компонентных шин вы сможете вставить, что позволяет работать с еще большим числом компонентов.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/controlUnit.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/controlUnit.md
index 46ca8cd031..b0b1cdeffb 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/controlUnit.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/controlUnit.md
@@ -1,5 +1,5 @@
# Блок управления
-
+
Предмет, используемый при создании более продвинутых схем, например [процессоров](cpu1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/cpu1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/cpu1.md
index 566305e3cc..4d612bfdb3 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/cpu1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/cpu1.md
@@ -1,6 +1,6 @@
# Процессор
-
+
Основа всех [компьютеров](../general/computer.md) и [серверов](server1.md). Определяет архитектуру [компьютера](../general/computer.md) и максимальное число компонентов, которые могут быть к нему подключены. Чем выше уровень процессора, тем больше [компьютер](../general/computer.md) может вызывать прямых методов в тик - проще говоря, чем лучше процессор, тем быстрее он работает.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/craftingUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/craftingUpgrade.md
index c8fcab4001..edb8f1d583 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/craftingUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/craftingUpgrade.md
@@ -1,5 +1,5 @@
# Улучшение "Верстак"
-
+
Это улучшение позволяет [роботам](../block/robot.md) крафтить предметы с помощью предметов из своего [инвентаря](../item/inventoryUpgrade.md). Для крафта используется сетка слотов 3x3 в левом верхнем углу [инвентаря](../item/inventoryUpgrade.md) [робота](../block/robot.md). Предметы должны быть расположены в соответствии с рецептом. Результаты крафта будут помещены в [инвентарь](../item/inventoryUpgrade.md) [робота](../block/robot.md) — в выбранный слот; если же он заполнен, тогда используется следующий слот. В случае если место в инвентаре закончилось, результаты крафта будут выброшены в мир.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/cuttingWire.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/cuttingWire.md
index cb749af497..046220597d 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/cuttingWire.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/cuttingWire.md
@@ -1,5 +1,5 @@
# Проволока
-
+
Если включены сложные рецепты, нужна для создания [основы для печатной платы](rawCircuitBoard.md) - очень неэффективного.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/dataCard1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/dataCard1.md
index 5c68b6aec5..2d5c539c22 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/dataCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/dataCard1.md
@@ -1,6 +1,6 @@
# Карта данных
-
+
Карта данных предоставляет несколько алгоритмов, которые труднореализуемы или работают медленнее на архитектуре компьютеров, например хэширование и inflate/deflate.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/databaseUpgrade1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/databaseUpgrade1.md
index 79a1149633..4ab094448d 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/databaseUpgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/databaseUpgrade1.md
@@ -1,6 +1,6 @@
# Улучшение "База данных"
-
+
Улучшение может быть настроено на хранение списка предметов, которые могут быть использованы другими компонентами. Это особенно полезно для элементов, отличающиеся только NBT-данными, которые не возвращаются методами компонентов.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/debugCard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/debugCard.md
index 11100abfd0..31d6af7079 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/debugCard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/debugCard.md
@@ -1,6 +1,6 @@
# Отладочная карта
-
+
Отладочная карта - это творческий предмет, который изначально был предназначен для упрощения отладки мода за счет автоматизации некоторых процессов. С тех пор она обрела большую функциональность, что делает ее полезным инструментом для создания карт.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/disk.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/disk.md
index 6241df1ba8..90bbb20ac8 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/disk.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/disk.md
@@ -1,5 +1,5 @@
# Диск
-
+
Базовый компонент для создания устройств хранения информации, таких как [дискеты](floppy.md) и [жесткие диски](hdd1.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/diskDriveMountable.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/diskDriveMountable.md
index b9bedfd6dc..2624b86a04 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/diskDriveMountable.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/diskDriveMountable.md
@@ -1,5 +1,5 @@
# Дисковод для серверной стойки
-
+
Аналог обычного [дисковода](../block/diskDrive.md), за исключением того, что он установливается в [стойку](../block/rack.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/drone.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/drone.md
index 48679a7305..2451397a04 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/drone.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/drone.md
@@ -1,5 +1,5 @@
# Дрон
-
+
Дроны собираются из [корпуса дрона](droneCase1.md) в [сборщике](../block/assembler.md). По сути, они являются [роботами](../block/robot.md) в виде сущностей, но с меньшим функционалом. Они также могут перемещаться по диагонали и гораздо быстрее, чем [роботы](../block/robot.md). Они обычно контролируются с помощью программы на [компьютере](../general/computer.md). Дроны могут быть сконфигурированы с помощью [EEPROM](eeprom.md) для выполнения различных комманд.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/droneCase1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/droneCase1.md
index 5c2eaa7e9b..205d25973a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/droneCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/droneCase1.md
@@ -1,6 +1,6 @@
# Корпус дрона
-
+
Корпус дрона используется для создания [дронов](drone.md) в [сборщике](../block/assembler.md). [Дроны](drone.md) - легковесные, быстрые и очень мобильные устройства с ограниченной функциональностью (доступно меньше слотов для компонентов и улучешний). В отличие от [роботов](../block/robot.md), они не могут использовать инструменты и взаимодействуют с игровым миром ограниченно.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/eeprom.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/eeprom.md
index 5401ec2098..912bb35274 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/eeprom.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/eeprom.md
@@ -1,6 +1,6 @@
# EEPROM
-
+
EEPROM содержит код, который позволяет загрузить компьютер. Эти данные хранятся в виде простого массива байтов и могут означать разные вещи на [процессорах](cpu1.md) разных архитектур. Например, для Lua это обычно маленький скрипт, который ищет сценарий инициализации в файловой системе, но для других архитектур это может быть сам машинный код.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/experienceUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/experienceUpgrade.md
index 86bdcba68e..0a461192ef 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/experienceUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/experienceUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Опыт"
-
+
Данное улучшение особенное, оно позволяет [роботам](../block/robot.md) и [дронам](drone.md) получать опыт за выполнение различных действий, таких как добыча руд и убийство животных. Одно улучшение может хранить до 30 уровней опыта, предоставляя различные бонусы с каждым уровнем, включая увеличение скорости ломания блоков или увеличения энергохранилища.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/floppy.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/floppy.md
index 47fec655ff..96a6e234e9 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/floppy.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/floppy.md
@@ -1,5 +1,5 @@
# Дискета
-
+
Дискета - это самое простое и дешевое средство хранения информации в OpenComputers, удобное на начальных этапах для переноса программ между [компьютерами](../general/computer.md) и [роботами](../block/robot.md). Вы также можете найти дискеты с программами в сокровищницах.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/generatorUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/generatorUpgrade.md
index f25426218d..774a290ca6 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/generatorUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/generatorUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Генератор"
-
+
Улучшение позволяет устройствам самозаряжаться за счёт твердого топлива, например угля. Внутренний инвентарь генератора может хранить один стак топлива. Топливо может быть убрано из генератора с помощью метода API компонента. Если вынуть генератор из [робота](../block/robot.md), его содержимое выпадает в игровой мир.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/graphicsCard1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/graphicsCard1.md
index 16321f466d..494bc42212 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/graphicsCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/graphicsCard1.md
@@ -1,6 +1,6 @@
# Видеокарта
-
+
Видеокарта является неотъемлемой частью большинства [компьютеров](../general/computer.md) и позволяет им выводить изображение на подключенный [монитор](../block/screen1.md). Видеокарты имеют несколько уровней, как и [мониторы](../block/screen1.md), и в зависимости от него поддерживают различные разрешения и глубину цвета.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/hdd1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/hdd1.md
index d1696e3da3..45e9f028ae 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/hdd1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/hdd1.md
@@ -1,5 +1,5 @@
# Жесткий диск
-
+
Жесткие диски - это продвинутое хранилище информации в OpenComputers. Все виды жестких дисков имеют одинаковую скорость работы, но разную емкость. Некоторые устройства могут использовать только жесткие диски (хотя серверы могут, например, использовать внешний [дисковод](../block/diskDrive.md)). Жесткие диски могут быть объединены в [RAID](../block/raid.md), благодаря чему несколько дисков будут работать как один большой. При объединении жестких дисков в [RAID](../block/raid.md) вся информация на них будет стерта.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverBoots.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverBoots.md
index 075ed791d6..8ae7c92d0b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverBoots.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverBoots.md
@@ -1,6 +1,6 @@
# Парящие ботинки
-
+
Если не хочется программировать [дронов](drone.md), то их можно использовать как роликовые коньки. Что-то вроде такого.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverUpgrade1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverUpgrade1.md
index e3b3491998..044f90bf91 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverUpgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/hoverUpgrade1.md
@@ -1,6 +1,6 @@
# Улучшение "Парение"
-
+
Это улучшение позволяет [роботам](../block/robot.md) летать гораздо выше над землёю, чем обычно. В отличие от [дронов](drone.md), максимальная высота их полета ограничена 8 блоками по умолчанию. Обычно это не доставляет больших проблем, потому что они все также могут двигаться по стенам и просто вверх. Правила их передвижения могут быть сведены к следующему:
- Робот будет двигаться при условии, что или стартовая, или конечная точки являются разрешёнными.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/inkCartridge.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/inkCartridge.md
index 5e930f44fe..ef5049992a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/inkCartridge.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/inkCartridge.md
@@ -1,5 +1,5 @@
# Картридж с чернилами
-
+
Картридж с чернилами используется для цветной печати в [3D принтерах](../block/printer.md). Также можно перезаправить их, используя краски, но это очень неэффективно.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/internetCard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/internetCard.md
index 7c690d506e..598ecd71f2 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/internetCard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/internetCard.md
@@ -1,5 +1,5 @@
# Интернет карта
-
+
Интернет карта позволяет [компьютерам](../general/computer.md) выходить в интернет. Она позволяет выполнять простые HTTP запросы, а также открывать, читать и писать в TCP сокеты.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/interweb.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/interweb.md
index 2b1bac91e9..b77c73dbc6 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/interweb.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/interweb.md
@@ -1,5 +1,5 @@
# Интерпаутина
-
+
Основной компонент для приборов дальней связи. Интерпаутина использует странную механику, основанную на квантовой передаче сообщений через мир Края. В основном используется при создании [интернет карт](internetCard.md) и [соединенных карт](linkedCard.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryControllerUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryControllerUpgrade.md
index f5495bd6cb..200dfb7c2a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryControllerUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryControllerUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Контроллер инвентаря"
-
+
Контроллер инвентаря предоставляет [роботам](../block/robot.md) и [дронам](drone.md) возможность выполнять еще больше действий с инвентарем. Это позволяет устройству явно указывать слоты при перемещении предметов из или во внешний инвентарь, получать подробную информацию о стаках предметов и, наконец, позволяет [роботам](../block/robot.md) самим менять инструмент.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryUpgrade.md
index d63e13487c..ba711e7501 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/inventoryUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Инвентарь"
-
+
Улучшение позволяет добавить слоты инвентаря для [роботов](../block/robot.md) и [дронов](drone.md). Каждое улучшение дает [роботу](../block/robot.md) 16 дополнительных слотов - до 64 слотов максимум; [дронам](drone.md) даёт 4 слота с каждым апгрейдом - максимально до 8 слотов.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/lanCard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/lanCard.md
index 7e9cee5fcd..728a12f22e 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/lanCard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/lanCard.md
@@ -1,5 +1,5 @@
# Сетевая карта
-
+
Сетевая карта позволяет [компьютерам](../general/computer.md) отправлять и получать сетевые сообщения. Сообщения (или пакеты) могут быть отправлены либо всем принимающим устройствам в подсети, либо конкретной сетевой карте с определённым адресом. [Ретрансляторы](../block/relay.md) могут быть использованы для связи нескольких подсетей друг с другом и передачи сообщений. Также возможно отправить письмо получателю в другой подсети, если сети соединены одним или несколькими [ретрансляторами](../block/relay.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/leashUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/leashUpgrade.md
index 5fdfd693be..384189818e 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/leashUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/leashUpgrade.md
@@ -1,5 +1,5 @@
# Улучшение "Поводок"
-
+
Позволяет привязывать животных к различным устройствам, например [дронам](drone.md). Одновременно можно привязать несколько животных, что делает это довольно удобным для перемещения стад.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/linkedCard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/linkedCard.md
index e52f7545ef..b2b7bf651b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/linkedCard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/linkedCard.md
@@ -1,5 +1,5 @@
# Соединенные карты
-
+
Соединенная карта - это специализированная, но продвинутая версия [сетевой карты](lanCard.md). Они могут работать только в паре, образуя прямое соединение между картами. Соединенные карты могут передавать данные через большие (точнее, бесконечные) расстояния, а также между измерениями.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/manual.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/manual.md
index 863f53a9bf..9e3c9ba0a0 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/manual.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/manual.md
@@ -1,6 +1,6 @@
# Руководство
-
+
То, что вы сейчас читаете. В руководстве собрана информация об OpenComputers. Если вы хотите что-либо узнать о блоке или предмете из этого мода, это то, что вам нужно! Пролистните вниз с помощью колёсика мыши, чтобы узнать, как пользоваться руководством.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/mfu.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/mfu.md
index 4d186fe01c..e90af6d64a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/mfu.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/mfu.md
@@ -1,6 +1,6 @@
# МФУ
-
+
Это улучшение работает как удаленный [адаптер](../block/adapter.md). Приседая, кликните на любую сторону какого-либо блока, чтобы привязать МФУ к нему. Потом поместите его в адаптер (расстояние очень ограничено), и он будет действовать так, будто адаптер расположен рядом со стороной блока, к которой вы его привязали.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/microcontrollerCase1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/microcontrollerCase1.md
index 7003d6414b..7daf4d553b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/microcontrollerCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/microcontrollerCase1.md
@@ -1,6 +1,6 @@
# Корпус микроконтроллера
-
+
Корпус микроконтроллера используется для создания [микроконтроллеров](../block/microcontroller.md) в [сборщике](../block/assembler.md). [Микроконтроллеры](../block/microcontroller.md) - это очень примитивные [компьютеры](../general/computer.md). Они содержат только очень ограниченный набор компонентов и используются в специфических задачах: реагирование на сигнал красного камня или обработка сетевых сообщений.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/nanomachines.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/nanomachines.md
index 6a4dffe3f5..4a4f7298c2 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/nanomachines.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/nanomachines.md
@@ -1,6 +1,6 @@
# Нанороботы
-
+
Это миниатюрные устройства, которые интегрируются с вашей нервной системой, чтобы сделать вас сильнее, лучше и быстрее или убить вас. Иногда все вместе. Проще говоря, нанороботы предоставляют систему, работающую на энергии и дающие игроку положительными (и отрицательными) эффектами. Съешьте нанороботов, чтобы ввести их в организм.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/navigationUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/navigationUpgrade.md
index cf557b5fce..98efaf2110 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/navigationUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/navigationUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Навигация"
-
+
Данное улучшение предоставляет информацию о местоположении и ориентации устройствам. Получаемые координаты относительны к центру карты, использованной при создании улучшения, а радиус функционирования зависит от размера карты.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/numPad.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/numPad.md
index c3e4387d0c..3f74ad7613 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/numPad.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/numPad.md
@@ -1,5 +1,5 @@
# Цифровой блок клавиш
-
+
Цифровая клавиатура - часть любой [клавиатуры](../block/keyboard.md). Позволяет вводить цифры.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/pistonUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/pistonUpgrade.md
index 7e53fa66ec..fef1f2050b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/pistonUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/pistonUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Поршень"
-
+
Улучшение "Поршень" позволяет некоторым устройствам работать так же, как и обычный поршень. После установки станет доступен компонент с одним методом - `push()`. При вызове данного метода устройство попытается сдвинуть блок, находящийся перед ним. Для [роботов](../block/robot.md) и [микроконтроллеров](../block/microcontroller.md) это передняя сторона; для [планшетов](tablet.md) будет использовано направление, куда смотрит игрок.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/printedCircuitBoard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/printedCircuitBoard.md
index e6a70c6eea..f3b756afd0 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/printedCircuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/printedCircuitBoard.md
@@ -1,5 +1,5 @@
# Печатная плата
-
+
Один из самых базовых компонентов крафта в OpenComputers вместе с [транзистором](transistor.md). Используется как основа для множества компонентов: [карт](card.md) и большого количества [блоков](../block/index.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/ram1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/ram1.md
index 4333ea6416..1dcc2f568a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/ram1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/ram1.md
@@ -1,6 +1,6 @@
# Оперативная память
-
+
Память, как и [процессор](cpu1.md), - неотъемлемая часть всех [компьютеров](../general/computer.md). В зависимости от архитектуры [процессора](cpu1.md), именно память отвечает за то, что [компьютеры](../general/computer.md) могут делать, а что нет. Для стандартной архитектуры Lua, например, это позволяет контролировать количество памяти, которое могут использовать Lua-скрипты. Это значит, что для запуска больших и требовательных программ вам потребуется больше памяти.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/rawCircuitBoard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/rawCircuitBoard.md
index 79622624e1..58c0b80376 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/rawCircuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/rawCircuitBoard.md
@@ -1,5 +1,5 @@
# Основа для печатной платы
-
+
Компонент крафта, использующийся для создания [печатной платы](circuitBoard.md) (или [отпечатанной печатной платы](printedCircuitBoard.md), в зависимости от используемых набора рецептов).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/redstoneCard1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/redstoneCard1.md
index 8eeb418aba..4dcd219067 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/redstoneCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/redstoneCard1.md
@@ -1,6 +1,6 @@
# Плата на красном камне
-
+
Карта на красном камне позволяет [компьютерам](../general/computer.md) считывать и подавать аналоговый сигнал красного камня в прилегающие блоки. Когда сила входящего сигнала изменяется, [компьютер](../general/computer.md) получает соответствующий сигнал.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/server1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/server1.md
index 7b3813cccd..35518881f8 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/server1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/server1.md
@@ -1,6 +1,6 @@
# Сервер
-
+
Серверы - это форма [компьютеров](../general/computer.md) более высокого уровня. Они могут быть настроены кликом, держа в руке, - как при открытии рюкзака, например, - а также после установки в [стойку](../block/rack.md) и клику (нацелившись на лицевую сторону сервера в [стойке](../block/rack.md)). Для работы сервер должен быть помещен в [стойку](../block/rack.md). Подробнее читайте на странице о [стойке](../block/rack.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/signUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/signUpgrade.md
index 99cc364443..02123d4ebb 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/signUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/signUpgrade.md
@@ -1,5 +1,5 @@
# Улучшение "Контроллер табличек"
-
+
Данное улучшение позволяет устройствам взаимодействовать с табличками в мире: читать текст на табличке, а также менять его, если разрешено.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/solarGeneratorUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/solarGeneratorUpgrade.md
index 6fdc5f4687..aecbd5d086 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/solarGeneratorUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/solarGeneratorUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Солнечная панель"
-
+
Данное улучшение может быть установлено в такие устройства, как: [роботы](../block/robot.md), [дроны](drone.md), [планшеты](tablet.md) - для пассивной генерации энергии. Генерация энергии происходит только под прямыми лучами солнца и не происходит в дождь или в помещении.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tablet.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tablet.md
index 0c6ee06439..39dc35d73b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tablet.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tablet.md
@@ -1,6 +1,6 @@
# Планшет
-
+
Планшеты можно создать, если поместить [корпус планшета](tabletCase1.md) в [сборщик](../block/assembler.md), добавить компоненты и собрать. Планшеты работают как переносные компьютеры, которые не могут напрямую взаимодействовать с игровым миром: например, простые [платы на красном камне](redstoneCard1.md) не работают с ними. Также не могут с ними работать некоторые улучшения: [контроллер табличек](signUpgrade.md) или [поршень](pistonUpgrade.md), для примера.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tabletCase1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tabletCase1.md
index f75bf0ada8..ea4820704c 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tabletCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tabletCase1.md
@@ -1,6 +1,6 @@
# Корпус планшета
-
+
Корпус планшета используется для создания [планшетов](tablet.md) в [сборщике](../block/assembler.md). [Планшеты](tablet.md) - миниатюрные и переносимые [компьютеры](../general/computer.md). В них можно установить некоторые улучшения, но они не могут взаимодействовать с игровым миром, как [системный блок](../block/case1.md) (использовать простые [сетевые карты](lanCard.md) или [плату на красном камне](redstoneCard1.md)).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankControllerUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankControllerUpgrade.md
index e8f85b1413..050a827e54 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankControllerUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankControllerUpgrade.md
@@ -1,6 +1,6 @@
# Улучшение "Контроллер бака"
-
+
Контроллер бака аналогичен [контроллеру инвентаря](inventoryControllerUpgrade.md), но для жидкостей. Позволяет устройствам получать подробную информацию о баках и их содержимом.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankUpgrade.md
index 3d12be6303..3e8be279b9 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tankUpgrade.md
@@ -1,5 +1,5 @@
# Улучшение "Бак для жидкостей"
-
+
Позволяет устройствам хранить жидкости. Каждый бак может хранить жидкость только одного типа и объемом не более 16 ведер (16000mB). [Роботы](../block/robot.md) и [дроны](drone.md) могут выкачивать жидкости из игрового мира, а также из других баков. Затем они могут снова заполнять баки жидкостями и обратно выливать их (если жидкость поддерживает выливание в мир). Вы можете установить любое количество улучшений этого вида в устройство.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminal.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminal.md
index 9d078bfb72..a904c6aee9 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminal.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminal.md
@@ -1,6 +1,6 @@
# Удаленный терминал
-
+
Терминал может быть использован для контроля компьютеров через [сервер терминалов](terminalServer.md). Перед использованием кликните по [серверу терминалов](terminalServer.md), установленному в [стойку](../block/rack.md) (кликнув по блоку [стойки](../block/rack.md) в мире, направляя курсор на [сервер терминалов](terminalServer.md)), чтобы привязать терминал к серверу терминалов.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminalServer.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminalServer.md
index ed65044e2e..73fcf3c81b 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminalServer.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/terminalServer.md
@@ -1,5 +1,5 @@
# Сервер терминалов
-
+
Серверы терминалов предоставляют виртуальный [монитор](../block/screen1.md) и [клавиатуру](../block/keyboard.md), которыми можно управлять через [удаленные терминалы](terminal.md). Подробнее читайте на странице о [терминале](terminal.md). Для работы установите сервер терминалов в [стойку](../block/rack.md).
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/texturePicker.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/texturePicker.md
index b4531ed3a5..cdc0a66694 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/texturePicker.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/texturePicker.md
@@ -1,6 +1,6 @@
# Определитель текстур
-
+
Данный предмет будет в первую очередь удобен при создании моделей для [3D принтеров](../block/printer.md): он позволяет узнать название текстуры блока, установленного в мире, - достаточно просто кликнуть на него. Обратите внимание, что для блоков с особым рендером, таких как сундуки, это может не сработать.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tractorBeamUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tractorBeamUpgrade.md
index 3b4683d8fe..cb23b17cf7 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tractorBeamUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tractorBeamUpgrade.md
@@ -1,5 +1,5 @@
# Улучшение "Притягивающий луч"
-
+
Данное улучшение позволяет устройствам подбирать предметы в радиусе 3 блоков вокруг себя. Это очень удобно использовать для [роботов](../block/robot.md)-фермеров, а также если они используют инструменты, ломающие сразу несколько блоков вокруг себя (как инструменты из Tinker's Construct). Каждая операция пытается подобрать один стак предметов вокруг себя, на что затрачивает некоторое количество энергии.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tradingUpgrade.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tradingUpgrade.md
index 3096648992..c77b9d6dbf 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/tradingUpgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/tradingUpgrade.md
@@ -1,5 +1,5 @@
# Улучшение "Торговля"
-
+
Данное улучшение позволяет организовать автоматическую торговлю с торговцами - например, с жителями. В качестве покупателей могут выступать как [роботы](../block/robot.md), так и [дроны](drone.md). Они могут получать информацию о доступных сделках у продавцов, а также собственно торговать.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/transistor.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/transistor.md
index 234cb23f13..e3a6b19b8a 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/transistor.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/transistor.md
@@ -1,5 +1,5 @@
# Транзистор
-
+
Самый простой элемент крафта в OpenComputers. Он используется для крафта [микрочипов](chip1.md) и иных электронных компонентов.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/upgradeContainer1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/upgradeContainer1.md
index 62252b4b63..4c826b9162 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/upgradeContainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/upgradeContainer1.md
@@ -1,5 +1,5 @@
# Контейнер для улучшения
-
+
Это улучшение-контейнер для [роботов](../block/robot.md), добавляющее собранным [роботам](../block/robot.md) слот под установку еще одного улучшения. Максимальный уровень улучшения, которое может быть установлено, равен уровню контейнера. Прочтите документацию о [роботах](../block/robot.md) и [сборщике](../block/assembler.md) для информации о требуемой сложности сборки.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/wlanCard1.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/wlanCard1.md
index 7f007d1f88..dcf99fed13 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/wlanCard1.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/wlanCard1.md
@@ -1,6 +1,6 @@
# Беспроводная сетевая карта
-
+
Беспроводная сетевая карта - это улучшенная версия [сетевой карты](lanCard.md), которая в дополнение к сообщениям по проводной линии также может принимать сообщения и по беспроводной сети. Сила сигнала напрямую контролирует, на каком расстоянии может быть получено отправленное сообщение, и равна расстоянию в блоках.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/worldSensorCard.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/worldSensorCard.md
index 8bdbbd0160..5c03c3daa2 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/worldSensorCard.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/worldSensorCard.md
@@ -1,4 +1,4 @@
# Карта-мировой сенсор
-
+
Данная карта позволяет получать информацию об атмосфере и гравитации на планетах, добавляемых модом GalactiCraft. Может быть полезно для [роботов](../block/robot.md) и [дронов](drone.md), работающих в космосе.
diff --git a/src/main/resources/assets/opencomputers/doc/ru_ru/item/wrench.md b/src/main/resources/assets/opencomputers/doc/ru_ru/item/wrench.md
index f5e4910f50..c9d3b9d3c4 100644
--- a/src/main/resources/assets/opencomputers/doc/ru_ru/item/wrench.md
+++ b/src/main/resources/assets/opencomputers/doc/ru_ru/item/wrench.md
@@ -1,5 +1,5 @@
# Ключ
-
+
Как и другие технологические моды, OpenComputers имеет свой ключ. В данном случае это гибрид ключа и отвертки, который выглядит, будто его очень неудобно использовать. Ключ может поворачивать большинство блоков; кроме того, его можно использовать вместо других ключеподобных инструментов.
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/accesspoint.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/accesspoint.md
index 968d07ff90..114439f7ea 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/accesspoint.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/accesspoint.md
@@ -1,6 +1,6 @@
# 接入点
-
+
*本方块已废弃,将会在未来版本被移除* 请在工作台中将其合成为[中继器](relay.md)以避免丢失。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/adapter.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/adapter.md
index 10625ff252..fe91645d2e 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/adapter.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/adapter.md
@@ -1,6 +1,6 @@
# 适配器
-
+
适配器令[电脑](../general/computer.md)能与原版或其他 Mod 的方块交互。支持适配器的方块在连接适配器后,将会在与适配器连接的[电脑](../general/computer.md)上以组件的形式显示出来。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/assembler.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/assembler.md
index 3043669fb7..5a2ed46b2c 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/assembler.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/assembler.md
@@ -1,6 +1,6 @@
# 装配器
-
+
装配器是个用来制作精密电子设备的高级工作台,像是[机器人](robot.md)、[无人机](../item/drone.md)和[平板](../item/tablet.md)这样的设备都需要在这里制作。组装电子设备的过程需要消耗大量能源,所以在此推荐使用[电容](capacitor.md)保证其能源供应。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/cable.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/cable.md
index 5fc4ed909d..69ad2afd44 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/cable.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/cable.md
@@ -1,6 +1,6 @@
# 线缆
-
+
用于连接相距甚远的[电脑](../general/computer.md)和设备。如果你的设备群足够紧凑,你大概不需要这玩意。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/capacitor.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/capacitor.md
index 20ba42f83a..99380578fe 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/capacitor.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/capacitor.md
@@ -1,6 +1,6 @@
# 电容
-
+
电容存储了计算机网络需要的能源,实际上就是一个以备不时之需的缓存。和使用[能源转换器](powerConverter.md)将转换其他 Mod 的能量到 OpenComputer 使用的电力不一样的是,电容传输电力的过程是瞬时的。这样一个缓存对一些能耗大的任务比较有用,比如[组装](assembler.md)或[充能](charger.md)[机器人](robot.md)和[无人机](../item/drone.md)这样的设备。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/case1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/case1.md
index 7d72bf0457..44453df734 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/case1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/case1.md
@@ -1,6 +1,6 @@
# 机箱
-
+
机箱有数个型号,决定了能装什么配件。相比于其他配件的等级,机箱还多一个用于创造模式下调试的等级。机箱还用于在[装配器](assembler.md)中组装[机器人](robot.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/chameliumblock.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/chameliumblock.md
index 56e5fa6358..084465234d 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/chameliumblock.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/chameliumblock.md
@@ -1,6 +1,6 @@
# 变色块
-
+
几块[变色材料](../item/chamelium.md)合成出装饰用的单色方块。可用染料染成原版的十六种颜色。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/charger.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/charger.md
index b939722d9d..b574503cd9 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/charger.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/charger.md
@@ -1,6 +1,6 @@
# 充电机
-
+
充电机可为[机器人](robot.md)、[无人机](../item/drone.md)和[平板](../item/tablet.md)这样的设备充能。需要用红石信号激活方能工作。充能速度被红石信号强度决定,信号强度为 15 时它会全速为设备充能。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/disassembler.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/disassembler.md
index dad952de5a..51b9be9473 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/disassembler.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/disassembler.md
@@ -1,6 +1,6 @@
# 拆解器
-
+
拆解器可以将 OpenComputers 中的绝大多数设备拆成零件。常用来回收不需要的或者制造出错的设备,比如忘了装[系统](../general/openOS.md)的[机器人](robot.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/diskdrive.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/diskdrive.md
index 5a1111633a..2809745bda 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/diskdrive.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/diskdrive.md
@@ -1,6 +1,6 @@
# 软盘驱动器
-
+
软盘驱动器与[电脑](../general/computer.md)连接后就能读[软盘](../item/floppy.md)了。这东西在初期很有用,因为低级别的[机箱](case1.md)没有内建的软盘插槽,但你需要用软盘装系统。[OpenOS](../general/openOS.md) 的安装盘可以通过用空的[软盘](../item/floppy.md) 和[手册](../item/manual.md)在工作台中合成获得。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/geolyzer.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/geolyzer.md
index ddc4dddb98..2bac3174f1 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/geolyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/geolyzer.md
@@ -1,6 +1,6 @@
# 地质分析仪
-
+
地质分析仪让电脑能扫描其周边的地形,并描述周边的方块硬度分布。其扫描结果可借助[全息投影机](hologram1.md)显示成地图,或用来寻找有价值的方块,因为矿石的硬度往往比石头大。地质分析仪的扫描结果中有些许干扰,理论上可以通过反复扫描来提高精确度。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/hologram1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/hologram1.md
index 11d7a95554..8623cdfbdf 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/hologram1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/hologram1.md
@@ -1,6 +1,6 @@
# 全息投影机
-
+
全息投影仪是个立体成像显示器,说穿了就是一个可以显示三维图形的显示器,还能被[电脑](../general/computer.md)控制。T2 的全息投影仪和 T1 的相比,分辨率不变,但是支持电脑控制每个像素的颜色。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/keyboard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/keyboard.md
index 0b5df63262..8b991073bf 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/keyboard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/keyboard.md
@@ -1,6 +1,6 @@
# 键盘
-
+
键盘自然是用来在[屏幕](screen1.md)上打字的,或者作为输入设备嵌入[机器人](robot.md)和[平板](../item/tablet.md)中。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/motionsensor.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/motionsensor.md
index 52a141ace0..aeda23e0a7 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/motionsensor.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/motionsensor.md
@@ -1,6 +1,6 @@
# 运动传感器
-
+
运动传感器允许[电脑](../general/computer.md)探测生物的移动。如果生物的移动速度超过阈值,相连的[电脑](../general/computer.md)就会收到一个信号。阈值可在相连电脑上用其组件 API 调整。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/netsplitter.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/netsplitter.md
index db9bce2180..5787fdbee6 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/netsplitter.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/netsplitter.md
@@ -1,6 +1,6 @@
# 网络分配器
-
+
网络分配器用于控制子网的连接。和[中继器](relay.md)或者[能源转换](powerConverter.md)不一样,网络分配器会与相邻的子网直接连接。每个面上的连接都可以用[螺丝刀扳手](../item/wrench.md)这样的扳手控制。红石信号可令所有连接反转。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerconverter.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerconverter.md
index 6f8922b366..8436b394d4 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerconverter.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerconverter.md
@@ -1,5 +1,5 @@
# 能量转换器
-
+
能量转换器是让 OpenComputers 使用其他 Mod 能源的最快捷的办法了。如果你只是运行一台电脑,或是一个用不了几次的大电容,你大概不需要造这个。然而如果你想直接驱动[装配机](assembler.md)或者[充电机](charger.md),那你就应该造一台这个了。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerdistributor.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerdistributor.md
index 11d8b1310d..2e1a4ac4ab 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerdistributor.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/powerdistributor.md
@@ -1,5 +1,5 @@
# 能量分配器
-
+
能量分配器能在不将组件暴露于子网中的前提下,将一个共享能源池(如[电容](capacitor.md))里的能量分配到各个组件上去。它依照负载均衡的原则工作,因此你会发现每个子网的能量供应都“差不多”。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/printer.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/printer.md
index ada5c88c7b..d2e1bb2947 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/printer.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/printer.md
@@ -1,6 +1,6 @@
# 3D 打印机
-
+
3D 打印机允许你在任何方块上用任何纹理打印出你想要的样子。首先你需要在电脑边放一台打印机,这样电脑就能使用 `printer3d` 这个 API,通过这个 API 就能控制打印机打印出[模型](print.md)了。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/rack.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/rack.md
index 928c7a6c98..5e57e35785 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/rack.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/rack.md
@@ -1,6 +1,6 @@
# 机架
-
+
机架中可以存放四台像是[服务器](../item/server1.md)、[终端服务器](../item/terminalServer.md)和[可挂载磁盘驱动器](../item/diskDriveMountable.md)这样的设备。你可以通过 GUI 来设定机架中设备的连接关系;特别的,如果服务器里面安装了网卡等组件,那么你可以设定这些服务器只暴露网络连接,而不暴露其内部组件。这样的连接在 GUI 中会以一种更细的连接表示,以与允许访问内部设备的普通连接相区分。内部连接只能在设备(或设备中的组件)与总线之间建立;若需连接多个设备,连接到一条总线上即可。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/raid.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/raid.md
index efabd666d8..4f582ef222 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/raid.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/raid.md
@@ -1,6 +1,6 @@
# Raid
-
+
Raid 磁盘阵列可将三块[硬盘](../item/hdd1.md)组成一个文件系统,组合的文件系统拥有所有硬盘容量之和的大小,并且所有与其相连的电脑都能访问。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/redstone.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/redstone.md
index 82ca6084ae..d622e0385c 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/redstone.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/redstone.md
@@ -1,6 +1,6 @@
# 红石 I/O 端口
-
+
红石 I/O 端口可用来远程读取和发射红石信号。它就像是 T1 和 T2 [红石卡](../item/redstoneCard1.md)的合体,可以收发简单的模拟信号及捆绑信号,但是无法收发无线红石信号。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/relay.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/relay.md
index 23bbcbe0cd..5ad9b80faf 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/relay.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/relay.md
@@ -1,6 +1,6 @@
# 中继器
-
+
中继器能在不把组件暴露给其他网络的[电脑](../general/computer.md)的前提下,让子网间进行网络通信。把组件限制在本地网络是个好主意,这样就不用担心[电脑](../general/computer.md)接错屏幕,或者电脑因组件过多崩溃并拒绝启动这样的怪事发生了。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/screen1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/screen1.md
index b32b23fad4..a6e9aab2c0 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/screen1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/screen1.md
@@ -1,6 +1,6 @@
# 显示屏
-
+
显示屏需要和[显卡](../item/graphicsCard1.md)一起使用,这样电脑才能显示文本。不同型号的屏幕能支持的分辨率和色深不尽相同,从低分单色屏到高分 256 色屏都有。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/switch.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/switch.md
index d8d8b291da..1ddd71b491 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/switch.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/switch.md
@@ -1,6 +1,6 @@
# Switch
-
+
*本方块已废弃,将会在未来版本被移除* 请在工作台中将其合成为[中继器](relay.md)以避免丢失。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/transposer.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/transposer.md
index d21ba56f1e..4d317259d1 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/transposer.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/transposer.md
@@ -1,6 +1,6 @@
# 转运器
-
+
转运器连接了红石控制的漏斗和[机器人](robot.md),这样[电脑](../general/computer.md)就能控制物品和流体在相邻方块之间的传输了。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/block/waypoint.md b/src/main/resources/assets/opencomputers/doc/zh_cn/block/waypoint.md
index b337317f1d..647a11eeab 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/block/waypoint.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/block/waypoint.md
@@ -1,6 +1,6 @@
# 路径点
-
+
路径点重点不在本身,而是如何使用。[导航升级](../item/navigationUpgrade.md)可以探测路径点,因此安装了这种升级的设备就可以通过路径点来导航。这在编写适用于[机器人](robot.md)和[无人机](../item/drone.md)的高度可重用程序时很有用。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/general/example.md b/src/main/resources/assets/opencomputers/doc/zh_cn/general/example.md
index 3bdda70bc6..8db963f6c1 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/general/example.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/general/example.md
@@ -4,13 +4,13 @@ This is some test text for the subset of Markdown supported by the planned ingam


*This* is *italic* text, ~~strikethrough~~ maybe abc-ter **some** text **in bold**. Is _this underlined_? Oh, no, _it's also italic!_ Well, this [a link](../index.md).
-
+
## Smaller headline [also with *link* but this __one__ longer](../block/adapter.md)
-
+
some text directly above the item stack renderer to test spacing
-
+
some text directly below the item stack renderer to test spacing
This is *italic
@@ -42,9 +42,9 @@ asdasd  qweqwe
And finally, [this is a link!](https://avatars1.githubusercontent.com/u/514903).
-
-
-
+
+
+
wrap testing
12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
@@ -53,17 +53,17 @@ wrap testing
* 12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
- `123456789012345678901234567890.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890`
-this is a test for anan inline image kakakakalalsd 123 as
+this is a test for anan inline image kakakakalalsd 123 as
-this is a test for an
+this is a test for an
an image with a break after it
this is a test for an
-
+
an image between two lines
this is a test for an
-
+
an image between two blank lines
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/general/quickstart.md b/src/main/resources/assets/opencomputers/doc/zh_cn/general/quickstart.md
index 4673873740..3b3c5a537d 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/general/quickstart.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/general/quickstart.md
@@ -6,7 +6,7 @@
首先你需要一个[机箱](../block/case1.md)。你所有的电脑配件都要装这里面,它将决定你电脑的行为。
-
+
比如你要挑一个适合你的[显卡](../item/graphicsCard1.md),还可能需要一个[网卡](../item/lanCard.md)、一块[红石卡](../item/redstoneCard1.md)、甚至是创造模式下调试时需要的[调试卡](../item/debugCard.md)。
@@ -37,7 +37,7 @@
好的,它启动了。如果还有什么问题的话,可以使用[分析仪](../item/analyzer.md)排查。不过我们的电脑应该跑起来了。最难的部分已经过去了,剩下就是如何让电脑输出信息,并且让电脑接受输入。
你需要给电脑配[屏幕](../block/screen1.md)和[显卡](../item/graphicsCard1.md)。
-
+
[屏幕](../block/screen1.md)可以直接放在机箱一侧,或是通过[线缆](../block/cable.md)相连。[显卡](../item/graphicsCard1.md)自然是要装机箱里。现在你应该能看到[屏幕](../block/screen1.md)上闪烁的光标了。最后,[键盘](../block/keyboard.md)应安装在[屏幕](../block/screen1.md)上,或直接冲着[屏幕](../block/screen1.md)放置。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/abstractbuscard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/abstractbuscard.md
index 47e3204e67..c8df1eff3a 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/abstractbuscard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/abstractbuscard.md
@@ -1,5 +1,5 @@
# 抽象总线卡
-
+
这张卡允许[电脑](../general/computer.md)、[服务器](server1.md)和[机器人](../block/robot.md)与 StargateTech2 的抽象类总线交互。当它安装好时,这些方块会连接到抽象类总线,总线上的组件将会对机器可用,且机器可以通过抽象类总线发送信息。传入抽象类总线的信息将会被转换为发送给机器的信号。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/acid.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/acid.md
index 3d473e3c21..ddc4c3cf8f 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/acid.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/acid.md
@@ -1,6 +1,6 @@
# 酸液
-
+
可口的[来源请求]混合液体,如果你想……找点乐子,或者烧了你的食管,亦或者都想的话,就喝下去吧。同时也是制作多种物品的原料。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/alu.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/alu.md
index a48ce9e892..f929a57fa1 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/alu.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/alu.md
@@ -1,5 +1,5 @@
# 算术逻辑单元
-
+
用来合成 [CPU](cpu1.md) 和[显卡](graphicsCard1.md)这样需要执行计算的元件。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/analyzer.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/analyzer.md
index 0b190777c4..36f2c40097 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/analyzer.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/analyzer.md
@@ -1,6 +1,6 @@
# 分析仪
-
+
一个小巧的,用来探测 OpenComputers 的方块信息的仪器。只要在潜行时右键就可以把方块信息输出到你的聊天栏里。可以导出的信息从设备地址,到子网内的能量水平,再到让电脑宕机的错误信息应有尽有。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/angelupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/angelupgrade.md
index 169ad750fe..6465319e29 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/angelupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/angelupgrade.md
@@ -1,5 +1,5 @@
# 天使升级
-
+
允许[机器人](../block/robot.md)凭空放置方块,而不用靠着别的方块。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/apu1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/apu1.md
index b6b3e22a42..b4a3ce3a50 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/apu1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/apu1.md
@@ -1,6 +1,6 @@
# APU
-
+
[CPU](cpu1.md) 和[显卡](graphicsCard1.md)的完美结合,可以为你省下整整一个插槽。和普通的 CPU 一样,它决定了一台[电脑](../general/computer.md)的架构和这台[电脑](../general/computer.md)最多能够支持多少组件。同时,APU 还提供了基本的图形功能。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/arrowkeys.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/arrowkeys.md
index 8c27faf93e..20c1eff785 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/arrowkeys.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/arrowkeys.md
@@ -1,5 +1,5 @@
# 方向键
-
+
At the risk of repeating myself: it's a button sink. Because the button economy has seen some serious inflation in recent years. 言归正传,方向键自然是制造[键盘](../block/keyboard.md)的配件。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/batteryupgrade1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/batteryupgrade1.md
index 95efc25860..20526a821d 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/batteryupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/batteryupgrade1.md
@@ -1,5 +1,5 @@
# 电池升级
-
+
用于提升[机器人](../block/robot.md)和[平板](tablet.md)等设备的电池容量,提升它们的续航能力。等级越高存得越多。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/buttongroup.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/buttongroup.md
index 97b1bfa113..ec109af877 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/buttongroup.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/buttongroup.md
@@ -1,5 +1,5 @@
# 按钮组
-
+
你总是把按钮弄得到处都是,我们已经不知 Shift 点击那个按钮配方多少次了。言归正传,按钮组用于制造[键盘](../block/keyboard.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/card.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/card.md
index 8b2f55d293..6b65664f6b 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/card.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/card.md
@@ -1,5 +1,5 @@
# 基板
-
+
用于合成 OpenComputers 中诸如[显卡](graphicsCard1.md)、[网卡](lanCard.md)这样的卡状组件的基础材料。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/cardcontainer1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/cardcontainer1.md
index 23e4d6dfaf..05f3c3cc9d 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/cardcontainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/cardcontainer1.md
@@ -1,5 +1,5 @@
# 卡槽
-
+
卡槽是[机器人](../block/robot.md)的物品栏升级之一,安装后机器人就能热插拔卡。卡槽最高只能支持同级别的卡片。卡槽的复杂度是一般组件的两倍。关于复杂度的说明可参考[这里](../block/robot.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/chamelium.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/chamelium.md
index 4d0e885016..41306c6b9e 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/chamelium.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/chamelium.md
@@ -1,6 +1,6 @@
# 变色材料
-
+
变色材料是一种可塑材料,用于在 [3D 打印机](../block/printer.md)中打印出[各种东西](../block/print.md)。它本身没什么特性,可以拿来盖单色的墙。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/chip1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/chip1.md
index bfb6189c4f..784586defb 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/chip1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/chip1.md
@@ -1,5 +1,5 @@
# 微芯片
-
+
微芯片是电子配件的重要元件,分若干级别,用于不同级别的配件。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/chunkloaderupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/chunkloaderupgrade.md
index 2529933e99..c420728edf 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/chunkloaderupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/chunkloaderupgrade.md
@@ -1,6 +1,6 @@
# 区块加载升级
-
+
可以装在像是[机器人](../block/robot.md)和[微控制器](../block/microcontroller.md))的设备上,以保证其所在区块及相邻的区块的加载。这个功能自然是耗电的。可以透过其组件 API 来控制开关。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/circuitboard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/circuitboard.md
index b40fbd16a9..4f05abb03b 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/circuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/circuitboard.md
@@ -1,5 +1,5 @@
# 电路板
-
+
这是从[未加工电路板](rawCircuitBoard.md)到[印刷电路板](printedCircuitBoard.md)的中间体。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/componentbus1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/componentbus1.md
index bfb92169c8..d4924d4ba3 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/componentbus1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/componentbus1.md
@@ -1,6 +1,6 @@
# 组件总线
-
+
组件总线是[服务器](server1.md)专用的升级,允许[服务器](server1.md)和更多的组件同时通讯。和 CPU 一样,高级的组件总线可以连接更多的组件。更高级的[服务器](server1.md)能连接的组件总线也越多,这样一来服务器能连接的组件也就更多了。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/controlunit.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/controlunit.md
index de41b4017f..ae7e327c89 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/controlunit.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/controlunit.md
@@ -1,5 +1,5 @@
# 控制单元
-
+
合成 [CPU](cpu1.md) 等高级电路的元件。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/cpu1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/cpu1.md
index 5e24255d1d..2292a284fb 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/cpu1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/cpu1.md
@@ -1,6 +1,6 @@
# CPU
-
+
中央处理器是[电脑](../general/computer.md)和[服务器](server1.md)的核心,定义了[电脑](../general/computer.md)的架构,并决定了可连接组件的数量。级别越高,每 tick 可以进行的函数调用越多。一言以蔽之,级别越高跑得越快。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/craftingupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/craftingupgrade.md
index 3985ce817f..b46fb09636 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/craftingupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/craftingupgrade.md
@@ -1,5 +1,5 @@
# 合成升级
-
+
合成升级能让[机器人](../block/robot.md)在自己的[物品栏](../item/inventoryUpgrade.md)进行各种合成。[机器人](../block/robot.md)左上的 3X3 格子将会用作合成网格,物品需要根据配方来摆放。合成产物会返回机器人物品栏。捡起物品后,首先会尝试放入指定格子中;若失败,则尝试放在下一个空格子里。如果没有格子了,物品会被丢到地上。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/cuttingwire.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/cuttingwire.md
index 6acfca8a2a..2e34f40bb8 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/cuttingwire.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/cuttingwire.md
@@ -1,5 +1,5 @@
# 切割线
-
+
在困难模式合成中会用到的东西,用于合成[未加工电路板](rawCircuitBoard.md)。很低效。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/databaseupgrade1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/databaseupgrade1.md
index d4782483d2..4b26c157e0 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/databaseupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/databaseupgrade1.md
@@ -1,6 +1,6 @@
# 数据库升级
-
+
数据库升级可以通过配置来存储一系列物品信息,进而被其他组件所使用。对于仅仅通过 NBT 数据来区分的物品极为有用,因为它们在回调中并不会作为物品描述符的一部分。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/datacard1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/datacard1.md
index 19b13c8ddb..ca238588f9 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/datacard1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/datacard1.md
@@ -1,6 +1,6 @@
# 数据卡
-
+
数据卡提供了多个难以在架构上实现,或者是在那里跑得很慢的算法,例如散列函数、压缩解压缩等。和网卡一样,数据卡也内嵌有一个文件系统,存有一些需要用到这些功能的程序。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/debugcard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/debugcard.md
index 2384a7b259..4170e36bd7 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/debugcard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/debugcard.md
@@ -1,6 +1,6 @@
# 调试卡
-
+
调试卡本身是一种仅用于在创造模式下对设备进行快速调试的卡片。有鉴于其丰富的功能,它对于地图制作也很有用处。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/disk.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/disk.md
index cf00e955d8..a46dd2435c 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/disk.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/disk.md
@@ -1,5 +1,5 @@
# 磁碟
-
+
用于合成[软盘](floppy.md)和[硬盘](hdd1.md)的基础零件。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/diskdrivemountable.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/diskdrivemountable.md
index 6c39cf44a7..0f4c680431 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/diskdrivemountable.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/diskdrivemountable.md
@@ -1,5 +1,5 @@
# 可挂载软盘驱动器
-
+
这玩意相当于装进[机架](../block/rack.md)里的[软盘驱动器](../block/diskDrive.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/drone.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/drone.md
index 7895611cf5..a6697cc7c6 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/drone.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/drone.md
@@ -1,5 +1,5 @@
# 无人机
-
+
无人机需通过在[装配器](../block/assembler.md)中装配[无人机箱](droneCase1.md)制造。他们是实体形态的[机器人](../block/robot.md),造价便宜但功能受限。无人机通常由[电脑](../general/computer.md)程序控制移动,移动速度比[机器人](../block/robot.md)快,而且方向也可以不一样。无人机需要 [EEPROM](eeprom.md) 来监听指令或独自行动。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/dronecase1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/dronecase1.md
index 2a4d76d303..9c469627c3 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/dronecase1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/dronecase1.md
@@ -1,6 +1,6 @@
# 无人机外壳
-
+
无人机外壳是在[装配机](../block/assembler.md)中组装[无人机](drone.md)时所用的容器。[无人机](drone.md)是种轻量、快速、功能受限(只有少量的升级和插槽)的移动设备。和[机器人](../block/robot.md)不一样,无人机不能使用工具,也只能和世界进行有限的交互。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/eeprom.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/eeprom.md
index 06b71ba86a..6e04445bb7 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/eeprom.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/eeprom.md
@@ -1,6 +1,6 @@
# EEPROM
-
+
EEPROM 中包含了在电脑启动后引导其完成初始化的代码。这些代码以字节数组的形式保存,在不同的 [CPU](cpu1.md) 架构上有不同的含义,比如对于 Lua BIOS 来说这可能是搜索可用文件系统的初始化代码,对于其他设备这可能是机器码。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/experienceupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/experienceupgrade.md
index 25154378a0..ab56754703 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/experienceupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/experienceupgrade.md
@@ -1,6 +1,6 @@
# 经验升级
-
+
经验升级是一种允许[机器人](../block/robot.md)和[无人机](drone.md)通过杀死怪物、挖矿等操作收集经验球的特种升级。每个升级能存储 30 级经验,并且每一级都可以带来诸如挖矿加速、能量缓存提升等加成。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/floppy.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/floppy.md
index d90032f590..bfcb59dcbb 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/floppy.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/floppy.md
@@ -1,5 +1,5 @@
# 软盘
-
+
是 OpenComputers 中最便宜的存储设备,用于游戏初期在[电脑](../general/computer.md)和[机器人](../block/robot.md)间交换数据。你还可以在地牢中找到一些实用程序的安装软盘(比如 OpenPrograms Package Manager,一个能让你轻松从某个 GitHub 仓库中下载并安装程序的包管理器)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/generatorupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/generatorupgrade.md
index 818435ef46..7e852cea08 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/generatorupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/generatorupgrade.md
@@ -1,6 +1,6 @@
# 发电机升级
-
+
发电机升级是个给设备内嵌发电设备的升级。目前它仅支持煤这样的固体燃料。内部有存储燃料的物品栏。多余燃料可以通过对应的组件 API 取出。从[机器人](../block/robot.md)上移除升级时,会使里面的东西掉出来。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/graphicscard1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/graphicscard1.md
index 2820e52c1b..45ac695e8b 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/graphicscard1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/graphicscard1.md
@@ -1,6 +1,6 @@
# 显卡
-
+
显卡对大多数计算机都非常重要[computers](../general/computer.md),因为显卡允许[计算机](../general/computer.md)在相连的[屏幕](../block/screen1.md)上显示字符。显卡分若干等级,如同[显示屏](../block/screen1.md)那样支持不同的分辨率和色深。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/hdd1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/hdd1.md
index f860229000..d415f8f83c 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/hdd1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/hdd1.md
@@ -1,5 +1,5 @@
# 硬盘驱动器
-
+
硬盘是 OpenComputers 中的高级存储器,不同等级的硬盘速度一样,只有容量不同,级别越高容量越大。有的设备只能用硬盘存储数据(尽管服务器还可以用外置[软盘驱动器](../block/diskDrive.md))。硬盘还可在 [RAID](../block/raid.md) 中与其他磁盘组成共享文件系统的阵列,不过要注意,硬盘放进 RAID 里的时候之前的数据都会抹除。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverboots.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverboots.md
index 8481da65b1..d7240ac6a0 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverboots.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverboots.md
@@ -1,6 +1,6 @@
# 悬浮靴
-
+
如果不想去编程[无人机](drone.md),有个变通的办法:垫脚石!或者说那是美化的内联冰鞋的名字。总之就是这个意思。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverupgrade1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverupgrade1.md
index 2195a8bc85..09e62e53b3 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverupgrade1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/hoverupgrade1.md
@@ -1,6 +1,6 @@
# 悬浮升级
-
+
悬浮升级让[机器人](../block/robot.md)飞得更高。默认,机器人只能往上飞 8 格。平常因为机器人能爬墙所以这并不是什么大问题。机器人移动的规律如下:
- 机器人只会在起点和终点都有效的情况下才会动(比如允许搭桥)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/inkcartridge.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/inkcartridge.md
index 295c90c4ab..39c4b7823b 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/inkcartridge.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/inkcartridge.md
@@ -1,5 +1,5 @@
# 墨盒
-
+
墨盒可以很方便地给 [3D 打印机](../block/printer.md)供墨。当然你可以手动用染料来供墨,但这样一不太方便,二没有效率。所以我们强烈建议您今天购买一个真正的 OC 墨盒™!(免责声明:墨盒的价格有可能比打印机还高。)
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/internetcard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/internetcard.md
index 17c4d83903..6d1d2da514 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/internetcard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/internetcard.md
@@ -1,6 +1,6 @@
# 因特网卡
-
+
装了这个[电脑](../general/computer.md)就能联网了。它能承载简单的 HTTP 请求以及读写普通的 TCP 客户端套接字。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/interweb.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/interweb.md
index cdc12d6f4c..0b94d794dc 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/interweb.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/interweb.md
@@ -1,5 +1,5 @@
# 因特网
-
+
因特网是长距离通信设备用到的基本元件,基本原理是利用各种末影物质的奇怪性质以进行某种量子通讯。主要用在[因特网卡](internetCard.md)和[连接卡](linkedCard.md)上。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventorycontrollerupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventorycontrollerupgrade.md
index 713aa9d653..94116b68a6 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventorycontrollerupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventorycontrollerupgrade.md
@@ -1,6 +1,6 @@
# 物品栏控制器
-
+
物品栏控制器为[机器人](../block/robot.md)和[无人机](drone.md)提供了额外的物品栏交互能力。它允许设备在从外部容器存取物品时指定具体的格子、读取详细的物品信息以及允许[机器人](../block/robot.md) 不借助外力更换自身装备。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventoryupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventoryupgrade.md
index 525019802a..4f55ebb99c 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventoryupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/inventoryupgrade.md
@@ -1,6 +1,6 @@
# 物品栏升级
-
+
物品栏升级让[机器人](../block/robot.md)和[无人机](drone.md)有了物品栏。每个升级可为[机器人](../block/robot.md)提供 16 个格子,最大扩展到 64;对于[无人机](drone.md)则是提供 4 个格子,最大扩展到 8。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/lancard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/lancard.md
index ba691c1389..5647d3f173 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/lancard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/lancard.md
@@ -1,5 +1,5 @@
# 网卡
-
+
网卡允许[电脑](../general/computer.md)在本地网络内收发消息。消息(或者叫封包)可向子网广播,或者是发送至特定地址上的设备。[中继器](../block/relay.md)可以用来桥接不同的子网,使之互相通信。若两个网络间有若干[中继器](../block/relay.md),发送跨越网络到指定设备上的数据包也是可能的。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/leashupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/leashupgrade.md
index 8637a9e027..eedb3d0147 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/leashupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/leashupgrade.md
@@ -1,5 +1,5 @@
# 拴绳升级
-
+
拴绳升级允许[无人机](drone.md)这样的设备给动物拴上拴绳,这样一来这些装了该升级的设备就可以一次性拉走一群动物。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/linkedcard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/linkedcard.md
index 36fb17a08e..3472550172 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/linkedcard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/linkedcard.md
@@ -1,5 +1,5 @@
# 连接卡
-
+
连接卡是特化的高级[网卡](lanCard.md),只能成对使用,用于点对点(P2P)通讯。连接卡可以进行跨维度无限距离的通讯。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/manual.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/manual.md
index b5bfeb6d84..c6e916a220 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/manual.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/manual.md
@@ -1,6 +1,6 @@
# OpenComputers 手册
-
+
没错就是你正在读的东西!本手册涵盖了 OpenComputers 的所有内容(甚至还有别的东西)。如果你需要关于 OpenComputers 的某个方块或物品的信息,查手册就可以了!用鼠标滚轮往下翻(或者右边的滑块往下拉)来学习如何使用本手册。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/mfu.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/mfu.md
index 59ab66c633..6410065ce1 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/mfu.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/mfu.md
@@ -1,6 +1,6 @@
# MFU
-
+
这个升级相当于远程[适配器](../block/adapter.md)。潜行时,对任意方块的任意面使用该升级以将其与这个面绑定。然后,将其安装到附近的适配器里面(这个“附近”很有限)。好了,现在这个加了 MFU 的适配器就能访问到与 MFU 绑定的方块了!
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/microcontrollercase1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/microcontrollercase1.md
index 515cab46ea..72949c6fbe 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/microcontrollercase1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/microcontrollercase1.md
@@ -1,6 +1,6 @@
# 微控制器盒
-
+
微控制器盒是在[装配机](../block/assembler.md)中制造[微控制器](../block/microcontroller.md)的基础。 [微控制器](../block/microcontroller.md)是种极其简化的[电脑](../general/computer.md),只有少量组件,通常设计为特定用途,比如转发或者处理红石信号以及处理网路消息。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/nanomachines.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/nanomachines.md
index 9f39d3b8af..d14096eff9 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/nanomachines.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/nanomachines.md
@@ -1,6 +1,6 @@
# 纳米机器
-
+
这些跟你的神经系统打交道的玩意能让你变得更快、更高、更强,或者干掉你。甚至有时候这些是同时发生的!简单来说,纳米机器的用途就是往宿主玩家上加 buff 和 debuff。“安装”方法:吃下去!
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/navigationupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/navigationupgrade.md
index 3f1d716243..3ae1348fed 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/navigationupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/navigationupgrade.md
@@ -1,6 +1,6 @@
# 导航升级
-
+
导航升级可提供宿主设备的位置和朝向。坐标是相对用于合成这个升级的地图的中心而言的,它的作用范围也限制在那张地图的大小中。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/numpad.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/numpad.md
index 8dc25a6b84..4587ebc09a 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/numpad.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/numpad.md
@@ -1,5 +1,5 @@
# 数字键
-
+
数字键是每块[键盘](../block/keyboard.md)都有的东西,用来输入数字用的。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/pistonupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/pistonupgrade.md
index 651c77f519..d21bda0884 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/pistonupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/pistonupgrade.md
@@ -1,6 +1,6 @@
# 活塞升级
-
+
活塞升级能让某些设备的行为变得像原版活塞那样。安装后会暴露一个只有一个 `push()` 方法的组件。调用此方法时,设备将会试图将它面前的方块推出去。对于[机器人](../block/robot.md)和[单片机](../block/microcontroller.md)来说这就是它们的正面;对于[平板](tablet.md)来说,是玩家视角的那个方向。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/printedcircuitboard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/printedcircuitboard.md
index 50167890de..8693313899 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/printedcircuitboard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/printedcircuitboard.md
@@ -1,5 +1,5 @@
# 印刷电路板
-
+
印刷电路板和[晶体管](transistor.md)一样都是 OpenComputers 中的基础合成材料,用于制作多种元件,例如[卡片](card.md)和为数众多[方块](../block/index.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/ram1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/ram1.md
index 78ee629f76..fe839f951e 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/ram1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/ram1.md
@@ -1,6 +1,6 @@
# 内存
-
+
内存和 [CPU](cpu1.md) 一样都是[电脑](../general/computer.md)的核心部件。根据 [CPU](cpu1.md) 的架构的不同,内存很大程度上直接决定了电脑能做什么以及不能做什么。以标准 Lua 架构为例,内存条决定了 Lua 脚本能用多少内存。这意味着你要安装更大的内存条跑更大更复杂的程序。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/rawCircuitBoard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/rawCircuitBoard.md
index d0a703fc99..f10836f829 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/rawCircuitBoard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/rawCircuitBoard.md
@@ -1,5 +1,5 @@
# 未加工电路板
-
+
未加工电路板是合成[电路板](circuitBoard.md)及[印刷电路板](printedCircuitBoard.md)的中间材料(以游戏内使用的合成表为准)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/redstonecard1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/redstonecard1.md
index e335377a09..18113d9dbb 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/redstonecard1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/redstonecard1.md
@@ -1,6 +1,6 @@
# 红石卡
-
+
红石卡让[电脑](../general/computer.md)可以收发邻近方块的红石信号。输入信号强度变化时,信号将输入[电脑](../general/computer.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/server1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/server1.md
index ae5d83d463..79722f5fdf 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/server1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/server1.md
@@ -1,6 +1,6 @@
# 服务器
-
+
服务器是种高级[电脑](../general/computer.md)。你可以通过把它拿在手上像打开背包一样打开来进行配置,也可以放在[机架](../block/rack.md)里面,通过站在机架的正面打开机架操作界面来配置它。详细信息请参见[机架](../block/rack.md)条目。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/signupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/signupgrade.md
index e1bcc5a504..b5337b2639 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/signupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/signupgrade.md
@@ -1,5 +1,5 @@
# 告示牌 I/O
-
+
这个升级允许设备和告示牌交互,用于读取或改写(如果有权限)告示牌上的信息。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/solargeneratorupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/solargeneratorupgrade.md
index 4cea2d8f48..9ae7e3ad7f 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/solargeneratorupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/solargeneratorupgrade.md
@@ -1,6 +1,6 @@
# 太阳能发电机升级
-
+
太阳能发电机升级可以安装到[机器人](../block/robot.md)、[无人机](drone.md)和[平板](tablet.md)上。它只会在阳光直射的时候工作,不是晴天或者在密闭环境下它是不会产生一丁点能量的。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tablet.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tablet.md
index b413fe34f5..d6685a3905 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tablet.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tablet.md
@@ -1,6 +1,6 @@
# 平板电脑
-
+
平板电脑是在[装配机](../block/assembler.md)中通过配置[平板外壳](tabletCase1.md)并组装而成的。平板电脑本身是种无法直接与世界交互的移动计算机,比如[基础红石卡](redstoneCard1.md)就不能在平板上用,但像是[告示牌升级](signUpgrade.md)和[活塞升级](pistonUpgrade.md)这样的可以使用。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tabletCase1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tabletCase1.md
index 531c05e679..443cb9dad0 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tabletCase1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tabletCase1.md
@@ -1,6 +1,6 @@
# 平板电脑外壳
-
+
平板电脑外壳是在[装配机](../block/assembler.md)中组装[平板电脑](tablet.md)的基础。[平板电脑](tablet.md)是种小型可移动[电脑](../general/computer.md),可加装少量升级,但无法像[机箱](../block/case1.md)那样简单的使用红石卡和网卡和世界交互。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankcontrollerupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankcontrollerupgrade.md
index d4c2fced29..627789fadf 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankcontrollerupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankcontrollerupgrade.md
@@ -1,6 +1,6 @@
# 储罐控制器
-
+
储罐控制器可用来控制储罐,用于查询内部储罐和外部的信息。实际上它就是流体版的[物品栏控制器升级](inventoryControllerUpgrade.md)。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankupgrade.md
index a9b5bc1920..d98caa5e22 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tankupgrade.md
@@ -1,5 +1,5 @@
# 储罐升级
-
+
储罐升级允许设备存储流体。每个升级仅能存储一种流体,并提供 16 桶容量(即 16000 mB)。[机器人](../block/robot.md)和[无人机](drone.md)可以从世界中和其他储罐汲取液体,也可以倒回世界或者储罐中。单台设备可安装的储罐数没有限制。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminal.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminal.md
index 0053efaf1f..68c4499980 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminal.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminal.md
@@ -1,6 +1,6 @@
# 终端
-
+
终端可用于远程访问[终端服务器](terminalServer.md)。只需对准[机架](../block/rack.md)里安装的[终端服务器](terminalServer.md)手持远程终端右击即可完成绑定。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminalserver.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminalserver.md
index af56c51c55..340f754317 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminalserver.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/terminalserver.md
@@ -1,5 +1,5 @@
# 终端服务器
-
+
终端服务器可向外界提供虚拟[屏幕](../block/screen1.md)和[键盘](../block/keyboard.md),可以通过绑定[终端](terminal.md)来控制机器。关于终端的更多信息可参阅[终端](terminal.md)条目。终端服务器必须安装在[机架](../block/rack.md)里面。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/texturepicker.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/texturepicker.md
index 55a9e4ed84..594fb9d0b5 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/texturepicker.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/texturepicker.md
@@ -1,6 +1,6 @@
# 纹理选择器
-
+
纹理选择器在制作 [3D 打印机](../block/printer.md)使用的模型时很有用。只需要潜行时对着某个方块使用它,就能获得世界上某个方块的纹理名。免责声明:对于箱子这种有特殊渲染器的方块无效。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tractorbeamupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tractorbeamupgrade.md
index c9c6181fcb..6cc2c9374c 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tractorbeamupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tractorbeamupgrade.md
@@ -1,5 +1,5 @@
# 牵引光束
-
+
牵引光束升级能让设备捡起 3 格内的物品。对树场或农场里面工作,或使用像是匠魂的某些工具那样有范围破坏能力的工具的[机器人](../block/robot.md)来说十分有用。每次操作都会尝试吸取范围内的一个物品实体,并消耗一定能量。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tradingupgrade.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tradingupgrade.md
index 9a0d20ee39..9aaf00ac55 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/tradingupgrade.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/tradingupgrade.md
@@ -1,5 +1,5 @@
# 交易升级
-
+
交易升级让设备能自动和村民这样的商人交易。它可以装在[机器人](../block/robot.md)和[无人机](drone.md)里面,安装后其能够探测附近商人的存在,获取可用交易信息并完成交易。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/transistor.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/transistor.md
index 5c9e975a8a..89a9ffa109 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/transistor.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/transistor.md
@@ -1,5 +1,5 @@
# 晶体管
-
+
晶体管是 OpenComputers 中最基础的元件,主要用于合成[芯片](chip1.md)等电子产品。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/upgradecontainer1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/upgradecontainer1.md
index e932a9fb08..acdf83d984 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/upgradecontainer1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/upgradecontainer1.md
@@ -1,5 +1,5 @@
# 升级组件容器
-
+
升级组件容器是一种特殊的[机器人](../block/robot.md)升级,它提供一个支持热插拔的升级槽位。它支持的升级的等级和它自身的等级一致。其复杂度是其等级的二倍,参阅[机器人](../block/robot.md)和[装配机](../block/assembler.md)的说明以了解复杂度的设定。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/wlancard1.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/wlancard1.md
index 895d768072..a87ad22254 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/wlancard1.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/wlancard1.md
@@ -1,6 +1,6 @@
# 无线网卡
-
+
无线网卡是支持无线网络的升级版[网卡](lanCard.md),有无线收发数据的能力。T2 的无线网卡还能收发有线数据。无线信号发射强度决定了信息可以传多远,这里信号强度等于方块距离。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/worldsensorcard.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/worldsensorcard.md
index a46b9a7752..121fcab321 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/worldsensorcard.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/worldsensorcard.md
@@ -1,5 +1,5 @@
# 世界传感器卡
-
+
世界传感器卡让设备能读取大气、(GalactiCraft 的)重力等世界信息,对于在空间中[机器人](../block/robot.md)和[无人机](drone.md)来说有用。
diff --git a/src/main/resources/assets/opencomputers/doc/zh_cn/item/wrench.md b/src/main/resources/assets/opencomputers/doc/zh_cn/item/wrench.md
index 3b44fe43a5..f1e7374ced 100644
--- a/src/main/resources/assets/opencomputers/doc/zh_cn/item/wrench.md
+++ b/src/main/resources/assets/opencomputers/doc/zh_cn/item/wrench.md
@@ -1,5 +1,5 @@
# 螺丝刀扳手
-
+
和绝大多数科技主题的 Mod 一样,OpenComputers 也有它自己的扳手——一把融合了螺丝刀功能的扳手。看上去很难用。可以拿来旋转方块,也与其他很多 Mod 中支持各种扳手的设备兼容。
diff --git a/src/main/resources/assets/opencomputers/lang/de_DE.lang b/src/main/resources/assets/opencomputers/lang/de_DE.lang
deleted file mode 100644
index 4cf64dd2c8..0000000000
--- a/src/main/resources/assets/opencomputers/lang/de_DE.lang
+++ /dev/null
@@ -1,483 +0,0 @@
-# German (de_DE) localization file
-# Translations might not be 100% correct
-# Suggestions for improvements are welcome
-
-# Blocks
-tile.oc.adapter.name=Adapter
-tile.oc.assembler.name=Elektronik-Werkbank
-tile.oc.cable.name=Kabel
-tile.oc.capacitor.name=Kondensator
-tile.oc.carpetedcapacitor.name=Teppichkondensator
-tile.oc.case1.name=Computergehäuse (Stufe 1)
-tile.oc.case2.name=Computergehäuse (Stufe 2)
-tile.oc.case3.name=Computergehäuse (Stufe 3)
-tile.oc.caseCreative.name=Computergehäuse (Kreativ)
-tile.oc.chameliumBlock.name=Chamälium-Block
-tile.oc.charger.name=Ladestation
-tile.oc.disassembler.name=Recycler
-tile.oc.diskDrive.name=Diskettenlaufwerk
-tile.oc.endstone.name=Endstein
-tile.oc.geolyzer.name=Geolyzer
-tile.oc.hologram1.name=Hologrammprojektor (Stufe 1)
-tile.oc.hologram2.name=Hologrammprojektor (Stufe 2)
-tile.oc.keyboard.name=Tastatur
-tile.oc.microcontroller.name=Mikrocontroller
-tile.oc.motionSensor.name=Bewegungsmelder
-tile.oc.netSplitter.name=Net Splitter
-tile.oc.powerConverter.name=Leistungswandler
-tile.oc.powerDistributor.name=Stromverteiler
-tile.oc.print.name=3D-Druck
-tile.oc.printer.name=3D-Drucker
-tile.oc.raid.name=Raid
-tile.oc.redstone.name=Redstone-I/O
-tile.oc.relay.name=Relais
-tile.oc.robot.name=Roboter
-tile.oc.robotAfterimage.name=Roboter
-tile.oc.screen1.name=Bildschirm (Stufe 1)
-tile.oc.screen2.name=Bildschirm (Stufe 2)
-tile.oc.screen3.name=Bildschirm (Stufe 3)
-tile.oc.rack.name=Serverschrank
-tile.oc.transposer.name=Transposer
-tile.oc.waypoint.name=Wegpunkt
-
-# Items
-item.oc.AbstractBusCard.name=Abstrakter-Bus-Karte
-item.oc.Acid.name=Grog
-item.oc.ALU.name=Arithmetisch-logische Einheit (ALU)
-item.oc.Analyzer.name=Messgerät
-item.oc.APU0.name=Beschleunigter Prozessor (APU) (Stufe 1)
-item.oc.APU1.name=Beschleunigter Prozessor (APU) (Stufe 2)
-item.oc.APU2.name=Beschleunigter Prozessor (APU) (Kreativ)
-item.oc.ArrowKeys.name=Pfeiltasten
-item.oc.ButtonGroup.name=Tastengruppe
-item.oc.CardBase.name=Kartenbasis
-item.oc.Chamelium.name=Chamälium
-item.oc.CircuitBoard.name=Leiterplatte
-item.oc.ComponentBus0.name=Komponentenschnittstelle (Stufe 1)
-item.oc.ComponentBus1.name=Komponentenschnittstelle (Stufe 2)
-item.oc.ComponentBus2.name=Komponentenschnittstelle (Stufe 3)
-item.oc.componentbus3.name=Komponentenschnittstelle (Kreativ)
-item.oc.ControlUnit.name=Steuerwerk (CU)
-item.oc.CPU0.name=Hauptprozessor (CPU) (Stufe 1)
-item.oc.CPU1.name=Hauptprozessor (CPU) (Stufe 2)
-item.oc.CPU2.name=Hauptprozessor (CPU) (Stufe 3)
-item.oc.CuttingWire.name=Schneidedraht
-item.oc.DataCard0.name=Datenkarte (Stufe 1)
-item.oc.DataCard1.name=Datenkarte (Stufe 2)
-item.oc.DataCard2.name=Datenkarte (Stufe 3)
-item.oc.DebugCard.name=Debug-Karte
-item.oc.Debugger.name=Netzwerk-Debugger
-item.oc.DiamondChip.name=Diamantsplitter
-item.oc.Disk.name=Platte
-item.oc.DiskDriveMountable.name=Diskettenlaufwerk
-item.oc.Drone.name=Drohne
-item.oc.DroneCase0.name=Drohnengehäuse (Stufe 1)
-item.oc.DroneCase1.name=Drohnengehäuse (Stufe 2)
-item.oc.DroneCase3.name=Drohnengehäuse (Kreativ)
-item.oc.eeprom.name=EEPROM
-item.oc.FloppyDisk.name=Diskette
-item.oc.GraphicsCard0.name=Grafikkarte (Stufe 1)
-item.oc.GraphicsCard1.name=Grafikkarte (Stufe 2)
-item.oc.GraphicsCard2.name=Grafikkarte (Stufe 3)
-item.oc.HardDiskDrive0.name=Festplatte (Stufe 1)
-item.oc.HardDiskDrive1.name=Festplatte (Stufe 2)
-item.oc.HardDiskDrive2.name=Festplatte (Stufe 3)
-item.oc.hoverBoots.name=Schwebestiefel
-item.oc.InkCartridge.name=Tintenkartusche
-item.oc.InkCartridgeEmpty.name=Tintenkartusche (Leer)
-item.oc.InternetCard.name=Internetkarte
-item.oc.Interweb.name=Internetz
-item.oc.IronNugget.name=Eisennugget
-item.oc.LinkedCard.name=Verknüpfte Karte
-item.oc.Manual.name=OpenComputers-Handbuch
-item.oc.Memory0.name=Speicher (Stufe 1)
-item.oc.Memory1.name=Speicher (Stufe 1.5)
-item.oc.Memory2.name=Speicher (Stufe 2)
-item.oc.Memory3.name=Speicher (Stufe 2.5)
-item.oc.Memory4.name=Speicher (Stufe 3)
-item.oc.Memory5.name=Speicher (Stufe 3.5)
-item.oc.Microchip0.name=Mikrochip (Stufe 1)
-item.oc.Microchip1.name=Mikrochip (Stufe 2)
-item.oc.Microchip2.name=Mikrochip (Stufe 3)
-item.oc.MicrocontrollerCase0.name=Mikrocontroller-Gehäuse (Stufe 1)
-item.oc.MicrocontrollerCase1.name=Mikrocontroller-Gehäuse (Stufe 2)
-item.oc.MicrocontrollerCase3.name=Mikrocontroller-Gehäuse (Kreativ)
-item.oc.Nanomachines.name=Nanomaschinen
-item.oc.NetworkCard.name=Netzwerkkarte
-item.oc.NumPad.name=Ziffernblock
-item.oc.Present.name=Ein kleines Etwas...
-item.oc.PrintedCircuitBoard.name=Gedruckte Leiterplatte (PCB)
-item.oc.RawCircuitBoard.name=Leiterplattenrohling
-item.oc.RedstoneCard0.name=Redstonekarte (Stufe 1)
-item.oc.RedstoneCard1.name=Redstonekarte (Stufe 2)
-item.oc.Server0.name=Server (Stufe 1)
-item.oc.Server1.name=Server (Stufe 2)
-item.oc.Server2.name=Server (Stufe 3)
-item.oc.Server3.name=Server (Kreativ)
-item.oc.Tablet.name=Tablet
-item.oc.TabletCase0.name=Tablet-Gehäuse (Stufe 1)
-item.oc.TabletCase1.name=Tablet-Gehäuse (Stufe 2)
-item.oc.TabletCase3.name=Tablet-Gehäuse (Kreativ)
-item.oc.Terminal.name=Fernbedienung
-item.oc.TerminalServer.name=Terminalserver
-item.oc.TexturePicker.name=Texturenwähler
-item.oc.Transistor.name=Transistor
-item.oc.UpgradeAngel.name=Schwebe-Upgrade
-item.oc.UpgradeBattery0.name=Akku-Upgrade (Stufe 1)
-item.oc.UpgradeBattery1.name=Akku-Upgrade (Stufe 2)
-item.oc.UpgradeBattery2.name=Akku-Upgrade (Stufe 3)
-item.oc.UpgradeChunkloader.name=Chunkloader-Upgrade
-item.oc.UpgradeContainerCard0.name=Karten-Behälter (Stufe 1)
-item.oc.UpgradeContainerCard1.name=Karten-Behälter (Stufe 2)
-item.oc.UpgradeContainerCard2.name=Karten-Behälter (Stufe 3)
-item.oc.UpgradeContainerUpgrade0.name=Upgrade-Behälter (Stufe 1)
-item.oc.UpgradeContainerUpgrade1.name=Upgrade-Behälter (Stufe 2)
-item.oc.UpgradeContainerUpgrade2.name=Upgrade-Behälter (Stufe 3)
-item.oc.UpgradeCrafting.name=Crafting-Upgrade
-item.oc.UpgradeDatabase0.name=Datenbank-Upgrade (Stufe 1)
-item.oc.UpgradeDatabase1.name=Datenbank-Upgrade (Stufe 2)
-item.oc.UpgradeDatabase2.name=Datenbank-Upgrade (Stufe 3)
-item.oc.UpgradeExperience.name=Erfahrungs-Upgrade
-item.oc.UpgradeGenerator.name=Generator-Upgrade
-item.oc.UpgradeHover0.name=Schwebe-Upgrade (Stufe 1)
-item.oc.UpgradeHover1.name=Schwebe-Upgrade (Stufe 2)
-item.oc.UpgradeInventory.name=Inventar-Upgrade
-item.oc.UpgradeInventoryController.name=Inventarbedienungs-Upgrade
-item.oc.UpgradeLeash.name=Leinen-Upgrade
-item.oc.UpgradeMF.name=MFU
-item.oc.UpgradeNavigation.name=Navigations-Upgrade
-item.oc.UpgradePiston.name=Kolben-Upgrade
-item.oc.UpgradeSign.name=Schild-I/O-Upgrade
-item.oc.UpgradeSolarGenerator.name=Solargenerator-Upgrade
-item.oc.UpgradeTank.name=Tank-Upgrade
-item.oc.UpgradeTankController.name=Tankbedienungs-Upgrade
-item.oc.UpgradeTractorBeam.name=Traktorstrahl-Upgrade
-item.oc.UpgradeTrading.name=Handels-Upgrade
-item.oc.WirelessNetworkCard0.name=Drahtlosnetzwerkkarte (Stufe 1)
-item.oc.WirelessNetworkCard1.name=Drahtlosnetzwerkkarte (Stufe 2)
-item.oc.WorldSensorCard.name=Weltsensorkarte
-item.oc.wrench.name=Schraubenziehschlüssel
-
-# Entities
-entity.oc.Drone.name=Drohne
-
-# GUI
-oc:gui.Analyzer.Address=§6Adresse§f: %s
-oc:gui.Analyzer.AddressCopied=Adresse wurde in die Zwischenablage kopiert.
-oc:gui.Analyzer.ChargerSpeed=§6Ladegeschwindigkeit§f: %s
-oc:gui.Analyzer.ComponentName=§6Komponentenname§f: %s
-oc:gui.Analyzer.Components=§6Anzahl verbundener Komponenten§f: %s
-oc:gui.Analyzer.CopyToClipboard=In die Zwischenablage kopieren.
-oc:gui.Analyzer.LastError=§6Letzter Fehler§f: %s
-oc:gui.Analyzer.RobotName=§6Name§f: %s
-oc:gui.Analyzer.RobotOwner=§6Besitzer§f: %s
-oc:gui.Analyzer.RobotXp=§6Erfahrung§f: %s (Stufe %s)
-oc:gui.Analyzer.StoredEnergy=§6Gespeicherte Energie§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Insgesamt gespeicherte Energie§f: %s
-oc:gui.Analyzer.Users=§6Benutzer§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Signalstärke§f: %s
-oc:gui.Assembler.Collect=Fertiges Gerät entnehmen
-oc:gui.Assembler.Complexity=Komplexität: %s/%s
-oc:gui.Assembler.InsertCase=Grundbaustein einlegen
-oc:gui.Assembler.InsertCPU=CPU benötigt
-oc:gui.Assembler.InsertRAM=RAM benötigt
-oc:gui.Assembler.Progress=Fortschritt: %s%% (%s)
-oc:gui.Assembler.Run=Zusammenbauen
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=Grafikkarte
-oc:gui.Assembler.Warning.Inventory=Inventar-Upgrade
-oc:gui.Assembler.Warning.Keyboard=Tastatur
-oc:gui.Assembler.Warning.OS=Bootbares Medium
-oc:gui.Assembler.Warning.Screen=Bildschirm
-oc:gui.Assembler.Warnings=§eWarnung§7: Empfohlene Komponenten fehlen.
-oc:gui.Chat.NewVersion=Eine neue Version ist verfügbar: %s
-oc:gui.Chat.TextureName=§7Texturname ist §a%s§f.
-oc:gui.Chat.WarningClassTransformer=Es gab §cFehler§f beim Ausführen des Class-Transformers. Bitte melde dies, zusammen mit deiner (vollständigen!) FML §alatest.log§f/§afml-server-latest.log§f Log-Datei, danke!
-oc:gui.Chat.WarningFingerprint=§cWARNUNG§f - ungültige Signatur! Sollte '§a%s§f' sein, aber war '§e%s§f'. Falls du kein Modder bist und die "deobfuscated"-Version des Mods benutzt, solltest du OpenComputers erneut herunterladen, da die JAR, die du benutzt, vermutlich modifiziert wurde.
-oc:gui.Chat.WarningLink=Link konnte nicht geöffnet werden: %s
-oc:gui.Chat.WarningLuaFallback=Die native Lua-Implementierung ist nicht verfügbar. Computer können ihren Ausführungszustand nicht speichern. Sie werden automatisch neu starten, sobald ein Chunk neu geladen wird.
-oc:gui.Chat.WarningProjectRed=Die verwendete Version von Project: Red ist nicht mit OpenComputers kompatibel. Aktualisiere bitte deine Version von Project: Red.
-oc:gui.Chat.WarningRecipes=Es gab Fehler beim Laden eines oder mehrerer Rezepte. Einige Gegenstände können unter Umständen nicht gefertigt werden. Bitte wirf einen Blick in deine Log-Datei für weitere Informationen.
-oc:gui.Chat.WarningSimpleComponent=Eine Erweiterung (deine?) welche das §aSimpleComponent§f-Interface verwendet, hat etwas §efalsch gemacht§f. Komponentenlogik konnte nicht eingefügt werden. Bitte wirf einen Blick in deine Log-Datei für weitere Informationen.
-oc:gui.Drive.Managed=Managed
-oc:gui.Drive.Unmanaged=Unmanaged
-oc:gui.Drive.ReadOnlyLock=Sperre
-oc:gui.Drive.ReadOnlyLockWarning=§lNur Lesen§r Sperre. Kann nur entfernt werden, wenn das Laufwerk gelöscht wird.
-oc:gui.Drive.Warning=§lWarnung§r: Umschalten der Modi führt zum Datenverlust.
-oc:gui.Error.ComponentOverflow=Zu viele Komponenten sind mit dem Computer verbunden.
-oc:gui.Error.InternalError=Interner Fehler, bitte sieh in der Logdatei nach. Das ist wahrscheinlich ein Bug.
-oc:gui.Error.NoCPU=Im Computer ist kein Hauptprozessor (CPU) installiert.
-oc:gui.Error.NoEnergy=Nicht genug Energie.
-oc:gui.Error.NoRAM=Im Computer ist kein RAM installiert.
-oc:gui.Error.OutOfMemory=Nicht genug Arbeitsspeicher.
-oc:gui.Manual.Blocks=OpenComputers-Blöcke
-oc:gui.Manual.Home=Startseite
-oc:gui.Manual.Items=OpenComputers-Gegenstände
-oc:gui.Manual.Warning.BlockMissing=Block nicht verfügbar.
-oc:gui.Manual.Warning.ImageMissing=Bild nicht gefunden.
-oc:gui.Manual.Warning.ItemMissing=Gegenstand nicht verfügbar.
-oc:gui.Manual.Warning.OreDictMissing=Ore-Dictionary-Eintrag nicht verfügbar.
-oc:gui.Raid.Warning=§4Platten werden beim Einsetzen[nl] gelöscht. Entfernen einer Platte[nl] löscht das gesamte Raid.
-oc:gui.Robot.Power=Energie
-oc:gui.Robot.TurnOff=Ausschalten
-oc:gui.Robot.TurnOn=Einschalten[nl] §7Nutze ein Messgerät, um Fehler zu behandeln.§r
-oc:gui.Rack.Back=Hinten
-oc:gui.Rack.Bottom=Unten
-oc:gui.Rack.Left=Links
-oc:gui.Rack.None=Keine
-oc:gui.Rack.Right=Rechts
-oc:gui.Rack.Enabled=Aktiv
-oc:gui.Rack.Disabled=Inaktiv
-oc:gui.Rack.Top=Oben
-oc:gui.Switch.PacketsPerCycle=Pakete / Zyklus
-oc:gui.Switch.QueueSize=Puffergröße
-oc:gui.Switch.TransferRate=Taktung
-oc:gui.Terminal.InvalidKey=Ungültiger Schlüssel, vermutlich wurde eine andere Fernbedienung an den Server gebunden.
-oc:gui.Terminal.OutOfRange=Kein Signal.
-
-# Containers
-oc:container.adapter=Adapter
-oc:container.case=Computer
-oc:container.charger=Ladestation
-oc:container.disassembler=Recycler
-oc:container.diskdrive=Diskettenlaufwerk
-oc:container.printer=Drucker
-oc:container.raid=Raid
-oc:container.relay=Relais
-oc:container.server=Server
-oc:container.rack=Serverschrank
-oc:container.tabletwrapper=Tablet
-
-# Keybinds
-key.clipboardPaste=Zwischenablage einfügen
-
-# Item / Block Tooltips
-oc:tooltip.accesspoint=Verhält sich wie ein Switch, aber empfängt zusätzlich Drahtlosnachrichten und leitet Pakete aus dem Festnetz drahtlos weiter.
-oc:tooltip.abstractbuscard=Erlaubt es, LIP-Pakete des Abstrakten Busses von §fStargateTech 2§7 zu senden und zu empfangen.
-oc:tooltip.acid=Eine hochgiftige Möchtegernflüssigkeit, wird üblicherweise nur von gewissen Piraten konsumiert. Mag sich aber auch zu anderen Zwecken eignen.
-oc:tooltip.adapter=Erlaubt es, Blöcke anzusteuern, die keine Komponentenblöcke sind, wie etwa reguläre Minecraft-Blöcke oder Blöcke anderer Mods.
-oc:tooltip.alu=Zählt Zahlen zum Zeitvertreib. Klingt komisch, is aber so.
-oc:tooltip.analyzer=Erlaubt es, Informationen über Blöcke anzuzeigen, wie zum Bleistift ihre §fAdresse§7 und ihren §fKomponentennamen§7.[nl] Erlaubt zudem, den Fehler anzuzeigen, der zu einem Computerabsturz geführt hat, falls der Computer nicht regulär heruntergefahren wurde.
-oc:tooltip.apu=Eine CPU mit integrierter GPU (bzw. IGP), falls du unbedingt den zusätzlichen Kartenslot brauchst.[nl] Unterstützte Komponenten: §f%s§7[nl] Höchstauflösung: §f%sx%s§7[nl] Maximale Farbtiefe: §f%s§7[nl] Operationen/Tick: §f%s§7
-oc:tooltip.assembler=Erlaubt die Fertigung von Robotern und weiteren Geräten aus diversen anderen Computerteilen.
-oc:tooltip.cable=Ein billiger Weg, verschiedene Blöcke miteinander zu verbinden.
-oc:tooltip.capacitor=Speichert Energie für spätere Verwendung. Kann extrem schnell befüllt und entleert werden.
-oc:tooltip.carpetedcapacitor=Speichert Energie für den späteren Gebrauch. Kann sehr schnell befüllt und entleert werden. Lädt auf, wenn Schafe oder Ozelots darauf laufen.
-oc:tooltip.cardbase=Wie der Name schon sagt, werden alle Erweiterungskarten hieraus hergestellt.
-oc:tooltip.case=Das Computergehäuse ist der essentielle Grundbaustein für einen Computer. §fErweiterungskarten§7, §fRAM§7 und §fFestplatten§7 können in einem Gehäuse installiert werden.[nl] Slots: §f%s§7
-oc:tooltip.chamelium=Rohmaterial für 3D-Drucke. Nicht zum Verzehr geeignet: kann zu Erblindung und zeitweiligem Verlust von Präsenz führen.
-oc:tooltip.chameliumblock=Schick und sauber. Praktisch für gefärbte Teile in 3D-Drucken, oder einfach, um deine tolle Basis mit einem schlichten, gefärbten Block zu dekorieren.
-oc:tooltip.charger=Lädt Roboter mit Energie aus Kondensatoren auf. Die Ladegeschwindigkeit hängt vom eingehenden §fRedstonesignal§7 ab, wobei kein Signal "nicht laden" und ein Signal mit maximaler Stärke "schnellstmöglich laden" heißt. Erlaubt es auch Tablets zu laden, und ermöglicht Zugriff auf Festplatten in Tablets.
-oc:tooltip.circuitboard=Mühsam ernährt sich das Eichhörnchen. Wenn es groß wird, wird es mal eine gedruckte Leiterplatte.
-oc:tooltip.controlunit=Klingt wichtig, ist es auch. Man baut daraus immerhin CPUs. Wie könnte es da nicht wichtig sein.
-oc:tooltip.componentbus=Diese Erweiterung erlaubt es es Servern, mit noch mehr Komponenten gleichzeitig zu kommunizieren, ähnlich wie CPUs.[nl] Unterstützte Komponenten: §f%s§7
-oc:tooltip.cpu=Kernstück eines jeden Computers. Die Taktrate hat einen leichten Schatten, aber was kann man von einer Taschensonnenuhr schon erwarten?[nl] Unterstützte Komponenten: §f%s§7
-oc:tooltip.cpu.Architecture=Architektur: §f%s§7
-oc:tooltip.cuttingwire=Wird gebraucht, um Tonblöcke in Leiterplattenform zu bekommen. Vermutlich das ineffizienteste Werkzeug in der Geschichte der Menschheit, da es nach einer Verwendung kaputt geht.
-oc:tooltip.datacard0=Stellt einige komplexe Algorithmen wie Hash-Funktionen und deflate/inflate bereit.
-oc:tooltip.datacard1=Stellt einige komplexe Algorithmen wie Hash-Funktionen und deflate/inflate bereit.
-oc:tooltip.datacard2=Stellt einige komplexe Algorithmen wie Hash-Funktionen und deflate/inflate bereit.
-oc:tooltip.debugcard=Kreativ-Modus-Gegenstand, erlaubt es die Welt zu manipulieren um das Testen zu erleichtern. Verwendung auf eigene Gefahr.
-oc:tooltip.debugger=Erlaubt, Informationen über OCs internes Netzwerk auszugeben. Nur verwenden, wenn von einem Entwickler dazu aufgefordert.
-oc:tooltip.diamondchip=Ein kleines Stück eines einst wunderschönen Diamanten. Er wird niemals wieder so sein, wie er war.
-oc:tooltip.disassembler=Zerlegt Gegenstände in ihre Einzelteile. §lWarnung§7: zurückgewonnene Gegenstände haben eine %s%%-ige Chance beim Extrahieren kaputt zu gehen!
-oc:tooltip.disk=Sehr einfaches Speichermedium, das verwendet werden kann, um Disketten und Festplatten zu fertigen.
-oc:tooltip.diskdrive.CC=ComputerCraft-Disketten werden §aauch unterstützt§7.
-oc:tooltip.diskdrive=Erlaubt es, Disketten zu lesen und zu beschreiben. Kann in Robotern installiert werden, um später Disketten einlegen zu können.
-oc:tooltip.diskdrivemountable=Funktioniert genauso wie ein normales Diskettenlaufwerk, wird aber in einem Serverschrank installiert.
-oc:tooltip.diskusage=Festplattennutzung: %s/%s Byte
-oc:tooltip.disklocked=Gesperrt von %s
-oc:tooltip.diskmodemanaged=Modus: Managed
-oc:tooltip.diskmodeunmanaged=Modus: Unmanaged
-oc:tooltip.drone=Drohnen sind schlichte, flinke Aufklärungseinheiten mit limitierter Inventargröße.
-oc:tooltip.dronecase=Dieses Gehäuse wird verwendet, um Drohnen in der Elektronik-Werkbank zu bauen. Es bietet Platz für wenige Komponenten und kommt mit endsteinbetriebener Levitation.
-oc:tooltip.eeprom=Kleiner, programmierbarer Speicher für das BIOS, das Computer zum starten verwenden.
-oc:tooltip.fakeendstone=So gut wie echt, kann sogar schweben!
-oc:tooltip.geolyzer=Erlaubt es die Härte der Blöcke in der Umgebung abzufragen. Hilfreich um Hologramme der Gegend zu erzeugen, oder um Erze zu entdecken.
-oc:tooltip.graphicscard=Erlaubt es, den angezeigten Inhalt von Bildschirmen zu ändern.[nl] Höchstauflösung: §f%sx%s§7[nl] Maximale Farbtiefe: §f%s§7[nl] Operationen/Tick: §f%s§7
-oc:tooltip.hoverboots=Spring höher, fall tiefer, geh besser. Dies und noch mehr bekommst du mit den neuen, patentierten Schwebestiefeln (TM).
-oc:tooltip.inkcartridge=Wird verwendet, um 3D-Drucker zu befüllen. Aus mysteriösen Gründen muss die Kartusche nicht fest im Drucker eingebaut werden.
-oc:tooltip.inkcartridgeempty=Diese Kartusche wurde trocken gelegt. Fülle sie mit Farben wieder auf. Oder wirf sie weg. Mir doch egal.
-oc:tooltip.internetcard=Diese Karte erlaubt es, HTTP-Anfragen zu senden und echte TCP-Sockets zu verwenden.
-oc:tooltip.interweb=Kann in einer Internetkarte verwendet werden, um Computer mit dem rechtsfreien Raum kommunizieren zu lassen.
-oc:tooltip.ironnugget=Ein Nugget, das aus Eisen besteht, darum wird es ja auch Eisennugget genannt, duh...
-oc:tooltip.keyboard=Kann an Bildschirmen befestigt werden, um auf ihnen zu tippen.
-oc:tooltip.hologram0=Ein Volumendisplay, das beliebige, von Computern festgelegte Voxelstrukturen anzeigt.[nl] Auflösung: §f48x32x48§7 [nl] Maximale Skalierung: §f3x§7 [nl] Farbtiefe: §fMonochrom§7
-oc:tooltip.hologram1=Ein Volumendisplay, das beliebige, von Computern festgelegte Voxelstrukturen anzeigt.[nl] Auflösung: §f48x32x48§7 [nl] Maximale Skalierung: §f4x§7 [nl] Farbtiefe: §fTricolor§7
-oc:tooltip.linkedcard=Diese Karten werden paarweise hergestellt, und können ausschließlich mit ihrer jeweilgen Partnerkarte kommunizieren, dafür allerdings über beliebige Entfernungen, und sogar über Dimensionen hinweg. Der Nachteil ist der hohe Energieverbrauch beim Senden einer Nachricht.
-oc:tooltip.linkedcard_channel=§8Kanal: %s§7
-oc:tooltip.manual=Alles, was es über OpenComputers zu wissen gibt. Und mehr. Und das alles zu dem unglaublich niedrigen Preis von... §obitte R dücken, um fortzufahren§7.
-oc:tooltip.materialcosts=Halte [§f%s§7] gedrückt für Materialkosten.
-oc:tooltip.materials=Materialien:
-oc:tooltip.memory=Braucht ein jeder Computer, um zu starten. Je mehr vorhanden, desto komplexere Programme können ausgeführt werden.
-oc:tooltip.microchip=Tritt auch unter dem Alias Integrierter Schaltkreis auf. Keine Ahnung, warum das auch mit Redstone klappt, aber es funktioniert.
-oc:tooltip.microcontroller=Mikrocontroller sind möglichst einfache Computer. Sie sind dazu gedacht, für Spezialfälle verwendet zu werden, bei denen sie einfach das Programm auf dem in ihnen eingebauten EEPROM ausführen sollen.
-oc:tooltip.microcontrollercase=Dieses Gehäuse wird verwendet, um Mikrocontroller in der Elektronik-Werkbank zu bauen. Platziere es in eine solche und füge weitere Komponenten hinzu, um einen Mikrocontroller zu erstellen.
-oc:tooltip.motionsensor=Kann Bewegungen sich in der Nähe befindender Lebewesen erkennen. Benötigt eine klare Sichtlinie.
-oc:tooltip.nanomachines=Kontrolleinheit und eine Menge Nanomaschinen zur Einnahme, sofern du dich traust.
-oc:tooltip.networkcard=Erlaubt es Computern, die über mehrere Blöcke miteinander verbunden sind (z.B. Kabel), mittels Netzwerknachrichten zu kommunizieren.
-oc:tooltip.poweracceptor=Energiewandelgeschwindigkeit: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fBuildCraft MJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fFactorization Charge§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fIndustrialCraft² EU§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fMekanism Joules§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fThermal Expansion RF§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=Wandelt Strom anderer Mods in den internen Energietyp um. Umwandlungsverhältnisse:
-oc:tooltip.powerdistributor=Verteilt Energie zwischen mehreren Netzwerken. Nützlich, um Energie mit einem Wandler auf mehrere Subnetze, die voneinander getrennt sein sollen, zu verteilen.
-oc:tooltip.present=... für deine Mühen. Öffne dieses Geschenk für eine Chance, §kdolle Dinge§7 zu erhalten![nl]§8Fertige OpenComputers-Gegenstände zur rechten Zeit, und du hast die Chance ein Geschenk zu erhalten.§7
-oc:tooltip.print.BeaconBase=§8Funktioniert als Grundstein für ein Leuchtfeuer.
-oc:tooltip.print.LightValue=§8Leuchtkraft: %s.
-oc:tooltip.print.RedstoneLevel=§8Redstone-Signalstärke: %s.
-oc:tooltip.printedcircuitboard=Hierauf basieren alle Erweiterungskarten, Speicher und so weiter.
-oc:tooltip.printer=Erlaubt es, Blöcke aus benutzerdefinierten Formen zu drucken. Verwendet Chamälium und Tintenkartuschen. Muss über einen Computer konfiguriert werden. Von Kindern fern halten. Weil halt.
-oc:tooltip.raid=Erlaubt es, drei Festplatten zu einem größeren Dateisystem zusammenzuschließen, welches von allen verbundenen Computern genutzt werden kann.
-oc:tooltip.rawcircuitboard=Kann in einer Ofen-kompatiblen Schmelze freier Wahl gehärtet werden.
-oc:tooltip.redstone=Erlaubt das Lesen und Ausgeben von Redstonesignalen um den Block herum. Kann von jedem Computer, der mit dem Block verbunden ist, gesteuert werden. Dieser Block ist quasi wie eine externe Redstonekarte.
-oc:tooltip.redstonecard.ProjectRed=§fProjectRed§7 wird §aunterstützt§7.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 wird §aunterstützt§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 wird §aunterstützt§7.
-oc:tooltip.redstonecard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 wird §aunterstützt§7.
-oc:tooltip.redstonecard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 wird §aunterstützt§7.
-oc:tooltip.redstonecard=Erlaubt das Lesen und Ausgeben von Redstonesignalen um den Computer oder Roboter herum.
-oc:tooltip.relay=Erlaubt es, mehrere Netzwerke miteinander zu verbinden. Leitet ausschließlich Netzwerknachrichten weiter, Komponenten "hinter" dem Switch sind nicht sichtbar. Nützlich, um Netzwerke zu trennen, jedoch nach wie vor Kommunikation zwischen den Netzwerken zu erlauben, z.b. mittels Netzwerkkarten.
-oc:tooltip.robot=Im Gegensatz zu normalen Computern können sich Roboter in der Welt bewegen und ähnlich wie Spieler mit der Welt interagieren. Sie können jedoch §onicht§r§7 mit externen Komponenten interagieren!
-# The underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fStufe§7: §a%s§7.
-oc:tooltip.robot_storedenergy=§fGespeicherte Energie§7: §a%s§7.
-oc:tooltip.screen=Zeigt Text an, gesteuert von Grafikkarten in Computern.[nl] Höchstauflösung: §f%sx%s§7[nl] Maximale Farbtiefe: §f%s§7
-oc:tooltip.server=Ein Server kann wie ein gewöhnliches Computergehäuse mit Komponenten verbessert werden. Um den Server zu starten, muss er in einem Servergehäuse installiert werden.
-oc:tooltip.server.Components=Installierte Komponenten:
-oc:tooltip.rack=Erlaubt die Installation von bis zu vier Servern oder anderen Serverschrankkomponenten.
-oc:tooltip.switch=Erlaubt es, mehrere Netzwerke miteinander zu verbinden. Leitet ausschließlich Netzwerknachrichten weiter, Komponenten "hinter" dem Switch sind nicht sichtbar. Nützlich, um Netzwerke zu trennen, jedoch nach wie vor Kommunikation zwischen den Netzwerken zu erlauben, z.B. mittels Netzwerkkarten.
-oc:tooltip.tablet=Ein Tablet-PC, für Lua unterwegs. Kann durch Sneak-Aktivierung zwangsgestoppt werden.
-oc:tooltip.tabletcase=Einfaches Gehäuse für Tablet-PCs. Kann in der Elektronik-Werkbank mit Komponenten bestückt werden, um einen Tablet-PC zu fertigen.
-oc:tooltip.terminal=Erlaubt es, einen Server aus der Ferne zu steuern, so lange man sich in Reichweite des Servers befindet. Verhält sich wie Bildschirm und Tastatur in einem. Kann mit Shift-Rechtsklick an einen Server in einem Serverschrank gebunden werden.
-oc:tooltip.terminalserver=Das Rückgrat für Fernzugriff. Fernbedienungen können hiermit verbunden werden. Enthält virtuelle Tastatur und Bildschirm.
-oc:tooltip.texturepicker=Dieses Werkzeug erlaubt es, eine Zeichenkette anzuzeigen, die die Oberfläche eines Blocks beschreibt und in Form-Definitionen für 3D-Drucker verwendet werden kann. Definiv keine Texturnamen, oh nein. Nix da.
-oc:tooltip.tier=§8Stufe %s
-oc:tooltip.netsplitter=Kann Netzwerke dynamisch verbinden. Die Konnektivität jeder Seite kann umgeschaltet werden, in dem man "Professionelle Wartungsarbeiten" mit einem Schraubenschlüssel durchführt. Sie kann auch mit einem Redstone-Signal an entsprechenden Seiten invertiert werden.
-oc:tooltip.toolong=Halte [§f%s§7] gedrückt für mehr Infos.
-oc:tooltip.transistor=Elementarer Baustein der meisten Computerkomponenten. Nicht zu verwechseln mit Steinelementaren.
-oc:tooltip.transposer=Ermöglicht automatischen Transfer von Items und Flüssigkeiten zwischen angrenzenden Blöcken.
-oc:tooltip.upgradeangel=Erlaubt es Robotern, Blöcke in die Luft zu setzen, selbst wenn kein Referenzblock daneben existiert.
-oc:tooltip.upgradebattery=Erhöht die Energiespeicherkapazität eines Roboters, was ihm erlaubt, länger zu arbeiten, ohne erneut aufgeladen werden zu müssen.[nl] Kapazität: §f%s§7
-oc:tooltip.upgradechunkloader=Wenn sich im Wald ein Roboter bewegt, und niemand da ist, ihn zu sehen, bewegt er sich dann wirklich? Dieses Upgrade stellt sicher, dass dem so ist. Es hält den Chunk, in dem sich der Roboter befindet, geladen, verbraucht jedoch Energie, während es aktiv ist.
-oc:tooltip.upgradecontainercard=Dieses Behälter-Upgrade erlaubt es, eine Karte in einem bereits zusammengebauten Roboter zu installieren und wieder zu entfernen.[nl] Maximale Stufe: §f%s§7
-oc:tooltip.upgradecontainerupgrade=Dieses Behälter-Upgrade erlaubt es, ein Upgrade in einem bereits zusammengebauten Roboter zu installieren und wieder zu entfernen.[nl] Maximale Stufe: §f%s§7
-oc:tooltip.upgradecrafting=Ermöglicht Robotern, in dem oberen linken Bereich ihres Inventars Dinge zu fertigen. Gegenstände müssen so angeordnet sein, wie sie es in einer Werkbank wären.
-oc:tooltip.upgradedatabase=Diese Upgrade erlaubt es, Gegenstandsinformationen - für spätere Verwendung in anderen Komponenten - zu speichern.[nl] Maximale Einträge: §f%s§7
-oc:tooltip.upgradeexperience=Dieses Upgrade erlaubt es Robotern, durch verschiedene Aktionen Erfahrung zu sammeln. Je mehr Erfahrung ein Roboter hat, desto mehr Energie kann er speichern, desto schneller kann er Blöcke abbauen und desto effizienter kann er mit Werkzeugen umgehen.
-oc:tooltip.upgradegenerator=Kann verwendet werden, um unterwegs Energie aus Brennstoffen zu erzeugen. Verbraucht Gegenstände über einen ihrem Brennwert gemäßen Zeitraum.[nl] §fEffizienz§7: §a%s%%§7
-oc:tooltip.upgradehover=Erlaubt Robotern höher zu fliegen, ohne an Wänden klettern zu müssen.[nl] Maximalhöhe: §f%s§7
-oc:tooltip.upgradeinventory=Dieses Upgrade gibt Robotern ein internes Inventar. Ohne ein solches Upgrade können Roboter keine Gegenstände verwahren.
-oc:tooltip.upgradeinventorycontroller=Dieses Upgrade erlaubt es dem Roboter, präziser mit externen Inventaren zu interagieren, und erlaubt es ihm, das angelegte Werkzeug mit einem Gegenstand in seinem Inventar auszutauschen.
-oc:tooltip.upgrademf=Erlaubt es Adaptern, mit Blöcken zu interagieren, die etwas weiter weg sind.
-oc:tooltip.upgrademf.Linked=§fVerbindung hergestellt§7
-oc:tooltip.upgrademf.Unlinked=§fKeine Verbindung§7
-oc:tooltip.upgradeleash=Erlaubt es manchen Geräten, wie etwa Drohnen, B- *getuschel* Verzeihung. Mir wurde soeben zugetragen, dass es tatsächlich dazu verwendet werden kann, Tiere an die Leine zu legen. Sogar viele Viecher.
-oc:tooltip.upgradenavigation=Erlaubt es Robotern, ihre Position und Ausrichtung zu bestimmen. Die Position ist relativ zur Mitte der Karte, die in diesem Upgrade verbaut wurde.
-oc:tooltip.upgradepiston=Dieses Upgrade ist sehr drückend. Es macht es möglich Blöcke zu verschieben, ähnlich dem Kolben. Es kann jedoch §lkeine§7 Entities bewegen.
-oc:tooltip.upgradesign=Erlaubt das Lesen und Schreiben von Text auf Schildern.
-oc:tooltip.upgradesolargenerator=Kann verwendet werden, um unterwegs Energie aus Sonnenlicht zu generieren. Benötigt eine ungehinderte Sicht zum Himmel über dem Roboter. Generiert Energie mit %s%% der Geschwindigkeit eines Stirlingmotors.
-oc:tooltip.upgradetank=Dieses Upgrade gibt Robotern einen internen Tank. Ohne ein solches Upgrade können Roboter keine Flüssigkeiten verwahren.
-oc:tooltip.upgradetankcontroller=Dieses Upgrade erlaubt es dem Roboter, präziser mit externen Tanks zu interagieren, und erlaubt es ihm, Flüssigkeiten in und aus sich im Inventar befindlichen Tank-Gegenständen zu pumpen.
-oc:tooltip.upgradetractorbeam=Stattet den Roboter mit unglaublich fortschrittlicher Technologie - Kosename: "Gegenstandsmagnet" - aus. Erlaubt es dem Roboter, Gegenstände, innerhalb von 3 Blöcken um sich herum, einzusammeln.
-oc:tooltip.waypoint=Ein Orientierungpunkt für Geräte mit einem Navigations-Upgrade.
-oc:tooltip.wirelessnetworkcard=Erlaubt das drahtlose Senden von Netzwerknachrichten, zusätzlich zu normalen. Drahtlose Nachrichten werden nur gesendet, wenn eine §fSignalstärke§7 festgelegt wurde!
-oc:tooltip.worldsensorcard=Erlaubt es, Informationen über die Welt auszulesen, wie etwa Gravitation und ob die Atmosphäre atembar ist. Verwendung von Messergebnissen auf eigene Gefahr. Der Hersteller übernimmt keinerlei Garantie.
-oc:tooltip.wrench=Eine Mischung aus Schraubenzieher und Schraubenschlüssel, einfach zu benutzen, aber schwer zu meistern.
-
-#Achievements
-achievement.oc.adapter=Steck mich ein
-achievement.oc.adapter.desc=Interagiert mit Blöcken aus anderen Mods, und sogar Vanilla-Minecraft!
-achievement.oc.assembler=Wundervoll
-achievement.oc.assembler.desc=Zeit, die Welt zu erobern!
-achievement.oc.cable=Kein gewöhnliches Kabel
-achievement.oc.cable.desc=Mit patentierter Anti-Kabelsalat-Technologie.
-achievement.oc.capacitor=Batterien enthalten
-achievement.oc.capacitor.desc=Achtung: Kurzschlussgefahr.
-achievement.oc.card=Wir akzeptieren Karten
-achievement.oc.card.desc=Dreimal falsche PIN-Eingabe. Karte wird einbehalten.
-achievement.oc.case=Desktop-Computer
-achievement.oc.case.desc=Desktop (und Betriebssystem) separat erhältlich.
-achievement.oc.charger=Die Spannung steigt
-achievement.oc.charger.desc=Und auflad- verdammt, schon wieder das Redstone-Signal vergessen.
-achievement.oc.chip=Technischer Fortschritt
-achievement.oc.chip.desc=Besser als Elekrtonenröhren.
-achievement.oc.cpu=Übertaktet
-achievement.oc.cpu.desc=Endlich ein Nutzen für die ungenutzten Prozessorzyklen.
-achievement.oc.disassembler=Nochmal von vorn
-achievement.oc.disassembler.desc=Falls deine brillianten Ideen am Ende doch nicht so brilliant sind.
-achievement.oc.diskDrive=*klick brumm brumm brumm ratter*
-achievement.oc.diskDrive.desc=Weniger Speicherplatz, aber welch ein wundervolles Geräusch.
-achievement.oc.drone=Startbereit
-achievement.oc.drone.desc=Keep calm and nuke it from orbit.
-achievement.oc.eeprom=Es kann nur einen geben
-achievement.oc.eeprom.desc=Pro Computer, genau genommen. Für eine deterministische Boot-Reihenfolge, weißt du?
-achievement.oc.floppy=Der Eine Ri- Datenspeicher
-achievement.oc.floppy.desc=Nicht zu verwechseln mit Flappy.
-achievement.oc.geolyzer=Gezielte Rohstoffsuche
-achievement.oc.geolyzer.desc=Umweltfreundlicher als Fracking, versprochen.
-achievement.oc.graphicsCard=LastGen
-achievement.oc.graphicsCard.desc=The way it's meant to be... äh... rendered. Ja. So ungefähr.
-achievement.oc.hdd=Hotdog-Dealer
-achievement.oc.hdd.desc=Moment, das stimmt nicht ganz. Warte, gleich hab' ich's...
-achievement.oc.hologram=Eine höhere Dimension
-achievement.oc.hologram.desc=Weil 2D so langweilig ist. Oder ist es das wirklich?
-achievement.oc.keyboard=SchmutzFänger3000
-achievement.oc.keyboard.desc=Es wird davon abgeraten, sie umzudrehen und zu schütteln, auch wenn es noch so verlockend ist.
-achievement.oc.microcontroller=Kleine Schwester
-achievement.oc.microcontroller.desc=Das kleine Geschwisterkind des Computers.
-achievement.oc.motionSensor=Got the Moves
-achievement.oc.motionSensor.desc=Like Steve Swagger.
-achievement.oc.networkCard=Fernleitung
-achievement.oc.networkCard.desc=Perfekt um diese transitiven Beziehungen aufrecht zu erhalten.
-achievement.oc.openOS=Boot
-achievement.oc.openOS.desc=Das Eine Betrieb- wie, was meinst du, der Witz wird alt?
-achievement.oc.powerDistributor=Strom-Sharing
-achievement.oc.powerDistributor.desc=ElektroVZ ist so 2010.
-achievement.oc.rack=Multifunktionsschrank
-achievement.oc.rack.desc=Wird unter Anderem in Kantinen genutzt, um gebrauchte Tabletts zu sammeln.
-achievement.oc.raid=Suche Team
-achievement.oc.raid.desc=Heroic plzkthx.
-achievement.oc.ram=Random Access Memories
-achievement.oc.ram.desc=Congratulations, you're Doin' It Right.
-achievement.oc.redstoneCard=Kontakt
-achievement.oc.redstoneCard.desc=Zeit für analoge Signale.
-achievement.oc.redstoneIO=Außenseiter
-achievement.oc.redstoneIO.desc=Redstone-Signale, dort wo du sie brauchst.
-achievement.oc.robot=Beep Boop
-achievement.oc.robot.desc=VERNICHTEN!
-achievement.oc.screen=Hast du schon versucht, ihn aus- und wieder anzuschalten?
-achievement.oc.screen.desc=Nein, ernsthaft. Ein Redstone-Impuls kann wirklich einen Bildschirm an- und ausschalten.
-achievement.oc.server=Dediziert
-achievement.oc.server.desc=Hier kommen die Cloud-Dienste.
-achievement.oc.switch=Paketdienst
-achievement.oc.switch.desc=Nicht für Hinkelsteine verwenden, die könnten sonst beim Aussortieren verloren gehen.
-achievement.oc.tablet=Verschluckbare Kleinteile
-achievement.oc.tablet.desc=Von Kindern fernhalten, um unerwünschte Kreditkartenbelastungen zu vermeiden.
-achievement.oc.transistor=Schöne Grüße an Red!
-achievement.oc.transistor.desc=Jetzt kannst du dir den Soundtrack anhören.
-achievement.oc.wirelessNetworkCard=Das WLAN - Unendliche Weiten
-achievement.oc.wirelessNetworkCard.desc=Netzwerke, die nie ein Paket zuvor gesehen hat.
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code.
-death.attack.oc.nanomachinesOverload.1=%s ist zu gierig geworden.
-death.attack.oc.nanomachinesOverload.2=%s erlitt einen Nervenzusammenbruch.
-death.attack.oc.nanomachinesOverload.3=Die Nanomaschinen von %s gerieten wohl außer Kontrolle. Ups.
-death.attack.oc.nanomachinesHungry.1=%s wurde von Nanomaschinen verspeist.
-death.attack.oc.nanomachinesHungry.2=%s hat wohl seine Nanomaschinen nicht gefüttert.
-death.attack.oc.nanomachinesHungry.3=%s wurde verdaut.
-
-# NEI Integration
-nei.options.inventory.oredict=OreDictionary-Namen anzeigen
-nei.options.inventory.oredict.true=True
-nei.options.inventory.oredict.false=False
-nei.usage.oc.Manual=Handbuch öffnen
-
-# Waila Integration
-option.oc.address=Adresse
-option.oc.componentName=Komponentenname
-option.oc.energy=Energie
diff --git a/src/main/resources/assets/opencomputers/lang/de_de.json b/src/main/resources/assets/opencomputers/lang/de_de.json
new file mode 100644
index 0000000000..d5b7cc62d3
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/de_de.json
@@ -0,0 +1,460 @@
+{
+ "tile.oc.adapter": "Adapter",
+ "tile.oc.assembler": "Elektronik-Werkbank",
+ "tile.oc.cable": "Kabel",
+ "tile.oc.capacitor": "Kondensator",
+ "tile.oc.carpetedcapacitor": "Teppichkondensator",
+ "tile.oc.case1": "Computergehäuse (Stufe 1)",
+ "tile.oc.case2": "Computergehäuse (Stufe 2)",
+ "tile.oc.case3": "Computergehäuse (Stufe 3)",
+ "tile.oc.caseCreative": "Computergehäuse (Kreativ)",
+ "tile.oc.chameliumBlock": "Chamälium-Block",
+ "tile.oc.charger": "Ladestation",
+ "tile.oc.disassembler": "Recycler",
+ "tile.oc.diskDrive": "Diskettenlaufwerk",
+ "tile.oc.endstone": "Endstein",
+ "tile.oc.geolyzer": "Geolyzer",
+ "tile.oc.hologram1": "Hologrammprojektor (Stufe 1)",
+ "tile.oc.hologram2": "Hologrammprojektor (Stufe 2)",
+ "tile.oc.keyboard": "Tastatur",
+ "tile.oc.microcontroller": "Mikrocontroller",
+ "tile.oc.motionSensor": "Bewegungsmelder",
+ "tile.oc.netSplitter": "Net Splitter",
+ "tile.oc.powerConverter": "Leistungswandler",
+ "tile.oc.powerDistributor": "Stromverteiler",
+ "tile.oc.print": "3D-Druck",
+ "tile.oc.printer": "3D-Drucker",
+ "tile.oc.raid": "Raid",
+ "tile.oc.redstone": "Redstone-I/O",
+ "tile.oc.relay": "Relais",
+ "tile.oc.robot": "Roboter",
+ "tile.oc.robotAfterimage": "Roboter",
+ "tile.oc.screen1": "Bildschirm (Stufe 1)",
+ "tile.oc.screen2": "Bildschirm (Stufe 2)",
+ "tile.oc.screen3": "Bildschirm (Stufe 3)",
+ "tile.oc.rack": "Serverschrank",
+ "tile.oc.transposer": "Transposer",
+ "tile.oc.waypoint": "Wegpunkt",
+ "item.oc.AbstractBusCard": "Abstrakter-Bus-Karte",
+ "item.oc.Acid": "Grog",
+ "item.oc.ALU": "Arithmetisch-logische Einheit (ALU)",
+ "item.oc.Analyzer": "Messgerät",
+ "item.oc.APU0": "Beschleunigter Prozessor (APU) (Stufe 1)",
+ "item.oc.APU1": "Beschleunigter Prozessor (APU) (Stufe 2)",
+ "item.oc.APU2": "Beschleunigter Prozessor (APU) (Kreativ)",
+ "item.oc.ArrowKeys": "Pfeiltasten",
+ "item.oc.ButtonGroup": "Tastengruppe",
+ "item.oc.CardBase": "Kartenbasis",
+ "item.oc.Chamelium": "Chamälium",
+ "item.oc.CircuitBoard": "Leiterplatte",
+ "item.oc.ComponentBus0": "Komponentenschnittstelle (Stufe 1)",
+ "item.oc.ComponentBus1": "Komponentenschnittstelle (Stufe 2)",
+ "item.oc.ComponentBus2": "Komponentenschnittstelle (Stufe 3)",
+ "item.oc.componentbus3": "Komponentenschnittstelle (Kreativ)",
+ "item.oc.ControlUnit": "Steuerwerk (CU)",
+ "item.oc.CPU0": "Hauptprozessor (CPU) (Stufe 1)",
+ "item.oc.CPU1": "Hauptprozessor (CPU) (Stufe 2)",
+ "item.oc.CPU2": "Hauptprozessor (CPU) (Stufe 3)",
+ "item.oc.CuttingWire": "Schneidedraht",
+ "item.oc.DataCard0": "Datenkarte (Stufe 1)",
+ "item.oc.DataCard1": "Datenkarte (Stufe 2)",
+ "item.oc.DataCard2": "Datenkarte (Stufe 3)",
+ "item.oc.DebugCard": "Debug-Karte",
+ "item.oc.Debugger": "Netzwerk-Debugger",
+ "item.oc.DiamondChip": "Diamantsplitter",
+ "item.oc.Disk": "Platte",
+ "item.oc.DiskDriveMountable": "Diskettenlaufwerk",
+ "item.oc.Drone": "Drohne",
+ "item.oc.DroneCase0": "Drohnengehäuse (Stufe 1)",
+ "item.oc.DroneCase1": "Drohnengehäuse (Stufe 2)",
+ "item.oc.DroneCase3": "Drohnengehäuse (Kreativ)",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.FloppyDisk": "Diskette",
+ "item.oc.GraphicsCard0": "Grafikkarte (Stufe 1)",
+ "item.oc.GraphicsCard1": "Grafikkarte (Stufe 2)",
+ "item.oc.GraphicsCard2": "Grafikkarte (Stufe 3)",
+ "item.oc.HardDiskDrive0": "Festplatte (Stufe 1)",
+ "item.oc.HardDiskDrive1": "Festplatte (Stufe 2)",
+ "item.oc.HardDiskDrive2": "Festplatte (Stufe 3)",
+ "item.oc.hoverBoots": "Schwebestiefel",
+ "item.oc.InkCartridge": "Tintenkartusche",
+ "item.oc.InkCartridgeEmpty": "Tintenkartusche (Leer)",
+ "item.oc.InternetCard": "Internetkarte",
+ "item.oc.Interweb": "Internetz",
+ "item.oc.IronNugget": "Eisennugget",
+ "item.oc.LinkedCard": "Verknüpfte Karte",
+ "item.oc.Manual": "OpenComputers-Handbuch",
+ "item.oc.Memory0": "Speicher (Stufe 1)",
+ "item.oc.Memory1": "Speicher (Stufe 1.5)",
+ "item.oc.Memory2": "Speicher (Stufe 2)",
+ "item.oc.Memory3": "Speicher (Stufe 2.5)",
+ "item.oc.Memory4": "Speicher (Stufe 3)",
+ "item.oc.Memory5": "Speicher (Stufe 3.5)",
+ "item.oc.Microchip0": "Mikrochip (Stufe 1)",
+ "item.oc.Microchip1": "Mikrochip (Stufe 2)",
+ "item.oc.Microchip2": "Mikrochip (Stufe 3)",
+ "item.oc.MicrocontrollerCase0": "Mikrocontroller-Gehäuse (Stufe 1)",
+ "item.oc.MicrocontrollerCase1": "Mikrocontroller-Gehäuse (Stufe 2)",
+ "item.oc.MicrocontrollerCase3": "Mikrocontroller-Gehäuse (Kreativ)",
+ "item.oc.Nanomachines": "Nanomaschinen",
+ "item.oc.NetworkCard": "Netzwerkkarte",
+ "item.oc.NumPad": "Ziffernblock",
+ "item.oc.Present": "Ein kleines Etwas...",
+ "item.oc.PrintedCircuitBoard": "Gedruckte Leiterplatte (PCB)",
+ "item.oc.RawCircuitBoard": "Leiterplattenrohling",
+ "item.oc.RedstoneCard0": "Redstonekarte (Stufe 1)",
+ "item.oc.RedstoneCard1": "Redstonekarte (Stufe 2)",
+ "item.oc.Server0": "Server (Stufe 1)",
+ "item.oc.Server1": "Server (Stufe 2)",
+ "item.oc.Server2": "Server (Stufe 3)",
+ "item.oc.Server3": "Server (Kreativ)",
+ "item.oc.Tablet": "Tablet",
+ "item.oc.TabletCase0": "Tablet-Gehäuse (Stufe 1)",
+ "item.oc.TabletCase1": "Tablet-Gehäuse (Stufe 2)",
+ "item.oc.TabletCase3": "Tablet-Gehäuse (Kreativ)",
+ "item.oc.Terminal": "Fernbedienung",
+ "item.oc.TerminalServer": "Terminalserver",
+ "item.oc.TexturePicker": "Texturenwähler",
+ "item.oc.Transistor": "Transistor",
+ "item.oc.UpgradeAngel": "Schwebe-Upgrade",
+ "item.oc.UpgradeBattery0": "Akku-Upgrade (Stufe 1)",
+ "item.oc.UpgradeBattery1": "Akku-Upgrade (Stufe 2)",
+ "item.oc.UpgradeBattery2": "Akku-Upgrade (Stufe 3)",
+ "item.oc.UpgradeChunkloader": "Chunkloader-Upgrade",
+ "item.oc.UpgradeContainerCard0": "Karten-Behälter (Stufe 1)",
+ "item.oc.UpgradeContainerCard1": "Karten-Behälter (Stufe 2)",
+ "item.oc.UpgradeContainerCard2": "Karten-Behälter (Stufe 3)",
+ "item.oc.UpgradeContainerUpgrade0": "Upgrade-Behälter (Stufe 1)",
+ "item.oc.UpgradeContainerUpgrade1": "Upgrade-Behälter (Stufe 2)",
+ "item.oc.UpgradeContainerUpgrade2": "Upgrade-Behälter (Stufe 3)",
+ "item.oc.UpgradeCrafting": "Crafting-Upgrade",
+ "item.oc.UpgradeDatabase0": "Datenbank-Upgrade (Stufe 1)",
+ "item.oc.UpgradeDatabase1": "Datenbank-Upgrade (Stufe 2)",
+ "item.oc.UpgradeDatabase2": "Datenbank-Upgrade (Stufe 3)",
+ "item.oc.UpgradeExperience": "Erfahrungs-Upgrade",
+ "item.oc.UpgradeGenerator": "Generator-Upgrade",
+ "item.oc.UpgradeHover0": "Schwebe-Upgrade (Stufe 1)",
+ "item.oc.UpgradeHover1": "Schwebe-Upgrade (Stufe 2)",
+ "item.oc.UpgradeInventory": "Inventar-Upgrade",
+ "item.oc.UpgradeInventoryController": "Inventarbedienungs-Upgrade",
+ "item.oc.UpgradeLeash": "Leinen-Upgrade",
+ "item.oc.UpgradeMF": "MFU",
+ "item.oc.UpgradeNavigation": "Navigations-Upgrade",
+ "item.oc.UpgradePiston": "Kolben-Upgrade",
+ "item.oc.UpgradeSign": "Schild-I/O-Upgrade",
+ "item.oc.UpgradeSolarGenerator": "Solargenerator-Upgrade",
+ "item.oc.UpgradeTank": "Tank-Upgrade",
+ "item.oc.UpgradeTankController": "Tankbedienungs-Upgrade",
+ "item.oc.UpgradeTractorBeam": "Traktorstrahl-Upgrade",
+ "item.oc.UpgradeTrading": "Handels-Upgrade",
+ "item.oc.WirelessNetworkCard0": "Drahtlosnetzwerkkarte (Stufe 1)",
+ "item.oc.WirelessNetworkCard1": "Drahtlosnetzwerkkarte (Stufe 2)",
+ "item.oc.WorldSensorCard": "Weltsensorkarte",
+ "item.oc.wrench": "Schraubenziehschlüssel",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "Drohne",
+ "oc:gui.Analyzer.Address": "§6Adresse§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Adresse wurde in die Zwischenablage kopiert.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Ladegeschwindigkeit§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Komponentenname§f: %s",
+ "oc:gui.Analyzer.Components": "§6Anzahl verbundener Komponenten§f: %s",
+ "oc:gui.Analyzer.CopyToClipboard": "In die Zwischenablage kopieren.",
+ "oc:gui.Analyzer.LastError": "§6Letzter Fehler§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Name§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Besitzer§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Erfahrung§f: %s (Stufe %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6Gespeicherte Energie§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Insgesamt gespeicherte Energie§f: %s",
+ "oc:gui.Analyzer.Users": "§6Benutzer§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Signalstärke§f: %s",
+ "oc:gui.Assembler.Collect": "Fertiges Gerät entnehmen",
+ "oc:gui.Assembler.Complexity": "Komplexität: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Grundbaustein einlegen",
+ "oc:gui.Assembler.InsertCPU": "CPU benötigt",
+ "oc:gui.Assembler.InsertRAM": "RAM benötigt",
+ "oc:gui.Assembler.Progress": "Fortschritt: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Zusammenbauen",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Grafikkarte",
+ "oc:gui.Assembler.Warning.Inventory": "Inventar-Upgrade",
+ "oc:gui.Assembler.Warning.Keyboard": "Tastatur",
+ "oc:gui.Assembler.Warning.OS": "Bootbares Medium",
+ "oc:gui.Assembler.Warning.Screen": "Bildschirm",
+ "oc:gui.Assembler.Warnings": "§eWarnung§7: Empfohlene Komponenten fehlen.",
+ "oc:gui.Chat.NewVersion": "Eine neue Version ist verfügbar: %s",
+ "oc:gui.Chat.TextureName": "§7Texturname ist §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "Es gab §cFehler§f beim Ausführen des Class-Transformers. Bitte melde dies, zusammen mit deiner (vollständigen!) FML §alatest.log§f/§afml-server-latest.log§f Log-Datei, danke!",
+ "oc:gui.Chat.WarningFingerprint": "§cWARNUNG§f - ungültige Signatur! Sollte '§a%s§f' sein, aber war '§e%s§f'. Falls du kein Modder bist und die \"deobfuscated\"-Version des Mods benutzt, solltest du OpenComputers erneut herunterladen, da die JAR, die du benutzt, vermutlich modifiziert wurde.",
+ "oc:gui.Chat.WarningLink": "Link konnte nicht geöffnet werden: %s",
+ "oc:gui.Chat.WarningLuaFallback": "Die native Lua-Implementierung ist nicht verfügbar. Computer können ihren Ausführungszustand nicht speichern. Sie werden automatisch neu starten, sobald ein Chunk neu geladen wird.",
+ "oc:gui.Chat.WarningProjectRed": "Die verwendete Version von Project: Red ist nicht mit OpenComputers kompatibel. Aktualisiere bitte deine Version von Project: Red.",
+ "oc:gui.Chat.WarningRecipes": "Es gab Fehler beim Laden eines oder mehrerer Rezepte. Einige Gegenstände können unter Umständen nicht gefertigt werden. Bitte wirf einen Blick in deine Log-Datei für weitere Informationen.",
+ "oc:gui.Drive.Managed": "Managed",
+ "oc:gui.Drive.Unmanaged": "Unmanaged",
+ "oc:gui.Drive.ReadOnlyLock": "Sperre",
+ "oc:gui.Drive.ReadOnlyLockWarning": "§lNur Lesen§r Sperre. Kann nur entfernt werden, wenn das Laufwerk gelöscht wird.",
+ "oc:gui.Drive.Warning": "§lWarnung§r: Umschalten der Modi führt zum Datenverlust.",
+ "oc:gui.Error.ComponentOverflow": "Zu viele Komponenten sind mit dem Computer verbunden.",
+ "oc:gui.Error.InternalError": "Interner Fehler, bitte sieh in der Logdatei nach. Das ist wahrscheinlich ein Bug.",
+ "oc:gui.Error.NoCPU": "Im Computer ist kein Hauptprozessor (CPU) installiert.",
+ "oc:gui.Error.NoEnergy": "Nicht genug Energie.",
+ "oc:gui.Error.NoRAM": "Im Computer ist kein RAM installiert.",
+ "oc:gui.Error.OutOfMemory": "Nicht genug Arbeitsspeicher.",
+ "oc:gui.Manual.Blocks": "OpenComputers-Blöcke",
+ "oc:gui.Manual.Home": "Startseite",
+ "oc:gui.Manual.Items": "OpenComputers-Gegenstände",
+ "oc:gui.Manual.Warning.BlockMissing": "Block nicht verfügbar.",
+ "oc:gui.Manual.Warning.ImageMissing": "Bild nicht gefunden.",
+ "oc:gui.Manual.Warning.ItemMissing": "Gegenstand nicht verfügbar.",
+ "oc:gui.Manual.Warning.OreDictMissing": "Ore-Dictionary-Eintrag nicht verfügbar.",
+ "oc:gui.Raid.Warning": "§4Platten werden beim Einsetzen\ngelöscht. Entfernen einer Platte\nlöscht das gesamte Raid.",
+ "oc:gui.Robot.Power": "Energie",
+ "oc:gui.Robot.TurnOff": "Ausschalten",
+ "oc:gui.Robot.TurnOn": "Einschalten\n§7Nutze ein Messgerät, um Fehler zu behandeln.§r",
+ "oc:gui.Rack.Back": "Hinten",
+ "oc:gui.Rack.Bottom": "Unten",
+ "oc:gui.Rack.Left": "Links",
+ "oc:gui.Rack.None": "Keine",
+ "oc:gui.Rack.Right": "Rechts",
+ "oc:gui.Rack.Enabled": "Aktiv",
+ "oc:gui.Rack.Disabled": "Inaktiv",
+ "oc:gui.Rack.Top": "Oben",
+ "oc:gui.Switch.PacketsPerCycle": "Pakete / Zyklus",
+ "oc:gui.Switch.QueueSize": "Puffergröße",
+ "oc:gui.Switch.TransferRate": "Taktung",
+ "oc:gui.Terminal.InvalidKey": "Ungültiger Schlüssel, vermutlich wurde eine andere Fernbedienung an den Server gebunden.",
+ "oc:gui.Terminal.OutOfRange": "Kein Signal.",
+ "oc:container.adapter": "Adapter",
+ "oc:container.case": "Computer",
+ "oc:container.charger": "Ladestation",
+ "oc:container.disassembler": "Recycler",
+ "oc:container.diskdrive": "Diskettenlaufwerk",
+ "oc:container.printer": "Drucker",
+ "oc:container.raid": "Raid",
+ "oc:container.relay": "Relais",
+ "oc:container.server": "Server",
+ "oc:container.rack": "Serverschrank",
+ "oc:container.tabletwrapper": "Tablet",
+ "key.opencomputers.analyzeCopyAddress": "Adresse kopieren (Messgerät)",
+ "key.opencomputers.clipboardPaste": "Zwischenablage einfügen",
+ "key.opencomputers.extendedTooltip": "Mehr Infos anzeigen",
+ "oc:tooltip.accesspoint": "Verhält sich wie ein Switch, aber empfängt zusätzlich Drahtlosnachrichten und leitet Pakete aus dem Festnetz drahtlos weiter.",
+ "oc:tooltip.abstractbuscard": "Erlaubt es, LIP-Pakete des Abstrakten Busses von §fStargateTech 2§7 zu senden und zu empfangen.",
+ "oc:tooltip.acid": "Eine hochgiftige Möchtegernflüssigkeit, wird üblicherweise nur von gewissen Piraten konsumiert. Mag sich aber auch zu anderen Zwecken eignen.",
+ "oc:tooltip.adapter": "Erlaubt es, Blöcke anzusteuern, die keine Komponentenblöcke sind, wie etwa reguläre Minecraft-Blöcke oder Blöcke anderer Mods.",
+ "oc:tooltip.alu": "Zählt Zahlen zum Zeitvertreib. Klingt komisch, is aber so.",
+ "oc:tooltip.analyzer": "Erlaubt es, Informationen über Blöcke anzuzeigen, wie zum Bleistift ihre §fAdresse§7 und ihren §fKomponentennamen§7.\nErlaubt zudem, den Fehler anzuzeigen, der zu einem Computerabsturz geführt hat, falls der Computer nicht regulär heruntergefahren wurde.",
+ "oc:tooltip.apu": "Eine CPU mit integrierter GPU (bzw. IGP), falls du unbedingt den zusätzlichen Kartenslot brauchst.\nUnterstützte Komponenten: §f%s§7\nHöchstauflösung: §f%sx%s§7\nMaximale Farbtiefe: §f%s§7\nOperationen/Tick: §f%s§7",
+ "oc:tooltip.assembler": "Erlaubt die Fertigung von Robotern und weiteren Geräten aus diversen anderen Computerteilen.",
+ "oc:tooltip.cable": "Ein billiger Weg, verschiedene Blöcke miteinander zu verbinden.",
+ "oc:tooltip.capacitor": "Speichert Energie für spätere Verwendung. Kann extrem schnell befüllt und entleert werden.",
+ "oc:tooltip.carpetedcapacitor": "Speichert Energie für den späteren Gebrauch. Kann sehr schnell befüllt und entleert werden. Lädt auf, wenn Schafe oder Ozelots darauf laufen.",
+ "oc:tooltip.cardbase": "Wie der Name schon sagt, werden alle Erweiterungskarten hieraus hergestellt.",
+ "oc:tooltip.case": "Das Computergehäuse ist der essentielle Grundbaustein für einen Computer. §fErweiterungskarten§7, §fRAM§7 und §fFestplatten§7 können in einem Gehäuse installiert werden.\nSlots: §f%s§7",
+ "oc:tooltip.chamelium": "Rohmaterial für 3D-Drucke. Nicht zum Verzehr geeignet: kann zu Erblindung und zeitweiligem Verlust von Präsenz führen.",
+ "oc:tooltip.chameliumblock": "Schick und sauber. Praktisch für gefärbte Teile in 3D-Drucken, oder einfach, um deine tolle Basis mit einem schlichten, gefärbten Block zu dekorieren.",
+ "oc:tooltip.charger": "Lädt Roboter mit Energie aus Kondensatoren auf. Die Ladegeschwindigkeit hängt vom eingehenden §fRedstonesignal§7 ab, wobei kein Signal \"nicht laden\" und ein Signal mit maximaler Stärke \"schnellstmöglich laden\" heißt. Erlaubt es auch Tablets zu laden, und ermöglicht Zugriff auf Festplatten in Tablets.",
+ "oc:tooltip.circuitboard": "Mühsam ernährt sich das Eichhörnchen. Wenn es groß wird, wird es mal eine gedruckte Leiterplatte.",
+ "oc:tooltip.controlunit": "Klingt wichtig, ist es auch. Man baut daraus immerhin CPUs. Wie könnte es da nicht wichtig sein.",
+ "oc:tooltip.componentbus": "Diese Erweiterung erlaubt es es Servern, mit noch mehr Komponenten gleichzeitig zu kommunizieren, ähnlich wie CPUs.\nUnterstützte Komponenten: §f%s§7",
+ "oc:tooltip.cpu": "Kernstück eines jeden Computers. Die Taktrate hat einen leichten Schatten, aber was kann man von einer Taschensonnenuhr schon erwarten?\nUnterstützte Komponenten: §f%s§7",
+ "oc:tooltip.cpu.Architecture": "Architektur: §f%s§7",
+ "oc:tooltip.cuttingwire": "Wird gebraucht, um Tonblöcke in Leiterplattenform zu bekommen. Vermutlich das ineffizienteste Werkzeug in der Geschichte der Menschheit, da es nach einer Verwendung kaputt geht.",
+ "oc:tooltip.datacard0": "Stellt einige komplexe Algorithmen wie Hash-Funktionen und deflate/inflate bereit.",
+ "oc:tooltip.datacard1": "Stellt einige komplexe Algorithmen wie Hash-Funktionen und deflate/inflate bereit.",
+ "oc:tooltip.datacard2": "Stellt einige komplexe Algorithmen wie Hash-Funktionen und deflate/inflate bereit.",
+ "oc:tooltip.debugcard": "Kreativ-Modus-Gegenstand, erlaubt es die Welt zu manipulieren um das Testen zu erleichtern. Verwendung auf eigene Gefahr.",
+ "oc:tooltip.debugger": "Erlaubt, Informationen über OCs internes Netzwerk auszugeben. Nur verwenden, wenn von einem Entwickler dazu aufgefordert.",
+ "oc:tooltip.diamondchip": "Ein kleines Stück eines einst wunderschönen Diamanten. Er wird niemals wieder so sein, wie er war.",
+ "oc:tooltip.disassembler": "Zerlegt Gegenstände in ihre Einzelteile. §lWarnung§7: zurückgewonnene Gegenstände haben eine %s%%-ige Chance beim Extrahieren kaputt zu gehen!",
+ "oc:tooltip.disk": "Sehr einfaches Speichermedium, das verwendet werden kann, um Disketten und Festplatten zu fertigen.",
+ "oc:tooltip.diskdrive.CC": "ComputerCraft-Disketten werden §aauch unterstützt§7.",
+ "oc:tooltip.diskdrive": "Erlaubt es, Disketten zu lesen und zu beschreiben. Kann in Robotern installiert werden, um später Disketten einlegen zu können.",
+ "oc:tooltip.diskdrivemountable": "Funktioniert genauso wie ein normales Diskettenlaufwerk, wird aber in einem Serverschrank installiert.",
+ "oc:tooltip.diskusage": "Festplattennutzung: %s/%s Byte",
+ "oc:tooltip.disklocked": "Gesperrt von %s",
+ "oc:tooltip.diskmodemanaged": "Modus: Managed",
+ "oc:tooltip.diskmodeunmanaged": "Modus: Unmanaged",
+ "oc:tooltip.drone": "Drohnen sind schlichte, flinke Aufklärungseinheiten mit limitierter Inventargröße.",
+ "oc:tooltip.dronecase": "Dieses Gehäuse wird verwendet, um Drohnen in der Elektronik-Werkbank zu bauen. Es bietet Platz für wenige Komponenten und kommt mit endsteinbetriebener Levitation.",
+ "oc:tooltip.eeprom": "Kleiner, programmierbarer Speicher für das BIOS, das Computer zum starten verwenden.",
+ "oc:tooltip.fakeendstone": "So gut wie echt, kann sogar schweben!",
+ "oc:tooltip.geolyzer": "Erlaubt es die Härte der Blöcke in der Umgebung abzufragen. Hilfreich um Hologramme der Gegend zu erzeugen, oder um Erze zu entdecken.",
+ "oc:tooltip.graphicscard": "Erlaubt es, den angezeigten Inhalt von Bildschirmen zu ändern.\nHöchstauflösung: §f%sx%s§7\nMaximale Farbtiefe: §f%s§7\nOperationen/Tick: §f%s§7",
+ "oc:tooltip.hoverboots": "Spring höher, fall tiefer, geh besser. Dies und noch mehr bekommst du mit den neuen, patentierten Schwebestiefeln (TM).",
+ "oc:tooltip.inkcartridge": "Wird verwendet, um 3D-Drucker zu befüllen. Aus mysteriösen Gründen muss die Kartusche nicht fest im Drucker eingebaut werden.",
+ "oc:tooltip.inkcartridgeempty": "Diese Kartusche wurde trocken gelegt. Fülle sie mit Farben wieder auf. Oder wirf sie weg. Mir doch egal.",
+ "oc:tooltip.internetcard": "Diese Karte erlaubt es, HTTP-Anfragen zu senden und echte TCP-Sockets zu verwenden.",
+ "oc:tooltip.interweb": "Kann in einer Internetkarte verwendet werden, um Computer mit dem rechtsfreien Raum kommunizieren zu lassen.",
+ "oc:tooltip.ironnugget": "Ein Nugget, das aus Eisen besteht, darum wird es ja auch Eisennugget genannt, duh...",
+ "oc:tooltip.keyboard": "Kann an Bildschirmen befestigt werden, um auf ihnen zu tippen.",
+ "oc:tooltip.hologram0": "Ein Volumendisplay, das beliebige, von Computern festgelegte Voxelstrukturen anzeigt.\nAuflösung: §f48x32x48§7\nMaximale Skalierung: §f3x§7\nFarbtiefe: §fMonochrom§7",
+ "oc:tooltip.hologram1": "Ein Volumendisplay, das beliebige, von Computern festgelegte Voxelstrukturen anzeigt.\nAuflösung: §f48x32x48§7\nMaximale Skalierung: §f4x§7\nFarbtiefe: §fTricolor§7",
+ "oc:tooltip.linkedcard": "Diese Karten werden paarweise hergestellt, und können ausschließlich mit ihrer jeweilgen Partnerkarte kommunizieren, dafür allerdings über beliebige Entfernungen, und sogar über Dimensionen hinweg. Der Nachteil ist der hohe Energieverbrauch beim Senden einer Nachricht.",
+ "oc:tooltip.linkedcard_channel": "§8Kanal: %s§7",
+ "oc:tooltip.manual": "Alles, was es über OpenComputers zu wissen gibt. Und mehr. Und das alles zu dem unglaublich niedrigen Preis von... §obitte R dücken, um fortzufahren§7.",
+ "oc:tooltip.materialcosts": "Halte [§f%s§7] gedrückt für Materialkosten.",
+ "oc:tooltip.materials": "Materialien:",
+ "oc:tooltip.memory": "Braucht ein jeder Computer, um zu starten. Je mehr vorhanden, desto komplexere Programme können ausgeführt werden.",
+ "oc:tooltip.microchip": "Tritt auch unter dem Alias Integrierter Schaltkreis auf. Keine Ahnung, warum das auch mit Redstone klappt, aber es funktioniert.",
+ "oc:tooltip.microcontroller": "Mikrocontroller sind möglichst einfache Computer. Sie sind dazu gedacht, für Spezialfälle verwendet zu werden, bei denen sie einfach das Programm auf dem in ihnen eingebauten EEPROM ausführen sollen.",
+ "oc:tooltip.microcontrollercase": "Dieses Gehäuse wird verwendet, um Mikrocontroller in der Elektronik-Werkbank zu bauen. Platziere es in eine solche und füge weitere Komponenten hinzu, um einen Mikrocontroller zu erstellen.",
+ "oc:tooltip.motionsensor": "Kann Bewegungen sich in der Nähe befindender Lebewesen erkennen. Benötigt eine klare Sichtlinie.",
+ "oc:tooltip.nanomachines": "Kontrolleinheit und eine Menge Nanomaschinen zur Einnahme, sofern du dich traust.",
+ "oc:tooltip.networkcard": "Erlaubt es Computern, die über mehrere Blöcke miteinander verbunden sind (z.B. Kabel), mittels Netzwerknachrichten zu kommunizieren.",
+ "oc:tooltip.poweracceptor": "Energiewandelgeschwindigkeit: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fBuildCraft MJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fFactorization Charge§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fIndustrialCraft² EU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fMekanism Joules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fThermal Expansion RF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fResonant Engine Coulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Wandelt Strom anderer Mods in den internen Energietyp um. Umwandlungsverhältnisse:",
+ "oc:tooltip.powerdistributor": "Verteilt Energie zwischen mehreren Netzwerken. Nützlich, um Energie mit einem Wandler auf mehrere Subnetze, die voneinander getrennt sein sollen, zu verteilen.",
+ "oc:tooltip.present": "... für deine Mühen. Öffne dieses Geschenk für eine Chance, §kdolle Dinge§7 zu erhalten!\n§8Fertige OpenComputers-Gegenstände zur rechten Zeit, und du hast die Chance ein Geschenk zu erhalten.§7",
+ "oc:tooltip.print.BeaconBase": "§8Funktioniert als Grundstein für ein Leuchtfeuer.",
+ "oc:tooltip.print.LightValue": "§8Leuchtkraft: %s.",
+ "oc:tooltip.print.RedstoneLevel": "§8Redstone-Signalstärke: %s.",
+ "oc:tooltip.printedcircuitboard": "Hierauf basieren alle Erweiterungskarten, Speicher und so weiter.",
+ "oc:tooltip.printer": "Erlaubt es, Blöcke aus benutzerdefinierten Formen zu drucken. Verwendet Chamälium und Tintenkartuschen. Muss über einen Computer konfiguriert werden. Von Kindern fern halten. Weil halt.",
+ "oc:tooltip.raid": "Erlaubt es, drei Festplatten zu einem größeren Dateisystem zusammenzuschließen, welches von allen verbundenen Computern genutzt werden kann.",
+ "oc:tooltip.rawcircuitboard": "Kann in einer Ofen-kompatiblen Schmelze freier Wahl gehärtet werden.",
+ "oc:tooltip.redstone": "Erlaubt das Lesen und Ausgeben von Redstonesignalen um den Block herum. Kann von jedem Computer, der mit dem Block verbunden ist, gesteuert werden. Dieser Block ist quasi wie eine externe Redstonekarte.",
+ "oc:tooltip.redstonecard.ProjectRed": "§fProjectRed§7 wird §aunterstützt§7.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 wird §aunterstützt§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 wird §aunterstützt§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "§fWireless Redstone (ChickenBones)§7 wird §aunterstützt§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "§fWireless Redstone (SlimeVoid)§7 wird §aunterstützt§7.",
+ "oc:tooltip.redstonecard": "Erlaubt das Lesen und Ausgeben von Redstonesignalen um den Computer oder Roboter herum.",
+ "oc:tooltip.relay": "Erlaubt es, mehrere Netzwerke miteinander zu verbinden. Leitet ausschließlich Netzwerknachrichten weiter, Komponenten \"hinter\" dem Switch sind nicht sichtbar. Nützlich, um Netzwerke zu trennen, jedoch nach wie vor Kommunikation zwischen den Netzwerken zu erlauben, z.b. mittels Netzwerkkarten.",
+ "oc:tooltip.robot": "Im Gegensatz zu normalen Computern können sich Roboter in der Welt bewegen und ähnlich wie Spieler mit der Welt interagieren. Sie können jedoch §onicht§r§7 mit externen Komponenten interagieren!",
+ "oc:tooltip.robot_level": "§fStufe§7: §a%s§7.",
+ "oc:tooltip.robot_storedenergy": "§fGespeicherte Energie§7: §a%s§7.",
+ "oc:tooltip.screen": "Zeigt Text an, gesteuert von Grafikkarten in Computern.\nHöchstauflösung: §f%sx%s§7\nMaximale Farbtiefe: §f%s§7",
+ "oc:tooltip.server": "Ein Server kann wie ein gewöhnliches Computergehäuse mit Komponenten verbessert werden. Um den Server zu starten, muss er in einem Servergehäuse installiert werden.",
+ "oc:tooltip.server.Components": "Installierte Komponenten:",
+ "oc:tooltip.rack": "Erlaubt die Installation von bis zu vier Servern oder anderen Serverschrankkomponenten.",
+ "oc:tooltip.switch": "Erlaubt es, mehrere Netzwerke miteinander zu verbinden. Leitet ausschließlich Netzwerknachrichten weiter, Komponenten \"hinter\" dem Switch sind nicht sichtbar. Nützlich, um Netzwerke zu trennen, jedoch nach wie vor Kommunikation zwischen den Netzwerken zu erlauben, z.B. mittels Netzwerkkarten.",
+ "oc:tooltip.tablet": "Ein Tablet-PC, für Lua unterwegs. Kann durch Sneak-Aktivierung zwangsgestoppt werden.",
+ "oc:tooltip.tabletcase": "Einfaches Gehäuse für Tablet-PCs. Kann in der Elektronik-Werkbank mit Komponenten bestückt werden, um einen Tablet-PC zu fertigen.",
+ "oc:tooltip.terminal": "Erlaubt es, einen Server aus der Ferne zu steuern, so lange man sich in Reichweite des Servers befindet. Verhält sich wie Bildschirm und Tastatur in einem. Kann mit Shift-Rechtsklick an einen Server in einem Serverschrank gebunden werden.",
+ "oc:tooltip.terminalserver": "Das Rückgrat für Fernzugriff. Fernbedienungen können hiermit verbunden werden. Enthält virtuelle Tastatur und Bildschirm.",
+ "oc:tooltip.texturepicker": "Dieses Werkzeug erlaubt es, eine Zeichenkette anzuzeigen, die die Oberfläche eines Blocks beschreibt und in Form-Definitionen für 3D-Drucker verwendet werden kann. Definiv keine Texturnamen, oh nein. Nix da.",
+ "oc:tooltip.tier": "§8Stufe %s",
+ "oc:tooltip.netsplitter": "Kann Netzwerke dynamisch verbinden. Die Konnektivität jeder Seite kann umgeschaltet werden, in dem man \"Professionelle Wartungsarbeiten\" mit einem Schraubenschlüssel durchführt. Sie kann auch mit einem Redstone-Signal an entsprechenden Seiten invertiert werden.",
+ "oc:tooltip.toolong": "Halte [§f%s§7] gedrückt für mehr Infos.",
+ "oc:tooltip.transistor": "Elementarer Baustein der meisten Computerkomponenten. Nicht zu verwechseln mit Steinelementaren.",
+ "oc:tooltip.transposer": "Ermöglicht automatischen Transfer von Items und Flüssigkeiten zwischen angrenzenden Blöcken.",
+ "oc:tooltip.upgradeangel": "Erlaubt es Robotern, Blöcke in die Luft zu setzen, selbst wenn kein Referenzblock daneben existiert.",
+ "oc:tooltip.upgradebattery": "Erhöht die Energiespeicherkapazität eines Roboters, was ihm erlaubt, länger zu arbeiten, ohne erneut aufgeladen werden zu müssen.\nKapazität: §f%s§7",
+ "oc:tooltip.upgradechunkloader": "Wenn sich im Wald ein Roboter bewegt, und niemand da ist, ihn zu sehen, bewegt er sich dann wirklich? Dieses Upgrade stellt sicher, dass dem so ist. Es hält den Chunk, in dem sich der Roboter befindet, geladen, verbraucht jedoch Energie, während es aktiv ist.",
+ "oc:tooltip.upgradecontainercard": "Dieses Behälter-Upgrade erlaubt es, eine Karte in einem bereits zusammengebauten Roboter zu installieren und wieder zu entfernen.\nMaximale Stufe: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "Dieses Behälter-Upgrade erlaubt es, ein Upgrade in einem bereits zusammengebauten Roboter zu installieren und wieder zu entfernen.\nMaximale Stufe: §f%s§7",
+ "oc:tooltip.upgradecrafting": "Ermöglicht Robotern, in dem oberen linken Bereich ihres Inventars Dinge zu fertigen. Gegenstände müssen so angeordnet sein, wie sie es in einer Werkbank wären.",
+ "oc:tooltip.upgradedatabase": "Diese Upgrade erlaubt es, Gegenstandsinformationen - für spätere Verwendung in anderen Komponenten - zu speichern.\nMaximale Einträge: §f%s§7",
+ "oc:tooltip.upgradeexperience": "Dieses Upgrade erlaubt es Robotern, durch verschiedene Aktionen Erfahrung zu sammeln. Je mehr Erfahrung ein Roboter hat, desto mehr Energie kann er speichern, desto schneller kann er Blöcke abbauen und desto effizienter kann er mit Werkzeugen umgehen.",
+ "oc:tooltip.upgradegenerator": "Kann verwendet werden, um unterwegs Energie aus Brennstoffen zu erzeugen. Verbraucht Gegenstände über einen ihrem Brennwert gemäßen Zeitraum.\n§fEffizienz§7: §a%s%%§7",
+ "oc:tooltip.upgradehover": "Erlaubt Robotern höher zu fliegen, ohne an Wänden klettern zu müssen.\nMaximalhöhe: §f%s§7",
+ "oc:tooltip.upgradeinventory": "Dieses Upgrade gibt Robotern ein internes Inventar. Ohne ein solches Upgrade können Roboter keine Gegenstände verwahren.",
+ "oc:tooltip.upgradeinventorycontroller": "Dieses Upgrade erlaubt es dem Roboter, präziser mit externen Inventaren zu interagieren, und erlaubt es ihm, das angelegte Werkzeug mit einem Gegenstand in seinem Inventar auszutauschen.",
+ "oc:tooltip.upgrademf": "Erlaubt es Adaptern, mit Blöcken zu interagieren, die etwas weiter weg sind.",
+ "oc:tooltip.upgrademf.Linked": "§fVerbindung hergestellt§7",
+ "oc:tooltip.upgrademf.Unlinked": "§fKeine Verbindung§7",
+ "oc:tooltip.upgradeleash": "Erlaubt es manchen Geräten, wie etwa Drohnen, B- *getuschel* Verzeihung. Mir wurde soeben zugetragen, dass es tatsächlich dazu verwendet werden kann, Tiere an die Leine zu legen. Sogar viele Viecher.",
+ "oc:tooltip.upgradenavigation": "Erlaubt es Robotern, ihre Position und Ausrichtung zu bestimmen. Die Position ist relativ zur Mitte der Karte, die in diesem Upgrade verbaut wurde.",
+ "oc:tooltip.upgradepiston": "Dieses Upgrade ist sehr drückend. Es macht es möglich Blöcke zu verschieben, ähnlich dem Kolben. Es kann jedoch §lkeine§7 Entities bewegen.",
+ "oc:tooltip.upgradesign": "Erlaubt das Lesen und Schreiben von Text auf Schildern.",
+ "oc:tooltip.upgradesolargenerator": "Kann verwendet werden, um unterwegs Energie aus Sonnenlicht zu generieren. Benötigt eine ungehinderte Sicht zum Himmel über dem Roboter. Generiert Energie mit %s%% der Geschwindigkeit eines Stirlingmotors.",
+ "oc:tooltip.upgradetank": "Dieses Upgrade gibt Robotern einen internen Tank. Ohne ein solches Upgrade können Roboter keine Flüssigkeiten verwahren.",
+ "oc:tooltip.upgradetankcontroller": "Dieses Upgrade erlaubt es dem Roboter, präziser mit externen Tanks zu interagieren, und erlaubt es ihm, Flüssigkeiten in und aus sich im Inventar befindlichen Tank-Gegenständen zu pumpen.",
+ "oc:tooltip.upgradetractorbeam": "Stattet den Roboter mit unglaublich fortschrittlicher Technologie - Kosename: \"Gegenstandsmagnet\" - aus. Erlaubt es dem Roboter, Gegenstände, innerhalb von 3 Blöcken um sich herum, einzusammeln.",
+ "oc:tooltip.waypoint": "Ein Orientierungpunkt für Geräte mit einem Navigations-Upgrade.",
+ "oc:tooltip.wirelessnetworkcard": "Erlaubt das drahtlose Senden von Netzwerknachrichten, zusätzlich zu normalen. Drahtlose Nachrichten werden nur gesendet, wenn eine §fSignalstärke§7 festgelegt wurde!",
+ "oc:tooltip.worldsensorcard": "Erlaubt es, Informationen über die Welt auszulesen, wie etwa Gravitation und ob die Atmosphäre atembar ist. Verwendung von Messergebnissen auf eigene Gefahr. Der Hersteller übernimmt keinerlei Garantie.",
+ "oc:tooltip.wrench": "Eine Mischung aus Schraubenzieher und Schraubenschlüssel, einfach zu benutzen, aber schwer zu meistern.",
+ "achievement.oc.adapter": "Steck mich ein",
+ "achievement.oc.adapter.desc": "Interagiert mit Blöcken aus anderen Mods, und sogar Vanilla-Minecraft!",
+ "achievement.oc.assembler": "Wundervoll",
+ "achievement.oc.assembler.desc": "Zeit, die Welt zu erobern!",
+ "achievement.oc.cable": "Kein gewöhnliches Kabel",
+ "achievement.oc.cable.desc": "Mit patentierter Anti-Kabelsalat-Technologie.",
+ "achievement.oc.capacitor": "Batterien enthalten",
+ "achievement.oc.capacitor.desc": "Achtung: Kurzschlussgefahr.",
+ "achievement.oc.card": "Wir akzeptieren Karten",
+ "achievement.oc.card.desc": "Dreimal falsche PIN-Eingabe. Karte wird einbehalten.",
+ "achievement.oc.case": "Desktop-Computer",
+ "achievement.oc.case.desc": "Desktop (und Betriebssystem) separat erhältlich.",
+ "achievement.oc.charger": "Die Spannung steigt",
+ "achievement.oc.charger.desc": "Und auflad- verdammt, schon wieder das Redstone-Signal vergessen.",
+ "achievement.oc.chip": "Technischer Fortschritt",
+ "achievement.oc.chip.desc": "Besser als Elekrtonenröhren.",
+ "achievement.oc.cpu": "Übertaktet",
+ "achievement.oc.cpu.desc": "Endlich ein Nutzen für die ungenutzten Prozessorzyklen.",
+ "achievement.oc.disassembler": "Nochmal von vorn",
+ "achievement.oc.disassembler.desc": "Falls deine brillianten Ideen am Ende doch nicht so brilliant sind.",
+ "achievement.oc.diskDrive": "*klick brumm brumm brumm ratter*",
+ "achievement.oc.diskDrive.desc": "Weniger Speicherplatz, aber welch ein wundervolles Geräusch.",
+ "achievement.oc.drone": "Startbereit",
+ "achievement.oc.drone.desc": "Keep calm and nuke it from orbit.",
+ "achievement.oc.eeprom": "Es kann nur einen geben",
+ "achievement.oc.eeprom.desc": "Pro Computer, genau genommen. Für eine deterministische Boot-Reihenfolge, weißt du?",
+ "achievement.oc.floppy": "Der Eine Ri- Datenspeicher",
+ "achievement.oc.floppy.desc": "Nicht zu verwechseln mit Flappy.",
+ "achievement.oc.geolyzer": "Gezielte Rohstoffsuche",
+ "achievement.oc.geolyzer.desc": "Umweltfreundlicher als Fracking, versprochen.",
+ "achievement.oc.graphicsCard": "LastGen",
+ "achievement.oc.graphicsCard.desc": "The way it's meant to be... äh... rendered. Ja. So ungefähr.",
+ "achievement.oc.hdd": "Hotdog-Dealer",
+ "achievement.oc.hdd.desc": "Moment, das stimmt nicht ganz. Warte, gleich hab' ich's...",
+ "achievement.oc.hologram": "Eine höhere Dimension",
+ "achievement.oc.hologram.desc": "Weil 2D so langweilig ist. Oder ist es das wirklich?",
+ "achievement.oc.keyboard": "SchmutzFänger3000",
+ "achievement.oc.keyboard.desc": "Es wird davon abgeraten, sie umzudrehen und zu schütteln, auch wenn es noch so verlockend ist.",
+ "achievement.oc.microcontroller": "Kleine Schwester",
+ "achievement.oc.microcontroller.desc": "Das kleine Geschwisterkind des Computers.",
+ "achievement.oc.motionSensor": "Got the Moves",
+ "achievement.oc.motionSensor.desc": "Like Steve Swagger.",
+ "achievement.oc.networkCard": "Fernleitung",
+ "achievement.oc.networkCard.desc": "Perfekt um diese transitiven Beziehungen aufrecht zu erhalten.",
+ "achievement.oc.openOS": "Boot",
+ "achievement.oc.openOS.desc": "Das Eine Betrieb- wie, was meinst du, der Witz wird alt?",
+ "achievement.oc.powerDistributor": "Strom-Sharing",
+ "achievement.oc.powerDistributor.desc": "ElektroVZ ist so 2010.",
+ "achievement.oc.rack": "Multifunktionsschrank",
+ "achievement.oc.rack.desc": "Wird unter Anderem in Kantinen genutzt, um gebrauchte Tabletts zu sammeln.",
+ "achievement.oc.raid": "Suche Team",
+ "achievement.oc.raid.desc": "Heroic plzkthx.",
+ "achievement.oc.ram": "Random Access Memories",
+ "achievement.oc.ram.desc": "Congratulations, you're Doin' It Right.",
+ "achievement.oc.redstoneCard": "Kontakt",
+ "achievement.oc.redstoneCard.desc": "Zeit für analoge Signale.",
+ "achievement.oc.redstoneIO": "Außenseiter",
+ "achievement.oc.redstoneIO.desc": "Redstone-Signale, dort wo du sie brauchst.",
+ "achievement.oc.robot": "Beep Boop",
+ "achievement.oc.robot.desc": "VERNICHTEN!",
+ "achievement.oc.screen": "Hast du schon versucht, ihn aus- und wieder anzuschalten?",
+ "achievement.oc.screen.desc": "Nein, ernsthaft. Ein Redstone-Impuls kann wirklich einen Bildschirm an- und ausschalten.",
+ "achievement.oc.server": "Dediziert",
+ "achievement.oc.server.desc": "Hier kommen die Cloud-Dienste.",
+ "achievement.oc.switch": "Paketdienst",
+ "achievement.oc.switch.desc": "Nicht für Hinkelsteine verwenden, die könnten sonst beim Aussortieren verloren gehen.",
+ "achievement.oc.tablet": "Verschluckbare Kleinteile",
+ "achievement.oc.tablet.desc": "Von Kindern fernhalten, um unerwünschte Kreditkartenbelastungen zu vermeiden.",
+ "achievement.oc.transistor": "Schöne Grüße an Red!",
+ "achievement.oc.transistor.desc": "Jetzt kannst du dir den Soundtrack anhören.",
+ "achievement.oc.wirelessNetworkCard": "Das WLAN - Unendliche Weiten",
+ "achievement.oc.wirelessNetworkCard.desc": "Netzwerke, die nie ein Paket zuvor gesehen hat.",
+ "death.attack.oc.nanomachinesOverload.1": "%s ist zu gierig geworden.",
+ "death.attack.oc.nanomachinesOverload.2": "%s erlitt einen Nervenzusammenbruch.",
+ "death.attack.oc.nanomachinesOverload.3": "Die Nanomaschinen von %s gerieten wohl außer Kontrolle. Ups.",
+ "death.attack.oc.nanomachinesHungry.1": "%s wurde von Nanomaschinen verspeist.",
+ "death.attack.oc.nanomachinesHungry.2": "%s hat wohl seine Nanomaschinen nicht gefüttert.",
+ "death.attack.oc.nanomachinesHungry.3": "%s wurde verdaut.",
+ "nei.options.inventory.oredict": "OreDictionary-Namen anzeigen",
+ "nei.options.inventory.oredict.true": "True",
+ "nei.options.inventory.oredict.false": "False",
+ "nei.usage.oc.Manual": "Handbuch öffnen",
+ "option.oc.address": "Adresse",
+ "option.oc.componentName": "Komponentenname",
+ "option.oc.energy": "Energie"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang
deleted file mode 100644
index 67527659fa..0000000000
--- a/src/main/resources/assets/opencomputers/lang/en_US.lang
+++ /dev/null
@@ -1,484 +0,0 @@
-# This is the english master file for localizations. It will always be the most
-# up-to-date version, so other localizations should be based on this one.
-# Use [nl] to for a line break.
-
-# Blocks
-tile.oc.adapter.name=Adapter
-tile.oc.assembler.name=Electronics Assembler
-tile.oc.cable.name=Cable
-tile.oc.capacitor.name=Capacitor
-tile.oc.carpetedcapacitor.name=Carpeted Capacitor
-tile.oc.case1.name=Computer Case (Tier 1)
-tile.oc.case2.name=Computer Case (Tier 2)
-tile.oc.case3.name=Computer Case (Tier 3)
-tile.oc.casecreative.name=Computer Case (Creative)
-tile.oc.chameliumblock.name=Block of Chamelium
-tile.oc.charger.name=Charger
-tile.oc.disassembler.name=Disassembler
-tile.oc.diskdrive.name=Disk Drive
-tile.oc.endstone.name=End Stone
-tile.oc.geolyzer.name=Geolyzer
-tile.oc.hologram1.name=Hologram Projector (Tier 1)
-tile.oc.hologram2.name=Hologram Projector (Tier 2)
-tile.oc.keyboard.name=Keyboard
-tile.oc.microcontroller.name=Microcontroller
-tile.oc.motionsensor.name=Motion Sensor
-tile.oc.netsplitter.name=Net Splitter
-tile.oc.powerconverter.name=Power Converter
-tile.oc.powerdistributor.name=Power Distributor
-tile.oc.print.name=3D Print
-tile.oc.printer.name=3D Printer
-tile.oc.raid.name=Raid
-tile.oc.redstone.name=Redstone I/O
-tile.oc.relay.name=Relay
-tile.oc.robot.name=Robot
-tile.oc.robotafterimage.name=Robot
-tile.oc.screen1.name=Screen (Tier 1)
-tile.oc.screen2.name=Screen (Tier 2)
-tile.oc.screen3.name=Screen (Tier 3)
-tile.oc.rack.name=Rack
-tile.oc.transposer.name=Transposer
-tile.oc.waypoint.name=Waypoint
-
-# Items
-item.oc.abstractbuscard.name=Abstract Bus Card
-item.oc.acid.name=Grog
-item.oc.alu.name=Arithmetic Logic Unit (ALU)
-item.oc.analyzer.name=Analyzer
-item.oc.apu0.name=Accelerated Processing Unit (APU) (Tier 2)
-item.oc.apu1.name=Accelerated Processing Unit (APU) (Tier 3)
-item.oc.apu2.name=Accelerated Processing Unit (APU) (Creative)
-item.oc.arrowkeys.name=Arrow Keys
-item.oc.buttongroup.name=Button Group
-item.oc.cardbase.name=Card Base
-item.oc.chamelium.name=Chamelium
-item.oc.circuitboard.name=Circuit Board
-item.oc.componentbus0.name=Component Bus (Tier 1)
-item.oc.componentbus1.name=Component Bus (Tier 2)
-item.oc.componentbus2.name=Component Bus (Tier 3)
-item.oc.componentbus3.name=Component Bus (Creative)
-item.oc.controlunit.name=Control Unit (CU)
-item.oc.cpu0.name=Central Processing Unit (CPU) (Tier 1)
-item.oc.cpu1.name=Central Processing Unit (CPU) (Tier 2)
-item.oc.cpu2.name=Central Processing Unit (CPU) (Tier 3)
-item.oc.cuttingwire.name=Cutting Wire
-item.oc.datacard0.name=Data Card (Tier 1)
-item.oc.datacard1.name=Data Card (Tier 2)
-item.oc.datacard2.name=Data Card (Tier 3)
-item.oc.debugcard.name=Debug Card
-item.oc.debugger.name=Network Debugger
-item.oc.diamondchip.name=Diamond Chip
-item.oc.disk.name=Disk Platter
-item.oc.diskdrivemountable.name=Disk Drive
-item.oc.drone.name=Drone
-item.oc.dronecase0.name=Drone Case (Tier 1)
-item.oc.dronecase1.name=Drone Case (Tier 2)
-item.oc.dronecase3.name=Drone Case (Creative)
-item.oc.eeprom.name=EEPROM
-item.oc.floppydisk.name=Floppy Disk
-item.oc.graphicscard0.name=Graphics Card (Tier 1)
-item.oc.graphicscard1.name=Graphics Card (Tier 2)
-item.oc.graphicscard2.name=Graphics Card (Tier 3)
-item.oc.harddiskdrive0.name=Hard Disk Drive (Tier 1)
-item.oc.harddiskdrive1.name=Hard Disk Drive (Tier 2)
-item.oc.harddiskdrive2.name=Hard Disk Drive (Tier 3)
-item.oc.hoverboots.name=Hover Boots
-item.oc.inkcartridge.name=Ink Cartridge
-item.oc.inkcartridgeempty.name=Ink Cartridge (Empty)
-item.oc.internetcard.name=Internet Card
-item.oc.interweb.name=Interweb
-item.oc.ironnugget.name=Iron Nugget
-item.oc.linkedcard.name=Linked Card
-item.oc.manual.name=OpenComputers Manual
-item.oc.memory0.name=Memory (Tier 1)
-item.oc.memory1.name=Memory (Tier 1.5)
-item.oc.memory2.name=Memory (Tier 2)
-item.oc.memory3.name=Memory (Tier 2.5)
-item.oc.memory4.name=Memory (Tier 3)
-item.oc.memory5.name=Memory (Tier 3.5)
-item.oc.microchip0.name=Microchip (Tier 1)
-item.oc.microchip1.name=Microchip (Tier 2)
-item.oc.microchip2.name=Microchip (Tier 3)
-item.oc.microcontrollercase0.name=Microcontroller Case (Tier 1)
-item.oc.microcontrollercase1.name=Microcontroller Case (Tier 2)
-item.oc.microcontrollercase3.name=Microcontroller Case (Creative)
-item.oc.nanomachines.name=Nanomachines
-item.oc.networkcard.name=Network Card
-item.oc.numpad.name=Numeric Keypad
-item.oc.present.name=A little something...
-item.oc.printedcircuitboard.name=Printed Circuit Board (PCB)
-item.oc.rawcircuitboard.name=Raw Circuit Board
-item.oc.redstonecard0.name=Redstone Card (Tier 1)
-item.oc.redstonecard1.name=Redstone Card (Tier 2)
-item.oc.server0.name=Server (Tier 1)
-item.oc.server1.name=Server (Tier 2)
-item.oc.server2.name=Server (Tier 3)
-item.oc.server3.name=Server (Creative)
-item.oc.tablet.name=Tablet
-item.oc.tabletcase0.name=Tablet Case (Tier 1)
-item.oc.tabletcase1.name=Tablet Case (Tier 2)
-item.oc.tabletcase3.name=Tablet Case (Creative)
-item.oc.terminal.name=Remote Terminal
-item.oc.terminalserver.name=Terminal Server
-item.oc.texturepicker.name=Texture Picker
-item.oc.transistor.name=Transistor
-item.oc.upgradeangel.name=Angel Upgrade
-item.oc.upgradebattery0.name=Battery Upgrade (Tier 1)
-item.oc.upgradebattery1.name=Battery Upgrade (Tier 2)
-item.oc.upgradebattery2.name=Battery Upgrade (Tier 3)
-item.oc.upgradechunkloader.name=Chunkloader Upgrade
-item.oc.upgradecontainercard0.name=Card Container (Tier 1)
-item.oc.upgradecontainercard1.name=Card Container (Tier 2)
-item.oc.upgradecontainercard2.name=Card Container (Tier 3)
-item.oc.upgradecontainerupgrade0.name=Upgrade Container (Tier 1)
-item.oc.upgradecontainerupgrade1.name=Upgrade Container (Tier 2)
-item.oc.upgradecontainerupgrade2.name=Upgrade Container (Tier 3)
-item.oc.upgradecrafting.name=Crafting Upgrade
-item.oc.upgradedatabase0.name=Database Upgrade (Tier 1)
-item.oc.upgradedatabase1.name=Database Upgrade (Tier 2)
-item.oc.upgradedatabase2.name=Database Upgrade (Tier 3)
-item.oc.upgradeexperience.name=Experience Upgrade
-item.oc.upgradegenerator.name=Generator Upgrade
-item.oc.upgradehover0.name=Hover Upgrade (Tier 1)
-item.oc.upgradehover1.name=Hover Upgrade (Tier 2)
-item.oc.upgradeinventory.name=Inventory Upgrade
-item.oc.upgradeinventorycontroller.name=Inventory Controller Upgrade
-item.oc.upgradeleash.name=Leash Upgrade
-item.oc.upgrademf.name=MFU
-item.oc.upgradenavigation.name=Navigation Upgrade
-item.oc.upgradepiston.name=Piston Upgrade
-item.oc.upgradestickypiston.name=Sticky Piston Upgrade
-item.oc.upgradesign.name=Sign I/O Upgrade
-item.oc.upgradesolargenerator.name=Solar Generator Upgrade
-item.oc.upgradetank.name=Tank Upgrade
-item.oc.upgradetankcontroller.name=Tank Controller Upgrade
-item.oc.upgradetractorbeam.name=Tractor Beam Upgrade
-item.oc.upgradetrading.name=Trading Upgrade
-item.oc.wirelessnetworkcard0.name=Wireless Network Card (Tier 1)
-item.oc.wirelessnetworkcard1.name=Wireless Network Card (Tier 2)
-item.oc.worldsensorcard.name=World Sensor Card
-item.oc.wrench.name=Scrench
-
-# Entities
-entity.oc.Drone.name=Drone
-
-# GUI
-oc:gui.Analyzer.Address=§6Address§f: %s
-oc:gui.Analyzer.AddressCopied=Address copied to clipboard.
-oc:gui.Analyzer.ChargerSpeed=§6Charge speed§f: %s
-oc:gui.Analyzer.ComponentName=§6Component name§f: %s
-oc:gui.Analyzer.Components=§6Number of connected components§f: %s
-oc:gui.Analyzer.CopyToClipboard=Click to copy to clipboard.
-oc:gui.Analyzer.LastError=§6Last error§f: %s
-oc:gui.Analyzer.RobotName=§6Name§f: %s
-oc:gui.Analyzer.RobotOwner=§6Owner§f: %s
-oc:gui.Analyzer.RobotXp=§6Experience§f: %s (Level %s)
-oc:gui.Analyzer.StoredEnergy=§6Stored energy§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Total stored energy§f: %s
-oc:gui.Analyzer.Users=§6Users§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Signal strength§f: %s
-oc:gui.Assembler.Collect=Collect output
-oc:gui.Assembler.Complexity=Complexity: %s/%s
-oc:gui.Assembler.InsertCase=Insert a base part
-oc:gui.Assembler.InsertCPU=Insert a CPU
-oc:gui.Assembler.InsertRAM=Insert some RAM
-oc:gui.Assembler.Progress=Progress: %s%% (%s)
-oc:gui.Assembler.Run=Assemble
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=Graphics Card
-oc:gui.Assembler.Warning.Inventory=Inventory Upgrade
-oc:gui.Assembler.Warning.Keyboard=Keyboard
-oc:gui.Assembler.Warning.OS=Bootable Medium
-oc:gui.Assembler.Warning.Screen=Screen
-oc:gui.Assembler.Warnings=§eWarning§7: Recommended components are missing.
-oc:gui.Chat.NewVersion=A new version is available: %s
-oc:gui.Chat.TextureName=§7Texture name is §a%s§f.
-oc:gui.Chat.WarningClassTransformer=There were §cerrors§f running the class transformer. Please report this, together with your (full!) FML §alatest.log§f/§afml-server-latest.log§f logfile, thank you!
-oc:gui.Chat.WarningFingerprint=§cWARNING§f - fingerprint mismatch! Expected '§a%s§f' but got '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.
-oc:gui.Chat.WarningLink=Could not open link: %s
-oc:gui.Chat.WarningLuaFallback=Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads.
-oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.
-oc:gui.Chat.WarningRecipes=There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.
-oc:gui.Chat.WarningSimpleComponent=An addon (yours?) using the §aSimpleComponent§f interface did §esomething wrong§f. Component logic could not be injected. Please check your log file for more information.
-oc:gui.Drive.Managed=Managed
-oc:gui.Drive.Unmanaged=Unmanaged
-oc:gui.Drive.ReadOnlyLock=Lock
-oc:gui.Drive.ReadOnlyLockWarning=§lRead Only§r lock. Cannot be removed unless the drive is wiped.
-oc:gui.Drive.Warning=§lWarning§r: switching modes will result in a loss of all data currently stored on the disk!
-oc:gui.Error.ComponentOverflow=Too many components connected to the computer.
-oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug.
-oc:gui.Error.NoCPU=No CPU is installed in the computer.
-oc:gui.Error.NoEnergy=Not enough energy.
-oc:gui.Error.NoRAM=No RAM is installed in the computer.
-oc:gui.Error.OutOfMemory=Out of memory.
-oc:gui.Manual.Blocks=OpenComputers Blocks
-oc:gui.Manual.Home=Home
-oc:gui.Manual.Items=OpenComputers Items
-oc:gui.Manual.Warning.BlockMissing=Block unavailable.
-oc:gui.Manual.Warning.ImageMissing=Image not found.
-oc:gui.Manual.Warning.ItemMissing=Item unavailable.
-oc:gui.Manual.Warning.OreDictMissing=Ore dictionary entry unavailable.
-oc:gui.Raid.Warning=§4Adding a disk wipes it.[nl] Removing a disk wipes the raid.
-oc:gui.Robot.Power=Energy
-oc:gui.Robot.TurnOff=Turn off
-oc:gui.Robot.TurnOn=Turn on[nl]§7Use an Analyzer to troubleshoot errors.§r
-oc:gui.Rack.Back=Back
-oc:gui.Rack.Bottom=Bottom
-oc:gui.Rack.Left=Left
-oc:gui.Rack.None=None
-oc:gui.Rack.Right=Right
-oc:gui.Rack.Enabled=Enabled
-oc:gui.Rack.Disabled=Disabled
-oc:gui.Rack.RelayModeTooltip=Relay Mode
-oc:gui.Rack.Top=Top
-oc:gui.Switch.PacketsPerCycle=Packets / cycle
-oc:gui.Switch.QueueSize=Queue size
-oc:gui.Switch.TransferRate=Cycle rate
-oc:gui.Terminal.InvalidKey=Invalid key, most likely another terminal has been bound to the server.
-oc:gui.Terminal.OutOfRange=No signal.
-
-# Containers
-oc:container.adapter=Adapter
-oc:container.case=Computer
-oc:container.charger=Charger
-oc:container.disassembler=Disassembler
-oc:container.diskdrive=Disk Drive
-oc:container.printer=Printer
-oc:container.raid=Raid
-oc:container.relay=Relay
-oc:container.server=Server
-oc:container.rack=Rack
-oc:container.tabletwrapper=Tablet
-
-# Keybinds
-key.clipboardPaste=Paste Clipboard
-
-# Item / Block Tooltips
-oc:tooltip.abstractbuscard=Allows interacting with §fStargateTech 2§7's abstract bus by sending and receiving LIP packets.
-oc:tooltip.acid=A highly toxic pseudo-liquid, usually only consumed by certain pirates. May prove to be useful in other ways, too, however.
-oc:tooltip.adapter=Used to control non-component blocks, such as vanilla blocks or blocks from other mods.
-oc:tooltip.alu=Adds numbers so you don't have to. It might be better this way.
-oc:tooltip.analyzer=Used to display information about blocks, such as their §faddress§7 and §fcomponent name§7.[nl] Also displays the error that caused a computer to crash if it did not shut down normally.
-oc:tooltip.apu=This is a CPU with an integrated GPU (or IGP), when you just need that extra card slot.[nl] Supported components: §f%s§7[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7[nl] Operations/tick: §f%s§7
-oc:tooltip.assembler=Allows constructing robots and other devices from a number of different computer parts.
-oc:tooltip.cable=A cheap way of connecting blocks.
-oc:tooltip.capacitor=Stores energy for later use. Can be filled and emptied very quickly.
-oc:tooltip.carpetedcapacitor=Stores energy for later use. Can be filled and emptied very quickly. Charges when Sheep or Ocelots walk on it
-oc:tooltip.cardbase=As the name indicates, this is the basic building block for all expansion cards.
-oc:tooltip.case=The Computer Case is the basic building block for computers and houses the computer's §fextension cards§7, §fRAM§7 and §fhard disks§7.[nl] Slots: §f%s§7
-oc:tooltip.chamelium=Raw material for 3D prints. Do not swallow: may lead to blindness and temporary lack of presence.
-oc:tooltip.chameliumblock=Nice and clean. Handy for tinted shapes in 3D prints, or just for having a clean, colored block to decorate your fancy base with.
-oc:tooltip.charger=Transfers energy from capacitors into adjacent robots and drones. The transfer rate depends on the incoming §fredstone signal§7, where no signal means don't charge devices, and maximum strength means charge at full speed. Can also be used to charge tablets and access hard drives in tablets.
-oc:tooltip.circuitboard=Now we're getting somewhere. Can be etched to obtain a printed circuit board.
-oc:tooltip.controlunit=This is the unit that... controls... stuff. You need it to build a CPU. So yeah, totally important.
-oc:tooltip.componentbus=This expansion allows servers to communicate with more components at the same time, similar to how CPUs do.[nl] Supported components: §f%s§7
-oc:tooltip.cpu=An essential component of all computers. The clock rate is a bit unreliable, but what do you expect when it runs on a pocket sundial?[nl] Supported components: §f%s§7
-oc:tooltip.cpu.Architecture=Architecture: §f%s§7
-oc:tooltip.cuttingwire=Used to cut clay blocks into circuit board shape. Breaks after one use, which probably makes it the most inefficient tool ever.
-oc:tooltip.datacard0=Provides a couple of advanced algorithms such as hashing and deflate/inflate.
-oc:tooltip.datacard1=Provides a couple of advanced algorithms such as hashing, AES encryption and deflate/inflate.
-oc:tooltip.datacard2=Provides a couple of advanced algorithms such as hashing, AES encryption, elliptic curve cryptography and deflate/inflate.
-oc:tooltip.debugcard=Creative mode item, allows manipulating the world to make testing easier. Use at your own peril.
-oc:tooltip.debugger=Can be used to output debug information on OC's internal network grid. Only use if so instructed by a dev.
-oc:tooltip.diamondchip=A small piece of a once radiant diamond. It will never be the same again.
-oc:tooltip.disassembler=Separates items into their original components. §lWarning§7: returned items have a %s%% chance of breaking in the process!
-oc:tooltip.disk=Primitive medium that can be used to build persistent storage devices.
-oc:tooltip.diskdrive.CC=ComputerCraft floppies are §asupported§7.
-oc:tooltip.diskdrive=Allows reading and writing floppies. Can be installed in robots to allow inserting floppies later on.
-oc:tooltip.diskdrivemountable=Provides the same functionality as a normal disk drive, but must be installed in a rack.
-oc:tooltip.diskusage=Disk usage: %s/%s Byte
-oc:tooltip.disklocked=Locked by: %s
-oc:tooltip.diskmodemanaged=Mode: Managed
-oc:tooltip.diskmodeunmanaged=Mode: Unmanaged
-oc:tooltip.drone=Drones are light-weight, fast reconnaissance units with limited cargo space.
-oc:tooltip.dronecase=This casing is used to build Drones in the assembler. It has room for a small amount of components and provides endstone-powered levitation.
-oc:tooltip.eeprom=Small, programmable storage that contains the BIOS computers use to boot.
-oc:tooltip.fakeendstone=Almost as good as the real thing, even emulates its floatiness!
-oc:tooltip.geolyzer=Allows scanning the surrounding area's blocks' hardness. This information can be useful for generating holograms of the area or for detecting ores.
-oc:tooltip.graphicscard=Used to change what's displayed on screens.[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7[nl] Operations/tick: §f%s§7
-oc:tooltip.hoverboots=Jump higher, fall deeper, walk better. This and more, with the new and patented Hover Boots (TM).
-oc:tooltip.inkcartridge=Used to refill ink in 3D printers. For mysterious reasons it does not have to remain in the printer.
-oc:tooltip.inkcartridgeempty=This ink cartridge has been sucked dry. Refill it using dyes. Or throw it away. See if I care.
-oc:tooltip.internetcard=This card allows making HTTP requests and using real TCP sockets.
-oc:tooltip.interweb=Congratulations, you win one (1) interweb. You can connect to it using an Internet Card. Beware: don't feed the trolls.
-oc:tooltip.ironnugget=A nugget made of iron, that's why it's called an Iron Nugget, duh...
-oc:tooltip.keyboard=Can be attached to screens to allow typing on them.
-oc:tooltip.hologram0=A volumetric display that can be controlled by computers to display arbitrary voxel structures.[nl] Resolution: §f48x32x48§7 [nl] Maximum scale: §f3x§7 [nl] Color depth: §fMonochrome§7
-oc:tooltip.hologram1=A volumetric display that can be controlled by computers to display arbitrary voxel structures.[nl] Resolution: §f48x32x48§7 [nl] Maximum scale: §f4x§7 [nl] Color depth: §fTricolor§7
-oc:tooltip.linkedcard=These are crafted in pairs, and can only communicate with their partner card. However, they can communicate across any distance, and even across dimensions. The energy required to send a message is fairly high, though.
-oc:tooltip.linkedcard_channel=§8Channel: %s§7
-oc:tooltip.manual=All the information you could possibly need about OpenComputers. And more. For the unbelievably low price of... §oplease press R to continue§7.
-oc:tooltip.memory=Required to get computers to run. The more you have, the more complex the programs you can run.
-oc:tooltip.microchip=The chip formerly known as Integrated Circuit. I have no idea why this works with redstone, but it does.
-oc:tooltip.microcontroller=Microcontrollers are computers boiled down to the essentials. They are intended to take care of very specific tasks, running only a single program that is provided on the EEPROM built into them.[nl] §cCan not connect to external components.§7
-oc:tooltip.microcontrollercase=Base component for building microcontrollers. Place it into an assembler to add further components and assemble a microcontroller.
-oc:tooltip.motionsensor=Can detect movement of nearby living beings. Requires clear line-of-sight.
-oc:tooltip.nanomachines=Control unit and a bunch of nanomachines for ingestion, if you dare.
-oc:tooltip.networkcard=Allows distant computers connected by other blocks (such as cable) to communicate by sending messages to each other.
-oc:tooltip.poweracceptor=Energy conversion speed: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fBuildCraft MJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fFactorization Charge§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fIndustrialCraft² EU§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fMekanism Joules§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fThermal Expansion RF§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=Converts power from other mods to the internal energy type. Conversion rates:
-oc:tooltip.powerdistributor=Distributes energy among different networks. This is useful for sharing power fed into your system from one converter among different sub-networks that should remain separate.
-oc:tooltip.present=... for your troubles. Open this present for a chance to receive some §kphat lewt§7![nl]§8Craft OpenComputers items when the time is right for a chance to receive a present.§7
-oc:tooltip.print.BeaconBase=§8Works as a beacon base.
-oc:tooltip.print.LightValue=§8Light emitted: %s.
-oc:tooltip.print.RedstoneLevel=§8Redstone output: %s.
-oc:tooltip.printedcircuitboard=The basic building block for expansion cards and memory and such.
-oc:tooltip.printer=Allows printing blocks of user-defined shapes using Chamelium and Ink Cartridges. Must be configured using a computer. Keep away from small children. Because reasons.
-oc:tooltip.raid=Allows combining three hard drives into one larger file system that can be used by all connected computers.
-oc:tooltip.rawcircuitboard=Can be hardened in any furnace compatible oven.
-oc:tooltip.redstone=Allows reading and emitting redstone signals around the block. Can be controlled by any computer the block is connected to. This is basically like an external redstone card.
-oc:tooltip.redstonecard.Charset=§fSimpleLogic§7 is §asupported§7.
-oc:tooltip.redstonecard.ProjectRed=§fProjectRed§7 is §asupported§7.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 is §asupported§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 is §asupported§7.
-oc:tooltip.redstonecard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 is §asupported§7.
-oc:tooltip.redstonecard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 is §asupported§7.
-oc:tooltip.redstonecard=Allows reading and emitting redstone signals around the computer or robot.
-oc:tooltip.relay=Allows connecting different networks to each other. Only network messages will be passed along, components will not be visible through this. Use this to separate networks while still allowing communication using Network Cards, for example.
-oc:tooltip.robot=Unlike computers, robots can move around and interact with the world much like a player can.[nl] §cCan not connect to external components.§7
-# the underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fLevel§7: §a%s§7
-oc:tooltip.robot_storedenergy=§fStored energy§7: §a%s§7
-oc:tooltip.screen=Display text, controlled by a Graphics Card in a Case.[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7
-oc:tooltip.server=This is a server, there are many like it, but this one can be upgraded with components much like a computer case can be. It can be run by inserting it into a server rack.
-oc:tooltip.server.Components=Installed components:
-oc:tooltip.rack=Allows the installation of up to four servers or other rack mountables.
-oc:tooltip.tablet=A tablet computer, for fresh Lua on the go. Can be forced to shut down by sneak-activating it.
-oc:tooltip.tabletcase=Basic case for tablets. Place it into the assembler to add in components and create a tablet computer.
-oc:tooltip.terminal=Allows controlling a server remotely, as long as you are in range of it. Acts like a portable screen and keyboard. Shift-right-click a server in a server rack to bind the terminal to it.
-oc:tooltip.terminalserver=Backend to which Remote Terminals can be connected to provide remote control. Houses a virtual screen and keyboard.
-oc:tooltip.texturepicker=This tool allows showing a string describing a block's surface, for use in 3D printer shape definitions. Totally not texture names, nope. No sir.
-oc:tooltip.tier=§8Tier %s
-oc:tooltip.netsplitter=Acts as a dynamic connector. Connectivity of each side can be toggled by hitting it with a wrench. Connectivity of all sides can be inverted by applying a redstone signal.
-oc:tooltip.toolong=Hold [§f%s§7] for a detailed tooltip.
-oc:tooltip.transistor=A basic element in most other computer parts. It's a bit twisted, but it does the job.
-oc:tooltip.transposer=Allows automated transferral of items and fluids between adjacent inventories and fluid containers.
-oc:tooltip.upgradeangel=Allows robots to place blocks in thin air, even if there is no point of reference.
-oc:tooltip.upgradebattery=Increase the amount of energy a device can store, allowing it work longer without having to be recharged. [nl] Capacity: §f%s§7
-oc:tooltip.upgradechunkloader=If a robot moves in a forest and no one is around to see it, does it really move? This upgrades makes sure it does. It keeps the chunk a device is in loaded, but continually consumes energy while active.
-oc:tooltip.upgradecontainercard=This container upgrade allows dynamically installing and removing a card from an assembled device. [nl] Maximum Tier: §f%s§7
-oc:tooltip.upgradecontainerupgrade=This container upgrade allows dynamically installing and removing another upgrade from an assembled device. [nl] Maximum Tier: §f%s§7
-oc:tooltip.upgradecrafting=Enables robots to use the top left area of their inventory for crafting objects. Items have to be aligned as they would be in a crafting table.
-oc:tooltip.upgradedatabase=This upgrade allows storing item stack information for later retrieval and use by other components.[nl] Supported entries: §f%s§7
-oc:tooltip.upgradeexperience=This upgrade allows robots to accumulate experience by performing various operations. The more experience they have, the more energy they can store, the faster they can harvest blocks and the more efficiently they can use tools.
-oc:tooltip.upgradegenerator=Can be used to generate energy from fuel on the go. Burns items to generate energy over time, based on their fuel value.[nl] §fEfficiency§7: §a%s%%§7
-oc:tooltip.upgradehover=This upgrade allows robots to fly higher above the ground without having to climb walls.[nl] Maximum height: §f%s§7
-oc:tooltip.upgradeinventory=This upgrade provides inventory space to a robot or drone. Without one of these, they will not be able to store items internally.
-oc:tooltip.upgradeinventorycontroller=This upgrade allows robots and drones more control in how it interact with external inventories, and allows robots to swap their equipped tool with an item in their inventory.
-oc:tooltip.upgrademf=Allows adapters to access blocks they are not adjacent to.
-oc:tooltip.upgrademf.Linked=§fConnection established§7
-oc:tooltip.upgrademf.Unlinked=§fNo connection§7
-oc:tooltip.upgradeleash=Allows some devices, such as drones, to bind Isaa- excuse me... *chatter* My apologies. I'm just being told this is actually used to put animals on a leash. Multiple animals, even. Odd.
-oc:tooltip.upgradenavigation=Can be used to determine the position and orientation of a device. The position is relative to the center of the map that was used to craft this upgrade.
-oc:tooltip.upgradepiston=This upgrade is very pushy. It allows moving blocks, similar to a piston.
-oc:tooltip.upgradestickypiston=This upgrade can push and pull. It allows moving blocks, similar to a sticky piston. It does §lnot§7 pull entities, however.
-oc:tooltip.upgradesign=Allows reading text on and writing text to signs.
-oc:tooltip.upgradesolargenerator=Can be used to generate energy from sunlight on the go. Requires a clear line of sight to the sky above the device. Generates energy at %s%% of the speed of a Stirling Engine.
-oc:tooltip.upgradetank=This upgrade provides a tank for fluid storage for robots and drones. Without one of these, they will not be able to store fluids internally.
-oc:tooltip.upgradetankcontroller=This upgrade allows robots and drones more control in how they interact with external tanks, and allows them to transfer fluids into and out of fluid tank items in their inventory.
-oc:tooltip.upgradetractorbeam=Equips a device with extremely advanced technology, nicknamed the "Item Magnet". Allows the device to pick up items anywhere within 3 blocks of its location.
-oc:tooltip.upgradetrading=Allows robots and drones to trade with villagers.
-oc:tooltip.waypoint=Provides a point of reference to devices with a navigation upgrade.
-oc:tooltip.wirelessnetworkcard=Allows wireless sending of network messages in addition to normal ones. You can adjust the §fsignal strength§7 to control how far messages are sent. Higher signal strength results in higher energy consumption.
-oc:tooltip.worldsensorcard=Allows reading out information about the world, such as its gravity and whether it has a breathable atmosphere. Use results at own risk. The manufacturer takes no responsibility for bodily or material harm caused by decisions made upon the cards' outputs. We have lawyers. And money. Don't even try.
-oc:tooltip.Wrench=A hybrid of Screwdriver and Wrench, this tool is easy to learn, but hard to master.
-
-#Achievements
-achievement.oc.adapter=Plug In Baby
-achievement.oc.adapter.desc=Interact with blocks from other mods and even vanilla Minecraft!
-achievement.oc.assembler=Wonderful
-achievement.oc.assembler.desc=Time to take over the world!
-achievement.oc.cable=Not a Dirty Wire
-achievement.oc.cable.desc=With patented anti-cable-spaghetti technology.
-achievement.oc.capacitor=Batteries included
-achievement.oc.capacitor.desc=You cannot stop it.
-achievement.oc.card=We Accept Cards
-achievement.oc.card.desc=For your convenience. No ulterior motive, promise.
-achievement.oc.case=In Case of Trouble
-achievement.oc.case.desc=Because cuboid towers are the best.
-achievement.oc.charger=All right, let's do this
-achievement.oc.charger.desc=Chaaaaaaaaaarg- dang, forgot the redstone signal again.
-achievement.oc.chip=All the Small Things
-achievement.oc.chip.desc=Because vacuum tubes are so yesteryear.
-achievement.oc.cpu=Overclocked
-achievement.oc.cpu.desc=Time to make good use of those computing cycles.
-achievement.oc.disassembler=Scratch That
-achievement.oc.disassembler.desc=In case one of your brilliant ideas turns out to be not that brilliant after all.
-achievement.oc.diskDrive=Roundabout
-achievement.oc.diskDrive.desc=Inferior capacity but such delicious sound.
-achievement.oc.drone=Fly Away
-achievement.oc.drone.desc=Keep calm and nuke it from orbit.
-achievement.oc.eeprom=There can be only one
-achievement.oc.eeprom.desc=Per computer, that is. For deterministic boot order, you know?
-achievement.oc.floppy=The One Ri- Disk
-achievement.oc.floppy.desc=Not to be confused with Flappy.
-achievement.oc.geolyzer=Down to Earth
-achievement.oc.geolyzer.desc=It has extraordinary qualities.
-achievement.oc.graphicsCard=LastGen
-achievement.oc.graphicsCard.desc=The way it's meant to be... uh... rendered. Yeah. That.
-achievement.oc.hdd=Hot Dog Dealer
-achievement.oc.hdd.desc=No wait, that's not what that meant. Hang on, almost got it...
-achievement.oc.hologram=Next Dimension
-achievement.oc.hologram.desc=Because 2D is boring. Or is it?
-achievement.oc.keyboard=DirtCatcher3000
-achievement.oc.keyboard.desc=It is highly recommended to resist the urge to flip them around and shake them.
-achievement.oc.microcontroller=Little Sister
-achievement.oc.microcontroller.desc=The small sibling of computers.
-achievement.oc.motionSensor=Got the Moves
-achievement.oc.motionSensor.desc=Like Steve Swagger.
-achievement.oc.networkCard=Now We're Talking!
-achievement.oc.networkCard.desc=Keep in touch with those distant relatives via transitive relations.
-achievement.oc.openOS=Boot
-achievement.oc.openOS.desc=One OS to - wait, I used that one already? Dang.
-achievement.oc.powerDistributor=Sharing is Caring
-achievement.oc.powerDistributor.desc=When you need some help balancing all that power.
-achievement.oc.rack=Dat Rack
-achievement.oc.rack.desc=I don't know what you're thinking of, I clearly meant the server rack.
-achievement.oc.raid=LFG
-achievement.oc.raid.desc=Heroic plzkthx.
-achievement.oc.ram=Random Access Memories
-achievement.oc.ram.desc=Congratulations, you're Doin' It Right.
-achievement.oc.redstoneCard=Contact
-achievement.oc.redstoneCard.desc=Time to go analog.
-achievement.oc.redstoneIO=The Outsider
-achievement.oc.redstoneIO.desc=Taking redstone signals where you want them.
-achievement.oc.robot=Beep Boop
-achievement.oc.robot.desc=EXTERMINATE!
-achievement.oc.screen=Have you tried turning it off and on again?
-achievement.oc.screen.desc=No seriously. A redstone pulse can toggle a screen's power, after all.
-achievement.oc.server=Dedicated
-achievement.oc.server.desc=Cloud services, here we come.
-achievement.oc.switch=Complex Topology
-achievement.oc.switch.desc=Avoid fragile goods due to possibility of dropped packets.
-achievement.oc.tablet=Do Not Swallow
-achievement.oc.tablet.desc=Also keep away from small children to avoid unexpected overdrawing of your credit card.
-achievement.oc.transistor=Tell Red I said "Hi."
-achievement.oc.transistor.desc=Create a Transistor to get started. Then listen to the soundtrack. No need to thank me.
-achievement.oc.wirelessNetworkCard=Signals
-achievement.oc.wirelessNetworkCard.desc=Time to go where no packet has gone before.
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code.
-death.attack.oc.nanomachinesOverload.1=%s got too greedy.
-death.attack.oc.nanomachinesOverload.2=%s had a nervous breakdown.
-death.attack.oc.nanomachinesOverload.3=The nanomachines of %s went out of control.
-death.attack.oc.nanomachinesHungry.1=%s was eaten by nanomachines.
-death.attack.oc.nanomachinesHungry.2=%s didn't keep their nanomachines fed.
-death.attack.oc.nanomachinesHungry.3=%s has been digested.
-
-# NEI Integration
-nei.options.inventory.oredict=Show OreDictionary names
-nei.options.inventory.oredict.true=True
-nei.options.inventory.oredict.false=False
-nei.usage.oc.Manual=Open Manual
-
-# Waila Integration
-option.oc.address=Address
-option.oc.componentName=Component Name
-option.oc.energy=Energy
diff --git a/src/main/resources/assets/opencomputers/lang/en_us.json b/src/main/resources/assets/opencomputers/lang/en_us.json
new file mode 100644
index 0000000000..5d4d881651
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/en_us.json
@@ -0,0 +1,461 @@
+{
+ "tile.oc.adapter": "Adapter",
+ "tile.oc.assembler": "Electronics Assembler",
+ "tile.oc.cable": "Cable",
+ "tile.oc.capacitor": "Capacitor",
+ "tile.oc.carpetedcapacitor": "Carpeted Capacitor",
+ "tile.oc.case1": "Computer Case (Tier 1)",
+ "tile.oc.case2": "Computer Case (Tier 2)",
+ "tile.oc.case3": "Computer Case (Tier 3)",
+ "tile.oc.casecreative": "Computer Case (Creative)",
+ "tile.oc.chameliumblock": "Block of Chamelium",
+ "tile.oc.charger": "Charger",
+ "tile.oc.disassembler": "Disassembler",
+ "tile.oc.diskdrive": "Disk Drive",
+ "tile.oc.endstone": "End Stone",
+ "tile.oc.geolyzer": "Geolyzer",
+ "tile.oc.hologram1": "Hologram Projector (Tier 1)",
+ "tile.oc.hologram2": "Hologram Projector (Tier 2)",
+ "tile.oc.keyboard": "Keyboard",
+ "tile.oc.microcontroller": "Microcontroller",
+ "tile.oc.motionsensor": "Motion Sensor",
+ "tile.oc.netsplitter": "Net Splitter",
+ "tile.oc.powerconverter": "Power Converter",
+ "tile.oc.powerdistributor": "Power Distributor",
+ "tile.oc.print": "3D Print",
+ "tile.oc.printer": "3D Printer",
+ "tile.oc.raid": "Raid",
+ "tile.oc.redstone": "Redstone I/O",
+ "tile.oc.relay": "Relay",
+ "tile.oc.robot": "Robot",
+ "tile.oc.robotafterimage": "Robot",
+ "tile.oc.screen1": "Screen (Tier 1)",
+ "tile.oc.screen2": "Screen (Tier 2)",
+ "tile.oc.screen3": "Screen (Tier 3)",
+ "tile.oc.rack": "Rack",
+ "tile.oc.transposer": "Transposer",
+ "tile.oc.waypoint": "Waypoint",
+ "item.oc.abstractbuscard": "Abstract Bus Card",
+ "item.oc.acid": "Grog",
+ "item.oc.alu": "Arithmetic Logic Unit (ALU)",
+ "item.oc.analyzer": "Analyzer",
+ "item.oc.apu0": "Accelerated Processing Unit (APU) (Tier 2)",
+ "item.oc.apu1": "Accelerated Processing Unit (APU) (Tier 3)",
+ "item.oc.apu2": "Accelerated Processing Unit (APU) (Creative)",
+ "item.oc.arrowkeys": "Arrow Keys",
+ "item.oc.buttongroup": "Button Group",
+ "item.oc.cardbase": "Card Base",
+ "item.oc.chamelium": "Chamelium",
+ "item.oc.circuitboard": "Circuit Board",
+ "item.oc.componentbus0": "Component Bus (Tier 1)",
+ "item.oc.componentbus1": "Component Bus (Tier 2)",
+ "item.oc.componentbus2": "Component Bus (Tier 3)",
+ "item.oc.componentbus3": "Component Bus (Creative)",
+ "item.oc.controlunit": "Control Unit (CU)",
+ "item.oc.cpu0": "Central Processing Unit (CPU) (Tier 1)",
+ "item.oc.cpu1": "Central Processing Unit (CPU) (Tier 2)",
+ "item.oc.cpu2": "Central Processing Unit (CPU) (Tier 3)",
+ "item.oc.cuttingwire": "Cutting Wire",
+ "item.oc.datacard0": "Data Card (Tier 1)",
+ "item.oc.datacard1": "Data Card (Tier 2)",
+ "item.oc.datacard2": "Data Card (Tier 3)",
+ "item.oc.debugcard": "Debug Card",
+ "item.oc.debugger": "Network Debugger",
+ "item.oc.diamondchip": "Diamond Chip",
+ "item.oc.disk": "Disk Platter",
+ "item.oc.diskdrivemountable": "Disk Drive",
+ "item.oc.drone": "Drone",
+ "item.oc.dronecase0": "Drone Case (Tier 1)",
+ "item.oc.dronecase1": "Drone Case (Tier 2)",
+ "item.oc.dronecase3": "Drone Case (Creative)",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.floppydisk": "Floppy Disk",
+ "item.oc.graphicscard0": "Graphics Card (Tier 1)",
+ "item.oc.graphicscard1": "Graphics Card (Tier 2)",
+ "item.oc.graphicscard2": "Graphics Card (Tier 3)",
+ "item.oc.harddiskdrive0": "Hard Disk Drive (Tier 1)",
+ "item.oc.harddiskdrive1": "Hard Disk Drive (Tier 2)",
+ "item.oc.harddiskdrive2": "Hard Disk Drive (Tier 3)",
+ "item.oc.hoverboots": "Hover Boots",
+ "item.oc.inkcartridge": "Ink Cartridge",
+ "item.oc.inkcartridgeempty": "Ink Cartridge (Empty)",
+ "item.oc.internetcard": "Internet Card",
+ "item.oc.interweb": "Interweb",
+ "item.oc.ironnugget": "Iron Nugget",
+ "item.oc.linkedcard": "Linked Card",
+ "item.oc.manual": "OpenComputers Manual",
+ "item.oc.memory0": "Memory (Tier 1)",
+ "item.oc.memory1": "Memory (Tier 1.5)",
+ "item.oc.memory2": "Memory (Tier 2)",
+ "item.oc.memory3": "Memory (Tier 2.5)",
+ "item.oc.memory4": "Memory (Tier 3)",
+ "item.oc.memory5": "Memory (Tier 3.5)",
+ "item.oc.microchip0": "Microchip (Tier 1)",
+ "item.oc.microchip1": "Microchip (Tier 2)",
+ "item.oc.microchip2": "Microchip (Tier 3)",
+ "item.oc.microcontrollercase0": "Microcontroller Case (Tier 1)",
+ "item.oc.microcontrollercase1": "Microcontroller Case (Tier 2)",
+ "item.oc.microcontrollercase3": "Microcontroller Case (Creative)",
+ "item.oc.nanomachines": "Nanomachines",
+ "item.oc.networkcard": "Network Card",
+ "item.oc.numpad": "Numeric Keypad",
+ "item.oc.present": "A little something...",
+ "item.oc.printedcircuitboard": "Printed Circuit Board (PCB)",
+ "item.oc.rawcircuitboard": "Raw Circuit Board",
+ "item.oc.redstonecard0": "Redstone Card (Tier 1)",
+ "item.oc.redstonecard1": "Redstone Card (Tier 2)",
+ "item.oc.server0": "Server (Tier 1)",
+ "item.oc.server1": "Server (Tier 2)",
+ "item.oc.server2": "Server (Tier 3)",
+ "item.oc.server3": "Server (Creative)",
+ "item.oc.tablet": "Tablet",
+ "item.oc.tabletcase0": "Tablet Case (Tier 1)",
+ "item.oc.tabletcase1": "Tablet Case (Tier 2)",
+ "item.oc.tabletcase3": "Tablet Case (Creative)",
+ "item.oc.terminal": "Remote Terminal",
+ "item.oc.terminalserver": "Terminal Server",
+ "item.oc.texturepicker": "Texture Picker",
+ "item.oc.transistor": "Transistor",
+ "item.oc.upgradeangel": "Angel Upgrade",
+ "item.oc.upgradebattery0": "Battery Upgrade (Tier 1)",
+ "item.oc.upgradebattery1": "Battery Upgrade (Tier 2)",
+ "item.oc.upgradebattery2": "Battery Upgrade (Tier 3)",
+ "item.oc.upgradechunkloader": "Chunkloader Upgrade",
+ "item.oc.upgradecontainercard0": "Card Container (Tier 1)",
+ "item.oc.upgradecontainercard1": "Card Container (Tier 2)",
+ "item.oc.upgradecontainercard2": "Card Container (Tier 3)",
+ "item.oc.upgradecontainerupgrade0": "Upgrade Container (Tier 1)",
+ "item.oc.upgradecontainerupgrade1": "Upgrade Container (Tier 2)",
+ "item.oc.upgradecontainerupgrade2": "Upgrade Container (Tier 3)",
+ "item.oc.upgradecrafting": "Crafting Upgrade",
+ "item.oc.upgradedatabase0": "Database Upgrade (Tier 1)",
+ "item.oc.upgradedatabase1": "Database Upgrade (Tier 2)",
+ "item.oc.upgradedatabase2": "Database Upgrade (Tier 3)",
+ "item.oc.upgradeexperience": "Experience Upgrade",
+ "item.oc.upgradegenerator": "Generator Upgrade",
+ "item.oc.upgradehover0": "Hover Upgrade (Tier 1)",
+ "item.oc.upgradehover1": "Hover Upgrade (Tier 2)",
+ "item.oc.upgradeinventory": "Inventory Upgrade",
+ "item.oc.upgradeinventorycontroller": "Inventory Controller Upgrade",
+ "item.oc.upgradeleash": "Leash Upgrade",
+ "item.oc.upgrademf": "MFU",
+ "item.oc.upgradenavigation": "Navigation Upgrade",
+ "item.oc.upgradepiston": "Piston Upgrade",
+ "item.oc.upgradestickypiston": "Sticky Piston Upgrade",
+ "item.oc.upgradesign": "Sign I/O Upgrade",
+ "item.oc.upgradesolargenerator": "Solar Generator Upgrade",
+ "item.oc.upgradetank": "Tank Upgrade",
+ "item.oc.upgradetankcontroller": "Tank Controller Upgrade",
+ "item.oc.upgradetractorbeam": "Tractor Beam Upgrade",
+ "item.oc.upgradetrading": "Trading Upgrade",
+ "item.oc.wirelessnetworkcard0": "Wireless Network Card (Tier 1)",
+ "item.oc.wirelessnetworkcard1": "Wireless Network Card (Tier 2)",
+ "item.oc.worldsensorcard": "World Sensor Card",
+ "item.oc.wrench": "Scrench",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "Drone",
+ "oc:gui.Analyzer.Address": "§6Address§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Address copied to clipboard.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Charge speed§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Component name§f: %s",
+ "oc:gui.Analyzer.Components": "§6Number of connected components§f: %s",
+ "oc:gui.Analyzer.CopyToClipboard": "Click to copy to clipboard.",
+ "oc:gui.Analyzer.LastError": "§6Last error§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Name§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Owner§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Experience§f: %s (Level %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6Stored energy§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Total stored energy§f: %s",
+ "oc:gui.Analyzer.Users": "§6Users§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Signal strength§f: %s",
+ "oc:gui.Assembler.Collect": "Collect output",
+ "oc:gui.Assembler.Complexity": "Complexity: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Insert a base part",
+ "oc:gui.Assembler.InsertCPU": "Insert a CPU",
+ "oc:gui.Assembler.InsertRAM": "Insert some RAM",
+ "oc:gui.Assembler.Progress": "Progress: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Assemble",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Graphics Card",
+ "oc:gui.Assembler.Warning.Inventory": "Inventory Upgrade",
+ "oc:gui.Assembler.Warning.Keyboard": "Keyboard",
+ "oc:gui.Assembler.Warning.OS": "Bootable Medium",
+ "oc:gui.Assembler.Warning.Screen": "Screen",
+ "oc:gui.Assembler.Warnings": "§eWarning§7: Recommended components are missing.",
+ "oc:gui.Chat.NewVersion": "A new version is available: %s",
+ "oc:gui.Chat.TextureName": "§7Texture name is §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "There were §cerrors§f running the class transformer. Please report this, together with your (full!) FML §alatest.log§f/§afml-server-latest.log§f logfile, thank you!",
+ "oc:gui.Chat.WarningFingerprint": "§cWARNING§f - fingerprint mismatch! Expected '§a%s§f' but got '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.",
+ "oc:gui.Chat.WarningLink": "Could not open link: %s",
+ "oc:gui.Chat.WarningLuaFallback": "Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads.",
+ "oc:gui.Chat.WarningProjectRed": "You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.",
+ "oc:gui.Chat.WarningRecipes": "There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.",
+ "oc:gui.Drive.Managed": "Managed",
+ "oc:gui.Drive.Unmanaged": "Unmanaged",
+ "oc:gui.Drive.ReadOnlyLock": "Lock",
+ "oc:gui.Drive.ReadOnlyLockWarning": "§lRead Only§r lock. Cannot be removed unless the drive is wiped.",
+ "oc:gui.Drive.Warning": "§lWarning§r: switching modes will result in a loss of all data currently stored on the disk!",
+ "oc:gui.Error.ComponentOverflow": "Too many components connected to the computer.",
+ "oc:gui.Error.InternalError": "Internal error, please see the log file. This is probably a bug.",
+ "oc:gui.Error.NoCPU": "No CPU is installed in the computer.",
+ "oc:gui.Error.NoEnergy": "Not enough energy.",
+ "oc:gui.Error.NoRAM": "No RAM is installed in the computer.",
+ "oc:gui.Error.OutOfMemory": "Out of memory.",
+ "oc:gui.Manual.Blocks": "OpenComputers Blocks",
+ "oc:gui.Manual.Home": "Home",
+ "oc:gui.Manual.Items": "OpenComputers Items",
+ "oc:gui.Manual.Warning.BlockMissing": "Block unavailable.",
+ "oc:gui.Manual.Warning.ImageMissing": "Image not found.",
+ "oc:gui.Manual.Warning.ItemMissing": "Item unavailable.",
+ "oc:gui.Manual.Warning.OreDictMissing": "Ore dictionary entry unavailable.",
+ "oc:gui.Raid.Warning": "§4Adding a disk wipes it.\nRemoving a disk wipes the raid.",
+ "oc:gui.Robot.Power": "Energy",
+ "oc:gui.Robot.TurnOff": "Turn off",
+ "oc:gui.Robot.TurnOn": "Turn on\n§7Use an Analyzer to troubleshoot errors.§r",
+ "oc:gui.Rack.Back": "Back",
+ "oc:gui.Rack.Bottom": "Bottom",
+ "oc:gui.Rack.Left": "Left",
+ "oc:gui.Rack.None": "None",
+ "oc:gui.Rack.Right": "Right",
+ "oc:gui.Rack.Enabled": "Enabled",
+ "oc:gui.Rack.Disabled": "Disabled",
+ "oc:gui.Rack.RelayModeTooltip": "Relay Mode",
+ "oc:gui.Rack.Top": "Top",
+ "oc:gui.Switch.PacketsPerCycle": "Packets / cycle",
+ "oc:gui.Switch.QueueSize": "Queue size",
+ "oc:gui.Switch.TransferRate": "Cycle rate",
+ "oc:gui.Terminal.InvalidKey": "Invalid key, most likely another terminal has been bound to the server.",
+ "oc:gui.Terminal.OutOfRange": "No signal.",
+ "oc:container.adapter": "Adapter",
+ "oc:container.case": "Computer",
+ "oc:container.charger": "Charger",
+ "oc:container.disassembler": "Disassembler",
+ "oc:container.diskdrive": "Disk Drive",
+ "oc:container.printer": "Printer",
+ "oc:container.raid": "Raid",
+ "oc:container.relay": "Relay",
+ "oc:container.server": "Server",
+ "oc:container.rack": "Rack",
+ "oc:container.tabletwrapper": "Tablet",
+ "key.opencomputers.analyzeCopyAddress": "Copy Address (Analyzer)",
+ "key.opencomputers.clipboardPaste": "Paste Clipboard",
+ "key.opencomputers.extendedTooltip": "Show Detailed Tooltips",
+ "oc:tooltip.abstractbuscard": "Allows interacting with §fStargateTech 2§7's abstract bus by sending and receiving LIP packets.",
+ "oc:tooltip.acid": "A highly toxic pseudo-liquid, usually only consumed by certain pirates. May prove to be useful in other ways, too, however.",
+ "oc:tooltip.adapter": "Used to control non-component blocks, such as vanilla blocks or blocks from other mods.",
+ "oc:tooltip.alu": "Adds numbers so you don't have to. It might be better this way.",
+ "oc:tooltip.analyzer": "Used to display information about blocks, such as their §faddress§7 and §fcomponent name§7.\nAlso displays the error that caused a computer to crash if it did not shut down normally.",
+ "oc:tooltip.apu": "This is a CPU with an integrated GPU (or IGP), when you just need that extra card slot.\nSupported components: §f%s§7\nMaximum resolution: §f%sx%s§7\nMaximum color depth: §f%s§7\nOperations/tick: §f%s§7",
+ "oc:tooltip.assembler": "Allows constructing robots and other devices from a number of different computer parts.",
+ "oc:tooltip.cable": "A cheap way of connecting blocks.",
+ "oc:tooltip.capacitor": "Stores energy for later use. Can be filled and emptied very quickly.",
+ "oc:tooltip.carpetedcapacitor": "Stores energy for later use. Can be filled and emptied very quickly. Charges when Sheep or Ocelots walk on it",
+ "oc:tooltip.cardbase": "As the name indicates, this is the basic building block for all expansion cards.",
+ "oc:tooltip.case": "The Computer Case is the basic building block for computers and houses the computer's §fextension cards§7, §fRAM§7 and §fhard disks§7.\nSlots: §f%s§7",
+ "oc:tooltip.chamelium": "Raw material for 3D prints. Do not swallow: may lead to blindness and temporary lack of presence.",
+ "oc:tooltip.chameliumblock": "Nice and clean. Handy for tinted shapes in 3D prints, or just for having a clean, colored block to decorate your fancy base with.",
+ "oc:tooltip.charger": "Transfers energy from capacitors into adjacent robots and drones. The transfer rate depends on the incoming §fredstone signal§7, where no signal means don't charge devices, and maximum strength means charge at full speed. Can also be used to charge tablets and access hard drives in tablets.",
+ "oc:tooltip.circuitboard": "Now we're getting somewhere. Can be etched to obtain a printed circuit board.",
+ "oc:tooltip.controlunit": "This is the unit that... controls... stuff. You need it to build a CPU. So yeah, totally important.",
+ "oc:tooltip.componentbus": "This expansion allows servers to communicate with more components at the same time, similar to how CPUs do.\nSupported components: §f%s§7",
+ "oc:tooltip.cpu": "An essential component of all computers. The clock rate is a bit unreliable, but what do you expect when it runs on a pocket sundial?\nSupported components: §f%s§7",
+ "oc:tooltip.cpu.Architecture": "Architecture: §f%s§7",
+ "oc:tooltip.cuttingwire": "Used to cut clay blocks into circuit board shape. Breaks after one use, which probably makes it the most inefficient tool ever.",
+ "oc:tooltip.datacard0": "Provides a couple of advanced algorithms such as hashing and deflate/inflate.",
+ "oc:tooltip.datacard1": "Provides a couple of advanced algorithms such as hashing, AES encryption and deflate/inflate.",
+ "oc:tooltip.datacard2": "Provides a couple of advanced algorithms such as hashing, AES encryption, elliptic curve cryptography and deflate/inflate.",
+ "oc:tooltip.debugcard": "Creative mode item, allows manipulating the world to make testing easier. Use at your own peril.",
+ "oc:tooltip.debugger": "Can be used to output debug information on OC's internal network grid. Only use if so instructed by a dev.",
+ "oc:tooltip.diamondchip": "A small piece of a once radiant diamond. It will never be the same again.",
+ "oc:tooltip.disassembler": "Separates items into their original components. §lWarning§7: returned items have a %s%% chance of breaking in the process!",
+ "oc:tooltip.disk": "Primitive medium that can be used to build persistent storage devices.",
+ "oc:tooltip.diskdrive.CC": "ComputerCraft floppies are §asupported§7.",
+ "oc:tooltip.diskdrive": "Allows reading and writing floppies. Can be installed in robots to allow inserting floppies later on.",
+ "oc:tooltip.diskdrivemountable": "Provides the same functionality as a normal disk drive, but must be installed in a rack.",
+ "oc:tooltip.diskusage": "Disk usage: %s/%s Byte",
+ "oc:tooltip.disklocked": "Locked by: %s",
+ "oc:tooltip.diskmodemanaged": "Mode: Managed",
+ "oc:tooltip.diskmodeunmanaged": "Mode: Unmanaged",
+ "oc:tooltip.drone": "Drones are light-weight, fast reconnaissance units with limited cargo space.",
+ "oc:tooltip.dronecase": "This casing is used to build Drones in the assembler. It has room for a small amount of components and provides endstone-powered levitation.",
+ "oc:tooltip.eeprom": "Small, programmable storage that contains the BIOS computers use to boot.",
+ "oc:tooltip.fakeendstone": "Almost as good as the real thing, even emulates its floatiness!",
+ "oc:tooltip.geolyzer": "Allows scanning the surrounding area's blocks' hardness. This information can be useful for generating holograms of the area or for detecting ores.",
+ "oc:tooltip.graphicscard": "Used to change what's displayed on screens.\nMaximum resolution: §f%sx%s§7\nMaximum color depth: §f%s§7\nOperations/tick: §f%s§7",
+ "oc:tooltip.hoverboots": "Jump higher, fall deeper, walk better. This and more, with the new and patented Hover Boots (TM).",
+ "oc:tooltip.inkcartridge": "Used to refill ink in 3D printers. For mysterious reasons it does not have to remain in the printer.",
+ "oc:tooltip.inkcartridgeempty": "This ink cartridge has been sucked dry. Refill it using dyes. Or throw it away. See if I care.",
+ "oc:tooltip.internetcard": "This card allows making HTTP requests and using real TCP sockets.",
+ "oc:tooltip.interweb": "Congratulations, you win one (1) interweb. You can connect to it using an Internet Card. Beware: don't feed the trolls.",
+ "oc:tooltip.ironnugget": "A nugget made of iron, that's why it's called an Iron Nugget, duh...",
+ "oc:tooltip.keyboard": "Can be attached to screens to allow typing on them.",
+ "oc:tooltip.hologram0": "A volumetric display that can be controlled by computers to display arbitrary voxel structures.\nResolution: §f48x32x48§7\nMaximum scale: §f3x§7\nColor depth: §fMonochrome§7",
+ "oc:tooltip.hologram1": "A volumetric display that can be controlled by computers to display arbitrary voxel structures.\nResolution: §f48x32x48§7\nMaximum scale: §f4x§7\nColor depth: §fTricolor§7",
+ "oc:tooltip.linkedcard": "These are crafted in pairs, and can only communicate with their partner card. However, they can communicate across any distance, and even across dimensions. The energy required to send a message is fairly high, though.",
+ "oc:tooltip.linkedcard_channel": "§8Channel: %s§7",
+ "oc:tooltip.manual": "All the information you could possibly need about OpenComputers. And more. For the unbelievably low price of... §oplease press R to continue§7.",
+ "oc:tooltip.memory": "Required to get computers to run. The more you have, the more complex the programs you can run.",
+ "oc:tooltip.microchip": "The chip formerly known as Integrated Circuit. I have no idea why this works with redstone, but it does.",
+ "oc:tooltip.microcontroller": "Microcontrollers are computers boiled down to the essentials. They are intended to take care of very specific tasks, running only a single program that is provided on the EEPROM built into them.\n§cCan not connect to external components.§7",
+ "oc:tooltip.microcontrollercase": "Base component for building microcontrollers. Place it into an assembler to add further components and assemble a microcontroller.",
+ "oc:tooltip.motionsensor": "Can detect movement of nearby living beings. Requires clear line-of-sight.",
+ "oc:tooltip.nanomachines": "Control unit and a bunch of nanomachines for ingestion, if you dare.",
+ "oc:tooltip.networkcard": "Allows distant computers connected by other blocks (such as cable) to communicate by sending messages to each other.",
+ "oc:tooltip.poweracceptor": "Energy conversion speed: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fBuildCraft MJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fFactorization Charge§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fIndustrialCraft² EU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fMekanism Joules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fThermal Expansion RF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fResonant Engine Coulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Converts power from other mods to the internal energy type. Conversion rates:",
+ "oc:tooltip.powerdistributor": "Distributes energy among different networks. This is useful for sharing power fed into your system from one converter among different sub-networks that should remain separate.",
+ "oc:tooltip.present": "... for your troubles. Open this present for a chance to receive some §kphat lewt§7!\n§8Craft OpenComputers items when the time is right for a chance to receive a present.§7",
+ "oc:tooltip.print.BeaconBase": "§8Works as a beacon base.",
+ "oc:tooltip.print.LightValue": "§8Light emitted: %s.",
+ "oc:tooltip.print.RedstoneLevel": "§8Redstone output: %s.",
+ "oc:tooltip.printedcircuitboard": "The basic building block for expansion cards and memory and such.",
+ "oc:tooltip.printer": "Allows printing blocks of user-defined shapes using Chamelium and Ink Cartridges. Must be configured using a computer. Keep away from small children. Because reasons.",
+ "oc:tooltip.raid": "Allows combining three hard drives into one larger file system that can be used by all connected computers.",
+ "oc:tooltip.rawcircuitboard": "Can be hardened in any furnace compatible oven.",
+ "oc:tooltip.redstone": "Allows reading and emitting redstone signals around the block. Can be controlled by any computer the block is connected to. This is basically like an external redstone card.",
+ "oc:tooltip.redstonecard.Charset": "§fSimpleLogic§7 is §asupported§7.",
+ "oc:tooltip.redstonecard.ProjectRed": "§fProjectRed§7 is §asupported§7.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 is §asupported§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 is §asupported§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "§fWireless Redstone (ChickenBones)§7 is §asupported§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "§fWireless Redstone (SlimeVoid)§7 is §asupported§7.",
+ "oc:tooltip.redstonecard": "Allows reading and emitting redstone signals around the computer or robot.",
+ "oc:tooltip.relay": "Allows connecting different networks to each other. Only network messages will be passed along, components will not be visible through this. Use this to separate networks while still allowing communication using Network Cards, for example.",
+ "oc:tooltip.robot": "Unlike computers, robots can move around and interact with the world much like a player can.\n§cCan not connect to external components.§7",
+ "oc:tooltip.robot_level": "§fLevel§7: §a%s§7",
+ "oc:tooltip.robot_storedenergy": "§fStored energy§7: §a%s§7",
+ "oc:tooltip.screen": "Display text, controlled by a Graphics Card in a Case.\nMaximum resolution: §f%sx%s§7\nMaximum color depth: §f%s§7",
+ "oc:tooltip.server": "This is a server, there are many like it, but this one can be upgraded with components much like a computer case can be. It can be run by inserting it into a server rack.",
+ "oc:tooltip.server.Components": "Installed components:",
+ "oc:tooltip.rack": "Allows the installation of up to four servers or other rack mountables.",
+ "oc:tooltip.tablet": "A tablet computer, for fresh Lua on the go. Can be forced to shut down by sneak-activating it.",
+ "oc:tooltip.tabletcase": "Basic case for tablets. Place it into the assembler to add in components and create a tablet computer.",
+ "oc:tooltip.terminal": "Allows controlling a server remotely, as long as you are in range of it. Acts like a portable screen and keyboard. Shift-right-click a server in a server rack to bind the terminal to it.",
+ "oc:tooltip.terminalserver": "Backend to which Remote Terminals can be connected to provide remote control. Houses a virtual screen and keyboard.",
+ "oc:tooltip.texturepicker": "This tool allows showing a string describing a block's surface, for use in 3D printer shape definitions. Totally not texture names, nope. No sir.",
+ "oc:tooltip.tier": "§8Tier %s",
+ "oc:tooltip.netsplitter": "Acts as a dynamic connector. Connectivity of each side can be toggled by hitting it with a wrench. Connectivity of all sides can be inverted by applying a redstone signal.",
+ "oc:tooltip.toolong": "Hold [§f%s§7] for a detailed tooltip.",
+ "oc:tooltip.transistor": "A basic element in most other computer parts. It's a bit twisted, but it does the job.",
+ "oc:tooltip.transposer": "Allows automated transferral of items and fluids between adjacent inventories and fluid containers.",
+ "oc:tooltip.upgradeangel": "Allows robots to place blocks in thin air, even if there is no point of reference.",
+ "oc:tooltip.upgradebattery": "Increase the amount of energy a device can store, allowing it work longer without having to be recharged.\nCapacity: §f%s§7",
+ "oc:tooltip.upgradechunkloader": "If a robot moves in a forest and no one is around to see it, does it really move? This upgrades makes sure it does. It keeps the chunk a device is in loaded, but continually consumes energy while active.",
+ "oc:tooltip.upgradecontainercard": "This container upgrade allows dynamically installing and removing a card from an assembled device.\nMaximum Tier: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "This container upgrade allows dynamically installing and removing another upgrade from an assembled device.\nMaximum Tier: §f%s§7",
+ "oc:tooltip.upgradecrafting": "Enables robots to use the top left area of their inventory for crafting objects. Items have to be aligned as they would be in a crafting table.",
+ "oc:tooltip.upgradedatabase": "This upgrade allows storing item stack information for later retrieval and use by other components.\nSupported entries: §f%s§7",
+ "oc:tooltip.upgradeexperience": "This upgrade allows robots to accumulate experience by performing various operations. The more experience they have, the more energy they can store, the faster they can harvest blocks and the more efficiently they can use tools.",
+ "oc:tooltip.upgradegenerator": "Can be used to generate energy from fuel on the go. Burns items to generate energy over time, based on their fuel value.\n§fEfficiency§7: §a%s%%§7",
+ "oc:tooltip.upgradehover": "This upgrade allows robots to fly higher above the ground without having to climb walls.\nMaximum height: §f%s§7",
+ "oc:tooltip.upgradeinventory": "This upgrade provides inventory space to a robot or drone. Without one of these, they will not be able to store items internally.",
+ "oc:tooltip.upgradeinventorycontroller": "This upgrade allows robots and drones more control in how it interact with external inventories, and allows robots to swap their equipped tool with an item in their inventory.",
+ "oc:tooltip.upgrademf": "Allows adapters to access blocks they are not adjacent to.",
+ "oc:tooltip.upgrademf.Linked": "§fConnection established§7",
+ "oc:tooltip.upgrademf.Unlinked": "§fNo connection§7",
+ "oc:tooltip.upgradeleash": "Allows some devices, such as drones, to bind Isaa- excuse me... *chatter* My apologies. I'm just being told this is actually used to put animals on a leash. Multiple animals, even. Odd.",
+ "oc:tooltip.upgradenavigation": "Can be used to determine the position and orientation of a device. The position is relative to the center of the map that was used to craft this upgrade.",
+ "oc:tooltip.upgradepiston": "This upgrade is very pushy. It allows moving blocks, similar to a piston.",
+ "oc:tooltip.upgradestickypiston": "This upgrade can push and pull. It allows moving blocks, similar to a sticky piston. It does §lnot§7 pull entities, however.",
+ "oc:tooltip.upgradesign": "Allows reading text on and writing text to signs.",
+ "oc:tooltip.upgradesolargenerator": "Can be used to generate energy from sunlight on the go. Requires a clear line of sight to the sky above the device. Generates energy at %s%% of the speed of a Stirling Engine.",
+ "oc:tooltip.upgradetank": "This upgrade provides a tank for fluid storage for robots and drones. Without one of these, they will not be able to store fluids internally.",
+ "oc:tooltip.upgradetankcontroller": "This upgrade allows robots and drones more control in how they interact with external tanks, and allows them to transfer fluids into and out of fluid tank items in their inventory.",
+ "oc:tooltip.upgradetractorbeam": "Equips a device with extremely advanced technology, nicknamed the \"Item Magnet\". Allows the device to pick up items anywhere within 3 blocks of its location.",
+ "oc:tooltip.upgradetrading": "Allows robots and drones to trade with villagers.",
+ "oc:tooltip.waypoint": "Provides a point of reference to devices with a navigation upgrade.",
+ "oc:tooltip.wirelessnetworkcard": "Allows wireless sending of network messages in addition to normal ones. You can adjust the §fsignal strength§7 to control how far messages are sent. Higher signal strength results in higher energy consumption.",
+ "oc:tooltip.worldsensorcard": "Allows reading out information about the world, such as its gravity and whether it has a breathable atmosphere. Use results at own risk. The manufacturer takes no responsibility for bodily or material harm caused by decisions made upon the cards' outputs. We have lawyers. And money. Don't even try.",
+ "oc:tooltip.Wrench": "A hybrid of Screwdriver and Wrench, this tool is easy to learn, but hard to master.",
+ "achievement.oc.adapter": "Plug In Baby",
+ "achievement.oc.adapter.desc": "Interact with blocks from other mods and even vanilla Minecraft!",
+ "achievement.oc.assembler": "Wonderful",
+ "achievement.oc.assembler.desc": "Time to take over the world!",
+ "achievement.oc.cable": "Not a Dirty Wire",
+ "achievement.oc.cable.desc": "With patented anti-cable-spaghetti technology.",
+ "achievement.oc.capacitor": "Batteries included",
+ "achievement.oc.capacitor.desc": "You cannot stop it.",
+ "achievement.oc.card": "We Accept Cards",
+ "achievement.oc.card.desc": "For your convenience. No ulterior motive, promise.",
+ "achievement.oc.case": "In Case of Trouble",
+ "achievement.oc.case.desc": "Because cuboid towers are the best.",
+ "achievement.oc.charger": "All right, let's do this",
+ "achievement.oc.charger.desc": "Chaaaaaaaaaarg- dang, forgot the redstone signal again.",
+ "achievement.oc.chip": "All the Small Things",
+ "achievement.oc.chip.desc": "Because vacuum tubes are so yesteryear.",
+ "achievement.oc.cpu": "Overclocked",
+ "achievement.oc.cpu.desc": "Time to make good use of those computing cycles.",
+ "achievement.oc.disassembler": "Scratch That",
+ "achievement.oc.disassembler.desc": "In case one of your brilliant ideas turns out to be not that brilliant after all.",
+ "achievement.oc.diskDrive": "Roundabout",
+ "achievement.oc.diskDrive.desc": "Inferior capacity but such delicious sound.",
+ "achievement.oc.drone": "Fly Away",
+ "achievement.oc.drone.desc": "Keep calm and nuke it from orbit.",
+ "achievement.oc.eeprom": "There can be only one",
+ "achievement.oc.eeprom.desc": "Per computer, that is. For deterministic boot order, you know?",
+ "achievement.oc.floppy": "The One Ri- Disk",
+ "achievement.oc.floppy.desc": "Not to be confused with Flappy.",
+ "achievement.oc.geolyzer": "Down to Earth",
+ "achievement.oc.geolyzer.desc": "It has extraordinary qualities.",
+ "achievement.oc.graphicsCard": "LastGen",
+ "achievement.oc.graphicsCard.desc": "The way it's meant to be... uh... rendered. Yeah. That.",
+ "achievement.oc.hdd": "Hot Dog Dealer",
+ "achievement.oc.hdd.desc": "No wait, that's not what that meant. Hang on, almost got it...",
+ "achievement.oc.hologram": "Next Dimension",
+ "achievement.oc.hologram.desc": "Because 2D is boring. Or is it?",
+ "achievement.oc.keyboard": "DirtCatcher3000",
+ "achievement.oc.keyboard.desc": "It is highly recommended to resist the urge to flip them around and shake them.",
+ "achievement.oc.microcontroller": "Little Sister",
+ "achievement.oc.microcontroller.desc": "The small sibling of computers.",
+ "achievement.oc.motionSensor": "Got the Moves",
+ "achievement.oc.motionSensor.desc": "Like Steve Swagger.",
+ "achievement.oc.networkCard": "Now We're Talking!",
+ "achievement.oc.networkCard.desc": "Keep in touch with those distant relatives via transitive relations.",
+ "achievement.oc.openOS": "Boot",
+ "achievement.oc.openOS.desc": "One OS to - wait, I used that one already? Dang.",
+ "achievement.oc.powerDistributor": "Sharing is Caring",
+ "achievement.oc.powerDistributor.desc": "When you need some help balancing all that power.",
+ "achievement.oc.rack": "Dat Rack",
+ "achievement.oc.rack.desc": "I don't know what you're thinking of, I clearly meant the server rack.",
+ "achievement.oc.raid": "LFG",
+ "achievement.oc.raid.desc": "Heroic plzkthx.",
+ "achievement.oc.ram": "Random Access Memories",
+ "achievement.oc.ram.desc": "Congratulations, you're Doin' It Right.",
+ "achievement.oc.redstoneCard": "Contact",
+ "achievement.oc.redstoneCard.desc": "Time to go analog.",
+ "achievement.oc.redstoneIO": "The Outsider",
+ "achievement.oc.redstoneIO.desc": "Taking redstone signals where you want them.",
+ "achievement.oc.robot": "Beep Boop",
+ "achievement.oc.robot.desc": "EXTERMINATE!",
+ "achievement.oc.screen": "Have you tried turning it off and on again?",
+ "achievement.oc.screen.desc": "No seriously. A redstone pulse can toggle a screen's power, after all.",
+ "achievement.oc.server": "Dedicated",
+ "achievement.oc.server.desc": "Cloud services, here we come.",
+ "achievement.oc.switch": "Complex Topology",
+ "achievement.oc.switch.desc": "Avoid fragile goods due to possibility of dropped packets.",
+ "achievement.oc.tablet": "Do Not Swallow",
+ "achievement.oc.tablet.desc": "Also keep away from small children to avoid unexpected overdrawing of your credit card.",
+ "achievement.oc.transistor": "Tell Red I said \"Hi.\"",
+ "achievement.oc.transistor.desc": "Create a Transistor to get started. Then listen to the soundtrack. No need to thank me.",
+ "achievement.oc.wirelessNetworkCard": "Signals",
+ "achievement.oc.wirelessNetworkCard.desc": "Time to go where no packet has gone before.",
+ "death.attack.oc.nanomachinesOverload.1": "%s got too greedy.",
+ "death.attack.oc.nanomachinesOverload.2": "%s had a nervous breakdown.",
+ "death.attack.oc.nanomachinesOverload.3": "The nanomachines of %s went out of control.",
+ "death.attack.oc.nanomachinesHungry.1": "%s was eaten by nanomachines.",
+ "death.attack.oc.nanomachinesHungry.2": "%s didn't keep their nanomachines fed.",
+ "death.attack.oc.nanomachinesHungry.3": "%s has been digested.",
+ "nei.options.inventory.oredict": "Show OreDictionary names",
+ "nei.options.inventory.oredict.true": "True",
+ "nei.options.inventory.oredict.false": "False",
+ "nei.usage.oc.Manual": "Open Manual",
+ "option.oc.address": "Address",
+ "option.oc.componentName": "Component Name",
+ "option.oc.energy": "Energy"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/fr_FR.lang b/src/main/resources/assets/opencomputers/lang/fr_FR.lang
deleted file mode 100644
index eac2d692d2..0000000000
--- a/src/main/resources/assets/opencomputers/lang/fr_FR.lang
+++ /dev/null
@@ -1,359 +0,0 @@
-# Blocks, items, gui, containers, keybinds and tooltips only
-#
-#
-
-# Blocks
-tile.oc.accesspoint.name=Point d'accès
-tile.oc.adapter.name=Adaptateur
-tile.oc.assembler.name=Assembleur électronique
-tile.oc.cable.name=Câble
-tile.oc.capacitor.name=Capaciteur
-tile.oc.case1.name=Boitier (Niveau 1)
-tile.oc.case2.name=Boitier (Niveau 2)
-tile.oc.case3.name=Boitier (Niveau 3)
-tile.oc.casecreative.name=Boitier (Créatif)
-tile.oc.chameliumblock.name=Bloc de Chamélium
-tile.oc.charger.name=Chargeur
-tile.oc.disassembler.name=Désassembleur
-tile.oc.diskdrive.name=Lecteur de disquettes
-tile.oc.endstone.name=Pierre du néant
-tile.oc.geolyzer.name=Géoliseur
-tile.oc.hologram1.name=Projecteur d'hologramme (Niveau 1)
-tile.oc.hologram2.name=Projecteur d'hologramme (Niveau 2)
-tile.oc.keyboard.name=Clavier
-tile.oc.microcontroller.name=Micro-contrôleur
-tile.oc.motionsensor.name=Détecteur de mouvement
-tile.oc.netsplitter.name=Répartiteur réseau
-tile.oc.powerconverter.name=Convertisseur énergétique
-tile.oc.powerdistributor.name=Distributeur énergétique
-tile.oc.print.name=Impression 3D
-tile.oc.printer.name=Imprimante 3D
-tile.oc.raid.name=Raid
-tile.oc.redstone.name=Redstone E/S
-tile.oc.relay.name=Relai
-tile.oc.robot.name=Robot
-tile.oc.robotafterimage.name=Robot
-tile.oc.screen1.name=Ecran (Niveau 1)
-tile.oc.screen2.name=Ecran (Niveau 2)
-tile.oc.screen3.name=Ecran (Niveau 3)
-tile.oc.rack.name=Support de serveur
-tile.oc.switch.name=Routeur
-tile.oc.transposer.name=Transposeur
-tile.oc.waypoint.name=Point de passage
-
-# Items
-item.oc.abstractbuscard.name=Carte de bus abstraite
-item.oc.acid.name=Grog
-item.oc.alu.name=Unité de Logique Arithmétique (ULA)
-item.oc.analyzer.name=Analyseur
-item.oc.apu0.name=Unité de Traitement Accélérée (UTA) (Niveau 1)
-item.oc.apu1.name=Unité de Traitement Accélérée (UTA) (Niveau 2)
-item.oc.apu2.name=Unité de Traitement Accélérée (UTA) (Créatif)
-item.oc.arrowkeys.name=Touches directionnelles
-item.oc.buttongroup.name=Groupe de boutons
-item.oc.cardbase.name=Base de carte
-item.oc.chamelium.name=Chamélium
-item.oc.circuitboard.name=Plaque de circuit imprimé
-item.oc.componentbus0.name=Bus des composants (Niveau 1)
-item.oc.componentbus1.name=Bus des composants (Niveau 2)
-item.oc.componentbus2.name=Bus des composants (Niveau 3)
-item.oc.controlunit.name=Unité de contrôle (UC)
-item.oc.cpu0.name=Processeur (Niveau 1)
-item.oc.cpu1.name=Processeur (Niveau 2)
-item.oc.cpu2.name=Processeur (Niveau 3)
-item.oc.cuttingwire.name=Fil de coupe
-item.oc.debugcard.name=Carte de débogueur
-item.oc.debugger.name=Débogueur réseau
-item.oc.disk.name=Disque
-item.oc.drone.name=Drone
-item.oc.dronecase0.name=Boitier de drone (Niveau 1)
-item.oc.dronecase1.name=Boitier de drone (Niveau 2)
-item.oc.dronecase3.name=Boitier de drone (Créatif)
-item.oc.eeprom.name=EEPROM
-item.oc.floppydisk.name=Disquette
-item.oc.graphicscard0.name=Carte graphique (Niveau 1)
-item.oc.graphicscard1.name=Carte graphique (Niveau 2)
-item.oc.graphicscard2.name=Carte graphique (Niveau 3)
-item.oc.harddiskdrive0.name=Disque dur (Niveau 1)
-item.oc.harddiskdrive1.name=Disque dur (Niveau 2)
-item.oc.harddiskdrive2.name=Disque dur (Niveau 3)
-item.oc.hoverboots.name=Bottes de vol plané
-item.oc.inkcartridge.name=Cartouche d'encre
-item.oc.inkcartridgeempty.name=Cartouche d'encre (Vide)
-item.oc.internetcard.name=Carte internet
-item.oc.interweb.name=Interweb
-item.oc.ironnugget.name=Pépite de fer
-item.oc.linkedcard.name=Carte liée
-item.oc.manual.name=Manuel d'OpenComputers
-item.oc.memory0.name=Mémoire (Niveau 1)
-item.oc.memory1.name=Mémoire (Niveau 1.5)
-item.oc.memory2.name=Mémoire (Niveau 2)
-item.oc.memory3.name=Mémoire (Niveau 2.5)
-item.oc.memory4.name=Mémoire (Niveau 3)
-item.oc.memory5.name=Mémoire (Niveau 3.5)
-item.oc.microchip0.name=Puce électronique (Niveau 1)
-item.oc.microchip1.name=Puce électronique (Niveau 2)
-item.oc.microchip2.name=Puce électronique (Niveau 3)
-item.oc.microcontrollercase0.name=Boitier de microcontrôleur (Niveau 1)
-item.oc.microcontrollercase1.name=Boitier de microcontrôleur (Niveau 2)
-item.oc.microcontrollercase3.name=Boitier de microcontrôleur (Créatif)
-item.oc.networkcard.name=Carte réseau
-item.oc.numpad.name=Pavé numérique
-item.oc.present.name=Un petit quelque chose...
-item.oc.printedcircuitboard.name=Circuit imprimé
-item.oc.rawcircuitboard.name=Plaque de circuit imprimé brute
-item.oc.redstonecard0.name=Carte de Redstone (Niveau 1)
-item.oc.redstonecard1.name=Carte de Redstone (Niveau 2)
-item.oc.server0.name=Serveur (Niveau 1)
-item.oc.server1.name=Serveur (Niveau 2)
-item.oc.server2.name=Serveur (Niveau 3)
-item.oc.server3.name=Serveur (Créatif)
-item.oc.tablet.name=Tablette
-item.oc.tabletcase.name=Boitier de tablette (Niveau 1)
-item.oc.tabletcase.name=Boitier de tablette (Niveau 2)
-item.oc.tabletcase.name=Boitier de tablette (Créatif)
-item.oc.terminal.name=Terminal à distance
-item.oc.texturepicker.name=Ramasseur de texture
-item.oc.transistor.name=Transistor
-item.oc.upgradeangel.name=Amélioration ange
-item.oc.upgradebattery0.name=Amélioration batterie (Niveau 1)
-item.oc.upgradebattery1.name=Amélioration batterie (Niveau 2)
-item.oc.upgradebattery2.name=Amélioration batterie (Niveau 3)
-item.oc.upgradechunkloader.name=Amélioration chargement de chunk
-item.oc.upgradecontainercard0.name=Conteneur de carte (Niveau 1)
-item.oc.upgradecontainercard1.name=Conteneur de carte (Niveau 2)
-item.oc.upgradecontainercard2.name=Conteneur de carte (Niveau 3)
-item.oc.upgradecontainerupgrade0.name=Amélioration de conteneur (Niveau 1)
-item.oc.upgradecontainerupgrade1.name=Amélioration de conteneur (Niveau 2)
-item.oc.upgradecontainerupgrade2.name=Amélioration de conteneur (Niveau 3)
-item.oc.upgradecrafting.name=Amélioration d'artisanat
-item.oc.upgradedatabase0.name=Amélioration de base de données (Niveau 1)
-item.oc.upgradedatabase1.name=Amélioration de base de données (Niveau 2)
-item.oc.upgradedatabase2.name=Amélioration de base de données (Niveau 3)
-item.oc.upgradeexperience.name=Amélioration d'expérience
-item.oc.upgradegenerator.name=Amélioration de générateur
-item.oc.upgradehover0.name=Amélioration de vol plané (Niveau 1)
-item.oc.upgradehover1.name=Amélioration de vol plané (Niveau 2)
-item.oc.upgradeinventory.name=Amélioration d'inventaire
-item.oc.upgradeinventorycontroller.name=Amélioration du contrôleur d'inventaire
-item.oc.upgradeleash.name=Amélioration de laisse
-item.oc.upgradenavigation.name=Amélioration de navigation
-item.oc.upgradepiston.name=Amélioration de piston
-item.oc.upgradesign.name=Amélioration de panneau d'E/S
-item.oc.upgradesolargenerator.name=Amélioration du générateur solaire
-item.oc.upgradetank.name=Amélioration de réservoir
-item.oc.upgradetankcontroller.name=Amélioration du contrôleur de réservoir
-item.oc.upgradetractorbeam.name=Amélioration du rayon tracteur
-item.oc.wirelessnetworkcard0.name=Carte de réseau sans-fils (Niveau 1)
-item.oc.wirelessnetworkcard1.name=Carte de réseau sans-fils (Niveau 2)
-item.oc.worldsensorcard.name=Carte de capteur du monde
-item.oc.wrench.name=Crisseur
-
-# Entities
-entity.oc.Drone.name=Drone
-
-# GUI
-oc:gui.Analyzer.Address=§6Addresse§f: %s
-oc:gui.Analyzer.AddressCopied=Adresse copiée dans le presse-papier.
-oc:gui.Analyzer.ChargerSpeed=§6Vitesse de charge§f: %s
-oc:gui.Analyzer.ComponentName=§6Nom du composant§f: %s
-oc:gui.Analyzer.Components=§6Nombre de composants connectés§f: %s
-oc:gui.Analyzer.LastError=§6Dernière erreur§f: %s
-oc:gui.Analyzer.RobotName=§6Nom§f: %s
-oc:gui.Analyzer.RobotOwner=§6Propriétaire§f: %s
-oc:gui.Analyzer.RobotXp=§6Expérience§f: %s
-oc:gui.Analyzer.StoredEnergy=§6Energie stockée§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Energie totale§f: %s
-oc:gui.Analyzer.Users=§6Utilisateurs§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Force du signal§f: %s
-oc:gui.Assembler.Collect=Collectez la sortie
-oc:gui.Assembler.Complexity=Complexité: %s/%s
-oc:gui.Assembler.InsertCase=Insérez une partie de base
-oc:gui.Assembler.InsertCPU=Insérez une UCP
-oc:gui.Assembler.InsertRAM=Insérez un peu de mémoire
-oc:gui.Assembler.Progress=Progression: %s%% (%s)
-oc:gui.Assembler.Run=Assemble
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=Carte graphique
-oc:gui.Assembler.Warning.Inventory=Amélioration d'inventaire
-oc:gui.Assembler.Warning.Keyboard=Clavier
-oc:gui.Assembler.Warning.OS=Moyen de démarrage
-oc:gui.Assembler.Warning.Screen=Ecran
-oc:gui.Assembler.Warnings=§eALERTE§7: Les composants recommandés sont manquant.
-oc:gui.Chat.NewVersion=une nouvelle version est disponible: %s
-oc:gui.Chat.TextureName=§7Le nom de la texture est §a%s§f.
-oc:gui.Chat.WarningClassTransformer=Il y a §cerrors§f lancement dans le transformeur de classe. Veuillez vérifier ceci, en même temps que votre fichier log (plein) FML §alatest.log§f/§afml-server-latest.log§f, Merci !
-oc:gui.Chat.WarningFingerprint=§cALERTE§f - Disparité d'empreinte digitale! Attendu '§a%s§f' mais eu '§e%s§f'. À moins que vous ne soyez un modder et que vous exécutiez la version deobfuscated du mod, Il est §lfortement§f recommendé de re-télécharger OpenComputers, parce que le JAR que vous utilisez peut avoir été falsifié.
-oc:gui.Chat.WarningLink=Impossible d'ouvrir le lien : %s
-oc:gui.Chat.WarningLuaFallback=Les bibliothèques natives Lua ne sont pas disponibles, les ordinateurs ne pourront pas persister en leur état. Ils réamorceront sur la recharge des chunks.
-oc:gui.Chat.WarningProjectRed=Vous utilisez une version de Project: Red qui est incompatible avec OpenComputers. Essayez de mettre à jour votre version de Project: Red.
-oc:gui.Chat.WarningRecipes=il y a des erreurs au lancement de recettes. Certains éléments doivent être infabricables. Veuillez vérifier votre fichier log pour plus d'information.
-oc:gui.Chat.WarningSimpleComponent=Un ajout (le votre ?) utilisant l'interface §aComposant Simple§f produit §equelquechose de mauvais§f. Le composant logique ne peut être inséré. Veuillez vérifier votre fichier log pour plus d'information.
-oc:gui.Error.ComponentOverflow=Beaucoup trop de composants connectés à l'ordinateur.
-oc:gui.Error.InternalError=Erreur interne, Veuillez lire le fichier log. Ceci est probablement une erreur.
-oc:gui.Error.NoCPU=Pas d'UCP installé dans cet ordinateur.
-oc:gui.Error.NoEnergy=Pas assez d'énergie.
-oc:gui.Error.NoRAM=pas de mémoire installée dans cet ordinateur.
-oc:gui.Error.OutOfMemory=Mémoire saturée.
-oc:gui.Manual.Blocks=Blocs d'OpenComputers
-oc:gui.Manual.Home=Accueil
-oc:gui.Manual.Items=Éléments d'OpenComputers
-oc:gui.Manual.Warning.BlockMissing=Bloc manquant.
-oc:gui.Manual.Warning.ImageMissing=Image manquante.
-oc:gui.Manual.Warning.ItemMissing=Élément manquant.
-oc:gui.Manual.Warning.OreDictMissing=Entrée au dictionnaire de minerai manquante.
-oc:gui.Raid.Warning=§4L'ajout d'un disque le nettoie.[nl] L'enlèvement d'un disque nettoie le raid.
-oc:gui.Robot.Power=Énergie
-oc:gui.Robot.TurnOff=Éteindre
-oc:gui.Robot.TurnOn=Allumer
-oc:gui.Rack.None=Aucun
-oc:gui.Rack.Back=Arrière
-oc:gui.Rack.Bottom=Bas
-oc:gui.Rack.Left=Gauche
-oc:gui.Rack.Right=Droite
-oc:gui.Rack.Top=Haut
-oc:gui.Switch.TransferRate=Vitesse du cycle
-oc:gui.Switch.PacketsPerCycle=paquets / cycle
-oc:gui.Switch.QueueSize=Taille de la file
-oc:gui.Terminal.InvalidKey=Clef invalide, très probablement qu'un autre terminal a dû nécessité le serveur.
-oc:gui.Terminal.OutOfRange=Pas de signal.
-
-# Containers
-oc:container.accesspoint=Point d'accès
-oc:container.adapter=Adapteur
-oc:container.case=Ordinateur
-oc:container.charger=Chargeur
-oc:container.disassembler=Désassembleur
-oc:container.diskdrive=Lecteur disque
-oc:container.printer=Imprimante
-oc:container.raid=Raid
-oc:container.server=Serveur
-oc:container.rack=Support de serveur
-oc:container.switch=Routeur
-oc:container.tabletwrapper=Tablette
-
-# Keybinds
-key.materialCosts=Montrer les coût en matériaux
-key.clipboardPaste=Coller le presse-papier
-
-# Item / Block Tooltips
-oc:tooltip.accesspoint=Fonctionne comme un routeur, de plus il recois les paquets sans-fil et il transmet les paquets filaires au réseau sans-fil.
-oc:tooltip.abstractbuscard=Il permet d'interagir avec le bus abstait de §fStargateTech 2§7 lors de l'envoi et de la reception de paquets LIP.
-oc:tooltip.acid=Un produit semi-liquide très toxique, uniquement bu par certains pirates. Grâce à ses propriétés corrosives, il est très utile à la gravure de circuits imprimés.
-oc:tooltip.adapter=Utilisé pour contrôler des blocs n'étant pas des composants d'ordinateurs, comme des blocs Vanilla ou d'autres mods.
-oc:tooltip.alu=Ajoute des nombres pour que vous n'ayez pas à le faire. C'est peut-être mieux comme ça.
-oc:tooltip.analyzer=Utilisé pour afficher des informations sur des blocs, comme leur §faddresse§7 et leur §fnom de composant§7.[nl] Affiche aussi les erreurs en cas de crash d'un ordinateur.
-oc:tooltip.apu=Ceci est une UTC avec une UTG intégrée (ou UTI), lorsque vous avez juste besoin d'un emplacement de carte supplémentaire.[nl] Composants supportés : §f%s§7[nl] Résolution maximum: §f%sx%s§7[nl] profondeur de couleur maxi: §f%s§7[nl] Opérations/tic: §f%s§7
-oc:tooltip.assembler=Il permet de construire des robots et d'autres dispositifs d'un certain nombre de pièces informatiques différentes.
-oc:tooltip.cable=Un moyen peu coûteux pour relier les ordinateurs entre eux.
-oc:tooltip.capacitor=Stocke l'énergie pour une utilisation ultérieure. Peut être chargé et déchargé très rapidement.
-oc:tooltip.cardbase=Comme son nom l'indique, c'est le bloc de construction basique pour toutes les cartes.
-oc:tooltip.case=La tour est le bloc principal de l'ordinateur, et héberge ses §fcartes§7, sa §fMémoire RAM§7 et ses §fdisques durs§7.[nl] Emplacements: §f%s§7
-oc:tooltip.chamelium=Matière première pour impression 3D. Ne pas avaler : Peut mener à la cécité et au manque de présence provisoire.
-oc:tooltip.chameliumblock=Joli et propre. Pratique pour formes teintées dans les impressions 3D, ou juste pour avoir un bloc propre, coloré, pour décorer votre base fantaisiste avec.
-oc:tooltip.charger=Transfère l'énergie depuis des capaciteurs pour les robots adjacents. La puissance du transfert dépends du §fsignal de redstone§7, ou une absence de signal ne charge pas les robots, et un signal maximum charge les robots le plus vite possible.
-oc:tooltip.circuitboard=Hé ben, on y arrive. Peut être gravé pour obtenir un circuit imprimé.
-oc:tooltip.controlunit=C'est une unité qui... controle... des trucs. On en a besoin pour faire un processeur. Donc, ouais, super important.
-oc:tooltip.componentbus=Cette extention autorise aux serveurs de communiquer avec plus composants en même temps, Semblable à ce que les UCP font.[nl] Composants supportés : §f%s§7
-oc:tooltip.cpu=Un composant essentiel pour tout ordinateur. La fréquence d'horloge est un peu douteuse, mais, vous vous attendiez à quoi avec un cadran solaire de poche ?
-oc:tooltip.cpu.Architecture=Architecture: §f%s§7
-oc:tooltip.cuttingwire=Utilisé pour couper des blocs d'argile en plaque de circuit imprimé. Se casse après utilisation, ce qui rends cet outil le moins efficace jamais utilisé.
-oc:tooltip.debugcard=Element en mode créatif, il autorise la manipulation du monde pour faciliter les tests. Utilisation à votre propre péril.
-oc:tooltip.debugger=Peut être utilisé pour sortir les information de débogue sur la grille réseau interne de OC. A utiliser seulement si instruit par un dev.
-oc:tooltip.disassembler=Sépare les éléments dans leur composants d'origine. §lAttention§7: les éléments ainsi récupérés ont %s%% de chance de ce briser dans le processus !
-oc:tooltip.disk=Moyen primitif qui peut être utilisé pour faire des appareils de stockage persistants.
-oc:tooltip.diskdrive.CC=Les disquettes ComputerCraft sont §asupportées§7.
-oc:tooltip.diskdrive=Permet de lire et d"écrire des disquettes. Peut être installé dans les robots pour permettre d'insérer des disquettes plus tard.
-oc:tooltip.drone=Les drones sont de légère unité de reconnaissance rapide avec un espace de chargement limité.
-oc:tooltip.dronecase=Ce boitier est utilisé pour construire des Drones dans l'assembleur. Il a des emplacement pour une petite quantité de composant et fournit la lévitation en pierre de néant alimentée.
-oc:tooltip.eeprom=Petit, stockage programmable qui contient le BIOS que les ordinateurs utilisent pour démarrer.
-oc:tooltip.fakeendstone=Presque aussi bon que la chose réelle, imite même sa flottabilité !
-oc:tooltip.geolyzer=Permet de scanner la dureté des blocs des environs. Ces informations peuvent être utiles pour produire un hologramme de la zone ou pour détecter les minerais.
-oc:tooltip.graphicscard=Utilisé pour changer ce qui est affiché sur écran.[nl] Résolution maximum: §f%sx%s§7[nl] Couleurs maximales: §f%s§7[nl] Operations/tick: §f%s§7
-oc:tooltip.hoverboots=Sautez plus haut, tombez plus bas, marchez mieux. Ceci et plus, avec les nouvelles Bottes de vol plané (TM).
-oc:tooltip.inkcartridge=Utilisé pour remplir d'encre les imprimantes 3D. Pour des raisons mystérieuses, elle ne doit pas rester dans l'imprimante.
-oc:tooltip.inkcartridgeempty=Cette cartouche d'encre a été vidé totalement. Remplissez la avec des couleurs. Ou jetez la. Voyez comme je m'en soucie.
-oc:tooltip.internetcard=Cette carte permet de faire des requêtes HTTP et utiliser de véritable TCP sockets.
-oc:tooltip.interweb=Félicitation, vous avez gagné un (1) interweb. Vous pouvez y connecter en utilisant une carte internet. Prenez garde : n'alimentez pas les trolls.
-oc:tooltip.ironnugget=Une pépite de fer. D'où son nom.
-oc:tooltip.keyboard=Peut être attaché à un écran pour permettre la saisie.
-oc:tooltip.hologram0=Un affichage volumétrique qui peut être contrôlé par des ordinateurs pour montrer des structures de voxel arbitraires.[nl] Résolution : §f48x32x48§7 [nl] Echelle maxi : §f3x§7 [nl] Colorimétrie : §fMonochrome§7
-oc:tooltip.hologram1=Un affichage volumétrique qui peut être contrôlé par des ordinateurs pour montrer des structures de voxel arbitraires.[nl] Résolution : §f48x32x48§7 [nl] Echelle maxi : §f4x§7 [nl] Colorimétrie : §fTricolore§7
-oc:tooltip.linkedcard=Elles sont fabriqué par paire et ne peuvent communiquer qu'avec leur Carte partenaire. Cependant, elles peuvent communiquer à travers n'importe quelle distance et même à travers les dimensions. L'énergie exigée pour envoyer un message est assez haute malgès tout.
-oc:tooltip.linkedcard_channel=§8Canal : %s§7
-oc:tooltip.manual=Toutes les informations vous pourriez probablement avoir besoin sur OpenComputers. Et plus. Au prix incroyablement bas de... §oveuillez appuyer sur R pour continuer§7.
-oc:tooltip.materialcosts=Prend [§f%s§7] pour les coûts des matériaux.
-oc:tooltip.materials=Materiaux :
-oc:tooltip.memory=Requis pour faire fonctionner les ordinateurs. Plus vous en avez, plus complexes les programmes seront utilisables.
-oc:tooltip.microchip=La puce anciennement circuit intégré. J'ai aucune idée du comment ça marche avec la redstone, mais ça marche.
-oc:tooltip.microcontroller=Les microcontrôleurs sont des ordinateurs résumés à l'essentiel. Ils sont destinés pour s'occuper de tâches très spécifiques, dirigant seulement l'unique programme que lui donne l'EEPROM qu'il intègre.
-oc:tooltip.microcontrollercase=Composant de base pour construire des microcontrôleurs. Placez-le dans un assembleur pour ajouter de nouveaux composants et assemblez un microcontrôleur.
-oc:tooltip.motionsensor=Peut détecter le mouvement d'êtres vivants à proximité. Demande une ligne de vue dégagée.
-oc:tooltip.networkcard=Permet à des ordinateurs distants de communiquer en s'envoyant des messages.
-oc:tooltip.poweracceptor=Vitesse de convertion d'énergie: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fBuildCraft en MJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fCharges de Factorization§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fIndustrialCraft² en EU§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fMekanism en Joules§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fThermal Expansion en RF§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fResonant Engine en Coulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=Convertis l'énergie d'autres mods en l'énergie requise pour faire fonctionner les ordinateurs.
-oc:tooltip.powerdistributor=Distribue l'énergie dans plusieurs réseaux. Utile pour partager cette énergie depuis un convertisseur vers différents sous-réseaux qui doivent rester séparés.
-oc:tooltip.present=... pour vos ennuis. Ouvrez ce cadeau pour une chance de recevoir quelques éléments d'OpenCompucters §kpsorti du chapeaut§7![nl]§8 quand c'est le bon momment de recevoir un cadeau.§7
-oc:tooltip.print.BeaconBase=§8Fonctionne comme une base de balise.
-oc:tooltip.print.LightValue=§8Lumière émise : %s.
-oc:tooltip.print.RedstoneLevel=§8Sortie Redstone : %s.
-oc:tooltip.printedcircuitboard=Le composant basique pour les cartes, la mémoire, etc.
-oc:tooltip.raid=Permet de combiner trois disques durs dans un plus grand système de fichiers qui pourra être utilisé par tous les ordinateurs connectés.
-oc:tooltip.rawcircuitboard=Peut être durci dans n'importe quel four.
-oc:tooltip.redstone=Permet de recevoir et d'émettre des signaux de redstone autour du bloc. Contrôlable par n'importe quel ordinateur connecté à ce bloc. En gros, une carte redstone externe.
-oc:tooltip.redstonecard.ProjectRed=§fProjectRed§7 est §asupporté7.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 est §asupporté§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 est §asupporté§7.
-oc:tooltip.redstonecard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 est §asupporté§7.
-oc:tooltip.redstonecard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 est §asupporté§7.
-oc:tooltip.redstonecard=Permet la réception et l'émission de signaux de redstone autour de l'ordinateur ou du robot.
-oc:tooltip.robot=Contrairement aux ordinateurs, les robots peuvent se déplacer et intéragir avec le monde comme un joueur le fait. Ils ne peuvent §opas§r§7 intéragir avec des composants d'ordinateur extérieurs, ceci dit !
-# the underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fNiveau§7: §a%s§7.
-oc:tooltip.robot_storedenergy=§fEnergie stockée§7: §a%s§7.
-oc:tooltip.screen=Affiche du texte, contrôlé par une Carte graphique dans un Boitier.[nl] Résolution maximum: §f%sx%s§7[nl] Couleurs maximales: §f%s§7
-oc:tooltip.server=Ceci est un serveur, il y en a beaucoup comme ca, mais celui-ci peut être amélioré avec des composants bien plus qu'un ordinateur peut l'être. Il peut être placé dans un support de serveur.
-oc:tooltip.server.Components=Composants installés :
-oc:tooltip.rack=Permet l'installation jusqu'à quatre serveurs.
-oc:tooltip.switch=Permet de connecter différents réseaux entre eux. Seulement des messages réseau seront transmis, les composants ne seront pas visibles via celui ci. A utiliser pour séparer des réseaux tout en leur permettant de communiquer entre eux, grâce aux Cartes réseau, par exemple.
-oc:tooltip.tablet=Une tablette, pour une Lua fraiche en route. Peut être forcé à l'arrêt par un accroupi-clique droit.
-oc:tooltip.tabletcase=Boitier de tablettes de base. Placez-le dans l'assembleur pour ajouter des composants et créez une tablette.
-oc:tooltip.terminal=Permet de contrôler un serveur à distance, tant que vous êtes à portée de lui. Fonctionne comme un écran-clavier portable. Maj-clique droit un serveur du support pour le lier au terminal.
-oc:tooltip.tier=§8Niv. %s
-oc:tooltip.toolong=Maintenez la touche [§f%s§7] pour plus d'informations.
-oc:tooltip.transistor=Un élément basique constituant la plupart des pièces d'un ordinateur. Il est un peu tordu, mais il fait son boulot.
-oc:tooltip.upgradeangel=Permet aux robots pour placer des blocs d'air mince, même s'il n'y a aucun point de référence.
-oc:tooltip.upgradebattery=Augmentez la quantité d'énergie qu'un robot peut stocker, le permettant de marcher plus longtemps sans devoir être rechargé. [nl] Capacité : §f%s§7
-oc:tooltip.upgradechunkloader=Si un robot se déplace dans une forêt sans personne à proximité, se déplace-il vraiment ? Cette amélioration s'assure qu'il le fait. Elle garde le chunk du robot chargé, mais consomme continuellement de l'énergie lors qu'il est actif.
-oc:tooltip.upgradecontainercard=Cette amélioration de conteneur permet l'installation ou le retrait dynamique d'une carte du robot assemblé. [nl] Niv. Maximum : §f%s§7
-oc:tooltip.upgradecontainerupgrade=Cette amélioration de conteneur permet l'installation ou le retrait dynamique d'une amélioration du robot assemblé. [nl] Niv. Maximum : §f%s§7
-oc:tooltip.upgradecrafting=Permet aux robots d'utiliser le coin en haut à gauche de leur inventaire comme table d'artisanat. Vous devez respecter la position des objets comme pour un artisanat normal.
-oc:tooltip.upgradedatabase=Cette amélioration permet de stoquer les information de pile d'éléments pour une utilisation future d'autres composants. Notez que ceci doit être configuré à la main.[nl] Entrées supportées : §f%s§7
-oc:tooltip.upgradeexperience=Cette amélioration permet aux robots d'accumuler de l'experience en exécutant diverses opérations. Plus ils gagnent d'expérience, plus ils peuvent stocker de l'énergie, miner plus rapidement et utiliser les outils plus efficacement.
-oc:tooltip.upgradegenerator=Utilisé pour générer de l'énergie directement sur un robot, indépendament d'un chargeur. Consume du comburant (ex: charbon) pour une génération sur la durée, en fonction de l'efficacité du combustible. [nl] §fEfficacité§7: §a%s%%§7
-oc:tooltip.upgradeinventory=Cette amélioration donne un espace d'inventaire au robot. Sans l'une d'elles, les robots ne seraient pas capable de stocker des éléments en interne.
-oc:tooltip.upgradeinventorycontroller=Cette amélioration permet au robot plus de contrôle sur ses interactions avec les inventaires externes, et leur permet d'échanger leurs outils avec un élément de son inventaire.
-oc:tooltip.upgradenavigation=Utilisé pour déterminer la position et l'orientation d'un robot. Cette position est relative au centre de la zone (affichée sur une carte) ou l'amélioration a été créée.
-oc:tooltip.upgradepiston=Cette amélioration est très rentre-dedans. Elle permet de déplacer des blocs comme lors de l'utilisation d'un piston. malgré tout, cela §lne déplace pas§7 les entités.
-oc:tooltip.upgradesign=Permets de lire et d'écrire sur des panneaux.
-oc:tooltip.upgradesolargenerator=Utilisé pour générer de l'énergie directement sur un robot, indépendament d'un chargeur, via le soleil. Aucun bloc ne doit se trouver au-dessus du robot pour que cette génération fonctionne. Génère de l'énergie à %s%% de la vitesse d'un moteur stirling (BuildCraft).
-oc:tooltip.upgradetank=Cette amélioration donne un réservoire de fluides au robot. Sans l'une d'elles, les robots ne seraient pas capable de stocker des fluides en interne.
-oc:tooltip.upgradetankcontroller=Cette amélioration permet au robot plus de contrôle sur ses interactions avec les réservoirs externes, et leur permet de transférer les fluides avec un élément réservoir de fluide de son inventaire.
-oc:tooltip.upgradetractorbeam=Equipe le robot avec une technologie extrêmement avancée, surnommé "l'aimant d'éléments". Cela lui permet de prendre des éléments n'importe où 3 blocs autour de son emplacement.
-oc:tooltip.wirelessnetworkcard=Permet l'envoi de messages réseaux sans fil. Pensez à régler la §fforce du signal§7, sinon aucun paquet ne sera envoyé!
-
-# NEI Integration
-nei.options.inventory.oredict=Montrez les noms OreDictionary
-nei.options.inventory.oredict.true=Vrai
-nei.options.inventory.oredict.false=Faux
-
-# Waila Integration
-option.oc.address=Adresse
-option.oc.componentName=Nom du composant
-option.oc.energy=Énergie
diff --git a/src/main/resources/assets/opencomputers/lang/fr_fr.json b/src/main/resources/assets/opencomputers/lang/fr_fr.json
new file mode 100644
index 0000000000..a9c2966662
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/fr_fr.json
@@ -0,0 +1,340 @@
+{
+ "tile.oc.accesspoint": "Point d'accès",
+ "tile.oc.adapter": "Adaptateur",
+ "tile.oc.assembler": "Assembleur électronique",
+ "tile.oc.cable": "Câble",
+ "tile.oc.capacitor": "Capaciteur",
+ "tile.oc.case1": "Boitier (Niveau 1)",
+ "tile.oc.case2": "Boitier (Niveau 2)",
+ "tile.oc.case3": "Boitier (Niveau 3)",
+ "tile.oc.casecreative": "Boitier (Créatif)",
+ "tile.oc.chameliumblock": "Bloc de Chamélium",
+ "tile.oc.charger": "Chargeur",
+ "tile.oc.disassembler": "Désassembleur",
+ "tile.oc.diskdrive": "Lecteur de disquettes",
+ "tile.oc.endstone": "Pierre du néant",
+ "tile.oc.geolyzer": "Géoliseur",
+ "tile.oc.hologram1": "Projecteur d'hologramme (Niveau 1)",
+ "tile.oc.hologram2": "Projecteur d'hologramme (Niveau 2)",
+ "tile.oc.keyboard": "Clavier",
+ "tile.oc.microcontroller": "Micro-contrôleur",
+ "tile.oc.motionsensor": "Détecteur de mouvement",
+ "tile.oc.netsplitter": "Répartiteur réseau",
+ "tile.oc.powerconverter": "Convertisseur énergétique",
+ "tile.oc.powerdistributor": "Distributeur énergétique",
+ "tile.oc.print": "Impression 3D",
+ "tile.oc.printer": "Imprimante 3D",
+ "tile.oc.raid": "Raid",
+ "tile.oc.redstone": "Redstone E/S",
+ "tile.oc.relay": "Relai",
+ "tile.oc.robot": "Robot",
+ "tile.oc.robotafterimage": "Robot",
+ "tile.oc.screen1": "Ecran (Niveau 1)",
+ "tile.oc.screen2": "Ecran (Niveau 2)",
+ "tile.oc.screen3": "Ecran (Niveau 3)",
+ "tile.oc.rack": "Support de serveur",
+ "tile.oc.switch": "Routeur",
+ "tile.oc.transposer": "Transposeur",
+ "tile.oc.waypoint": "Point de passage",
+ "item.oc.abstractbuscard": "Carte de bus abstraite",
+ "item.oc.acid": "Grog",
+ "item.oc.alu": "Unité de Logique Arithmétique (ULA)",
+ "item.oc.analyzer": "Analyseur",
+ "item.oc.apu0": "Unité de Traitement Accélérée (UTA) (Niveau 1)",
+ "item.oc.apu1": "Unité de Traitement Accélérée (UTA) (Niveau 2)",
+ "item.oc.apu2": "Unité de Traitement Accélérée (UTA) (Créatif)",
+ "item.oc.arrowkeys": "Touches directionnelles",
+ "item.oc.buttongroup": "Groupe de boutons",
+ "item.oc.cardbase": "Base de carte",
+ "item.oc.chamelium": "Chamélium",
+ "item.oc.circuitboard": "Plaque de circuit imprimé",
+ "item.oc.componentbus0": "Bus des composants (Niveau 1)",
+ "item.oc.componentbus1": "Bus des composants (Niveau 2)",
+ "item.oc.componentbus2": "Bus des composants (Niveau 3)",
+ "item.oc.controlunit": "Unité de contrôle (UC)",
+ "item.oc.cpu0": "Processeur (Niveau 1)",
+ "item.oc.cpu1": "Processeur (Niveau 2)",
+ "item.oc.cpu2": "Processeur (Niveau 3)",
+ "item.oc.cuttingwire": "Fil de coupe",
+ "item.oc.debugcard": "Carte de débogueur",
+ "item.oc.debugger": "Débogueur réseau",
+ "item.oc.disk": "Disque",
+ "item.oc.drone": "Drone",
+ "item.oc.dronecase0": "Boitier de drone (Niveau 1)",
+ "item.oc.dronecase1": "Boitier de drone (Niveau 2)",
+ "item.oc.dronecase3": "Boitier de drone (Créatif)",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.floppydisk": "Disquette",
+ "item.oc.graphicscard0": "Carte graphique (Niveau 1)",
+ "item.oc.graphicscard1": "Carte graphique (Niveau 2)",
+ "item.oc.graphicscard2": "Carte graphique (Niveau 3)",
+ "item.oc.harddiskdrive0": "Disque dur (Niveau 1)",
+ "item.oc.harddiskdrive1": "Disque dur (Niveau 2)",
+ "item.oc.harddiskdrive2": "Disque dur (Niveau 3)",
+ "item.oc.hoverboots": "Bottes de vol plané",
+ "item.oc.inkcartridge": "Cartouche d'encre",
+ "item.oc.inkcartridgeempty": "Cartouche d'encre (Vide)",
+ "item.oc.internetcard": "Carte internet",
+ "item.oc.interweb": "Interweb",
+ "item.oc.ironnugget": "Pépite de fer",
+ "item.oc.linkedcard": "Carte liée",
+ "item.oc.manual": "Manuel d'OpenComputers",
+ "item.oc.memory0": "Mémoire (Niveau 1)",
+ "item.oc.memory1": "Mémoire (Niveau 1.5)",
+ "item.oc.memory2": "Mémoire (Niveau 2)",
+ "item.oc.memory3": "Mémoire (Niveau 2.5)",
+ "item.oc.memory4": "Mémoire (Niveau 3)",
+ "item.oc.memory5": "Mémoire (Niveau 3.5)",
+ "item.oc.microchip0": "Puce électronique (Niveau 1)",
+ "item.oc.microchip1": "Puce électronique (Niveau 2)",
+ "item.oc.microchip2": "Puce électronique (Niveau 3)",
+ "item.oc.microcontrollercase0": "Boitier de microcontrôleur (Niveau 1)",
+ "item.oc.microcontrollercase1": "Boitier de microcontrôleur (Niveau 2)",
+ "item.oc.microcontrollercase3": "Boitier de microcontrôleur (Créatif)",
+ "item.oc.networkcard": "Carte réseau",
+ "item.oc.numpad": "Pavé numérique",
+ "item.oc.present": "Un petit quelque chose...",
+ "item.oc.printedcircuitboard": "Circuit imprimé",
+ "item.oc.rawcircuitboard": "Plaque de circuit imprimé brute",
+ "item.oc.redstonecard0": "Carte de Redstone (Niveau 1)",
+ "item.oc.redstonecard1": "Carte de Redstone (Niveau 2)",
+ "item.oc.server0": "Serveur (Niveau 1)",
+ "item.oc.server1": "Serveur (Niveau 2)",
+ "item.oc.server2": "Serveur (Niveau 3)",
+ "item.oc.server3": "Serveur (Créatif)",
+ "item.oc.tablet": "Tablette",
+ "item.oc.tabletcase": "Boitier de tablette (Niveau 1)",
+ "item.oc.tabletcase": "Boitier de tablette (Niveau 2)",
+ "item.oc.tabletcase": "Boitier de tablette (Créatif)",
+ "item.oc.terminal": "Terminal à distance",
+ "item.oc.texturepicker": "Ramasseur de texture",
+ "item.oc.transistor": "Transistor",
+ "item.oc.upgradeangel": "Amélioration ange",
+ "item.oc.upgradebattery0": "Amélioration batterie (Niveau 1)",
+ "item.oc.upgradebattery1": "Amélioration batterie (Niveau 2)",
+ "item.oc.upgradebattery2": "Amélioration batterie (Niveau 3)",
+ "item.oc.upgradechunkloader": "Amélioration chargement de chunk",
+ "item.oc.upgradecontainercard0": "Conteneur de carte (Niveau 1)",
+ "item.oc.upgradecontainercard1": "Conteneur de carte (Niveau 2)",
+ "item.oc.upgradecontainercard2": "Conteneur de carte (Niveau 3)",
+ "item.oc.upgradecontainerupgrade0": "Amélioration de conteneur (Niveau 1)",
+ "item.oc.upgradecontainerupgrade1": "Amélioration de conteneur (Niveau 2)",
+ "item.oc.upgradecontainerupgrade2": "Amélioration de conteneur (Niveau 3)",
+ "item.oc.upgradecrafting": "Amélioration d'artisanat",
+ "item.oc.upgradedatabase0": "Amélioration de base de données (Niveau 1)",
+ "item.oc.upgradedatabase1": "Amélioration de base de données (Niveau 2)",
+ "item.oc.upgradedatabase2": "Amélioration de base de données (Niveau 3)",
+ "item.oc.upgradeexperience": "Amélioration d'expérience",
+ "item.oc.upgradegenerator": "Amélioration de générateur",
+ "item.oc.upgradehover0": "Amélioration de vol plané (Niveau 1)",
+ "item.oc.upgradehover1": "Amélioration de vol plané (Niveau 2)",
+ "item.oc.upgradeinventory": "Amélioration d'inventaire",
+ "item.oc.upgradeinventorycontroller": "Amélioration du contrôleur d'inventaire",
+ "item.oc.upgradeleash": "Amélioration de laisse",
+ "item.oc.upgradenavigation": "Amélioration de navigation",
+ "item.oc.upgradepiston": "Amélioration de piston",
+ "item.oc.upgradesign": "Amélioration de panneau d'E/S",
+ "item.oc.upgradesolargenerator": "Amélioration du générateur solaire",
+ "item.oc.upgradetank": "Amélioration de réservoir",
+ "item.oc.upgradetankcontroller": "Amélioration du contrôleur de réservoir",
+ "item.oc.upgradetractorbeam": "Amélioration du rayon tracteur",
+ "item.oc.wirelessnetworkcard0": "Carte de réseau sans-fils (Niveau 1)",
+ "item.oc.wirelessnetworkcard1": "Carte de réseau sans-fils (Niveau 2)",
+ "item.oc.worldsensorcard": "Carte de capteur du monde",
+ "item.oc.wrench": "Crisseur",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "Drone",
+ "oc:gui.Analyzer.Address": "§6Addresse§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Adresse copiée dans le presse-papier.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Vitesse de charge§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Nom du composant§f: %s",
+ "oc:gui.Analyzer.Components": "§6Nombre de composants connectés§f: %s",
+ "oc:gui.Analyzer.LastError": "§6Dernière erreur§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Nom§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Propriétaire§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Expérience§f: %s",
+ "oc:gui.Analyzer.StoredEnergy": "§6Energie stockée§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Energie totale§f: %s",
+ "oc:gui.Analyzer.Users": "§6Utilisateurs§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Force du signal§f: %s",
+ "oc:gui.Assembler.Collect": "Collectez la sortie",
+ "oc:gui.Assembler.Complexity": "Complexité: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Insérez une partie de base",
+ "oc:gui.Assembler.InsertCPU": "Insérez une UCP",
+ "oc:gui.Assembler.InsertRAM": "Insérez un peu de mémoire",
+ "oc:gui.Assembler.Progress": "Progression: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Assemble",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Carte graphique",
+ "oc:gui.Assembler.Warning.Inventory": "Amélioration d'inventaire",
+ "oc:gui.Assembler.Warning.Keyboard": "Clavier",
+ "oc:gui.Assembler.Warning.OS": "Moyen de démarrage",
+ "oc:gui.Assembler.Warning.Screen": "Ecran",
+ "oc:gui.Assembler.Warnings": "§eALERTE§7: Les composants recommandés sont manquant.",
+ "oc:gui.Chat.NewVersion": "une nouvelle version est disponible: %s",
+ "oc:gui.Chat.TextureName": "§7Le nom de la texture est §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "Il y a §cerrors§f lancement dans le transformeur de classe. Veuillez vérifier ceci, en même temps que votre fichier log (plein) FML §alatest.log§f/§afml-server-latest.log§f, Merci !",
+ "oc:gui.Chat.WarningFingerprint": "§cALERTE§f - Disparité d'empreinte digitale! Attendu '§a%s§f' mais eu '§e%s§f'. À moins que vous ne soyez un modder et que vous exécutiez la version deobfuscated du mod, Il est §lfortement§f recommendé de re-télécharger OpenComputers, parce que le JAR que vous utilisez peut avoir été falsifié.",
+ "oc:gui.Chat.WarningLink": "Impossible d'ouvrir le lien : %s",
+ "oc:gui.Chat.WarningLuaFallback": "Les bibliothèques natives Lua ne sont pas disponibles, les ordinateurs ne pourront pas persister en leur état. Ils réamorceront sur la recharge des chunks.",
+ "oc:gui.Chat.WarningProjectRed": "Vous utilisez une version de Project: Red qui est incompatible avec OpenComputers. Essayez de mettre à jour votre version de Project: Red.",
+ "oc:gui.Chat.WarningRecipes": "il y a des erreurs au lancement de recettes. Certains éléments doivent être infabricables. Veuillez vérifier votre fichier log pour plus d'information.",
+ "oc:gui.Error.ComponentOverflow": "Beaucoup trop de composants connectés à l'ordinateur.",
+ "oc:gui.Error.InternalError": "Erreur interne, Veuillez lire le fichier log. Ceci est probablement une erreur.",
+ "oc:gui.Error.NoCPU": "Pas d'UCP installé dans cet ordinateur.",
+ "oc:gui.Error.NoEnergy": "Pas assez d'énergie.",
+ "oc:gui.Error.NoRAM": "pas de mémoire installée dans cet ordinateur.",
+ "oc:gui.Error.OutOfMemory": "Mémoire saturée.",
+ "oc:gui.Manual.Blocks": "Blocs d'OpenComputers",
+ "oc:gui.Manual.Home": "Accueil",
+ "oc:gui.Manual.Items": "Éléments d'OpenComputers",
+ "oc:gui.Manual.Warning.BlockMissing": "Bloc manquant.",
+ "oc:gui.Manual.Warning.ImageMissing": "Image manquante.",
+ "oc:gui.Manual.Warning.ItemMissing": "Élément manquant.",
+ "oc:gui.Manual.Warning.OreDictMissing": "Entrée au dictionnaire de minerai manquante.",
+ "oc:gui.Raid.Warning": "§4L'ajout d'un disque le nettoie.\nL'enlèvement d'un disque nettoie le raid.",
+ "oc:gui.Robot.Power": "Énergie",
+ "oc:gui.Robot.TurnOff": "Éteindre",
+ "oc:gui.Robot.TurnOn": "Allumer",
+ "oc:gui.Rack.None": "Aucun",
+ "oc:gui.Rack.Back": "Arrière",
+ "oc:gui.Rack.Bottom": "Bas",
+ "oc:gui.Rack.Left": "Gauche",
+ "oc:gui.Rack.Right": "Droite",
+ "oc:gui.Rack.Top": "Haut",
+ "oc:gui.Switch.TransferRate": "Vitesse du cycle",
+ "oc:gui.Switch.PacketsPerCycle": "paquets / cycle",
+ "oc:gui.Switch.QueueSize": "Taille de la file",
+ "oc:gui.Terminal.InvalidKey": "Clef invalide, très probablement qu'un autre terminal a dû nécessité le serveur.",
+ "oc:gui.Terminal.OutOfRange": "Pas de signal.",
+ "oc:container.accesspoint": "Point d'accès",
+ "oc:container.adapter": "Adapteur",
+ "oc:container.case": "Ordinateur",
+ "oc:container.charger": "Chargeur",
+ "oc:container.disassembler": "Désassembleur",
+ "oc:container.diskdrive": "Lecteur disque",
+ "oc:container.printer": "Imprimante",
+ "oc:container.raid": "Raid",
+ "oc:container.server": "Serveur",
+ "oc:container.rack": "Support de serveur",
+ "oc:container.switch": "Routeur",
+ "oc:container.tabletwrapper": "Tablette",
+ "key.opencomputers.analyzeCopyAddress": "Copier l'adresse (Analyseur)",
+ "key.opencomputers.clipboardPaste": "Coller le presse-papier",
+ "key.opencomputers.extendedTooltip": "Afficher plus d'informations",
+ "oc:tooltip.accesspoint": "Fonctionne comme un routeur, de plus il recois les paquets sans-fil et il transmet les paquets filaires au réseau sans-fil.",
+ "oc:tooltip.abstractbuscard": "Il permet d'interagir avec le bus abstait de §fStargateTech 2§7 lors de l'envoi et de la reception de paquets LIP.",
+ "oc:tooltip.acid": "Un produit semi-liquide très toxique, uniquement bu par certains pirates. Grâce à ses propriétés corrosives, il est très utile à la gravure de circuits imprimés.",
+ "oc:tooltip.adapter": "Utilisé pour contrôler des blocs n'étant pas des composants d'ordinateurs, comme des blocs Vanilla ou d'autres mods.",
+ "oc:tooltip.alu": "Ajoute des nombres pour que vous n'ayez pas à le faire. C'est peut-être mieux comme ça.",
+ "oc:tooltip.analyzer": "Utilisé pour afficher des informations sur des blocs, comme leur §faddresse§7 et leur §fnom de composant§7.\nAffiche aussi les erreurs en cas de crash d'un ordinateur.",
+ "oc:tooltip.apu": "Ceci est une UTC avec une UTG intégrée (ou UTI), lorsque vous avez juste besoin d'un emplacement de carte supplémentaire.\nComposants supportés : §f%s§7\nRésolution maximum: §f%sx%s§7\nprofondeur de couleur maxi: §f%s§7\nOpérations/tic: §f%s§7",
+ "oc:tooltip.assembler": "Il permet de construire des robots et d'autres dispositifs d'un certain nombre de pièces informatiques différentes.",
+ "oc:tooltip.cable": "Un moyen peu coûteux pour relier les ordinateurs entre eux.",
+ "oc:tooltip.capacitor": "Stocke l'énergie pour une utilisation ultérieure. Peut être chargé et déchargé très rapidement.",
+ "oc:tooltip.cardbase": "Comme son nom l'indique, c'est le bloc de construction basique pour toutes les cartes.",
+ "oc:tooltip.case": "La tour est le bloc principal de l'ordinateur, et héberge ses §fcartes§7, sa §fMémoire RAM§7 et ses §fdisques durs§7.\nEmplacements: §f%s§7",
+ "oc:tooltip.chamelium": "Matière première pour impression 3D. Ne pas avaler : Peut mener à la cécité et au manque de présence provisoire.",
+ "oc:tooltip.chameliumblock": "Joli et propre. Pratique pour formes teintées dans les impressions 3D, ou juste pour avoir un bloc propre, coloré, pour décorer votre base fantaisiste avec.",
+ "oc:tooltip.charger": "Transfère l'énergie depuis des capaciteurs pour les robots adjacents. La puissance du transfert dépends du §fsignal de redstone§7, ou une absence de signal ne charge pas les robots, et un signal maximum charge les robots le plus vite possible.",
+ "oc:tooltip.circuitboard": "Hé ben, on y arrive. Peut être gravé pour obtenir un circuit imprimé.",
+ "oc:tooltip.controlunit": "C'est une unité qui... controle... des trucs. On en a besoin pour faire un processeur. Donc, ouais, super important.",
+ "oc:tooltip.componentbus": "Cette extention autorise aux serveurs de communiquer avec plus composants en même temps, Semblable à ce que les UCP font.\nComposants supportés : §f%s§7",
+ "oc:tooltip.cpu": "Un composant essentiel pour tout ordinateur. La fréquence d'horloge est un peu douteuse, mais, vous vous attendiez à quoi avec un cadran solaire de poche ?",
+ "oc:tooltip.cpu.Architecture": "Architecture: §f%s§7",
+ "oc:tooltip.cuttingwire": "Utilisé pour couper des blocs d'argile en plaque de circuit imprimé. Se casse après utilisation, ce qui rends cet outil le moins efficace jamais utilisé.",
+ "oc:tooltip.debugcard": "Element en mode créatif, il autorise la manipulation du monde pour faciliter les tests. Utilisation à votre propre péril.",
+ "oc:tooltip.debugger": "Peut être utilisé pour sortir les information de débogue sur la grille réseau interne de OC. A utiliser seulement si instruit par un dev.",
+ "oc:tooltip.disassembler": "Sépare les éléments dans leur composants d'origine. §lAttention§7: les éléments ainsi récupérés ont %s%% de chance de ce briser dans le processus !",
+ "oc:tooltip.disk": "Moyen primitif qui peut être utilisé pour faire des appareils de stockage persistants.",
+ "oc:tooltip.diskdrive.CC": "Les disquettes ComputerCraft sont §asupportées§7.",
+ "oc:tooltip.diskdrive": "Permet de lire et d'écrire des disquettes. Peut être installé dans les robots pour permettre d'insérer des disquettes plus tard.",
+ "oc:tooltip.drone": "Les drones sont de légère unité de reconnaissance rapide avec un espace de chargement limité.",
+ "oc:tooltip.dronecase": "Ce boitier est utilisé pour construire des Drones dans l'assembleur. Il a des emplacement pour une petite quantité de composant et fournit la lévitation en pierre de néant alimentée.",
+ "oc:tooltip.eeprom": "Petit, stockage programmable qui contient le BIOS que les ordinateurs utilisent pour démarrer.",
+ "oc:tooltip.fakeendstone": "Presque aussi bon que la chose réelle, imite même sa flottabilité !",
+ "oc:tooltip.geolyzer": "Permet de scanner la dureté des blocs des environs. Ces informations peuvent être utiles pour produire un hologramme de la zone ou pour détecter les minerais.",
+ "oc:tooltip.graphicscard": "Utilisé pour changer ce qui est affiché sur écran.\nRésolution maximum: §f%sx%s§7\nCouleurs maximales: §f%s§7\nOperations/tick: §f%s§7",
+ "oc:tooltip.hoverboots": "Sautez plus haut, tombez plus bas, marchez mieux. Ceci et plus, avec les nouvelles Bottes de vol plané (TM).",
+ "oc:tooltip.inkcartridge": "Utilisé pour remplir d'encre les imprimantes 3D. Pour des raisons mystérieuses, elle ne doit pas rester dans l'imprimante.",
+ "oc:tooltip.inkcartridgeempty": "Cette cartouche d'encre a été vidé totalement. Remplissez la avec des couleurs. Ou jetez la. Voyez comme je m'en soucie.",
+ "oc:tooltip.internetcard": "Cette carte permet de faire des requêtes HTTP et utiliser de véritable TCP sockets.",
+ "oc:tooltip.interweb": "Félicitation, vous avez gagné un (1) interweb. Vous pouvez y connecter en utilisant une carte internet. Prenez garde : n'alimentez pas les trolls.",
+ "oc:tooltip.ironnugget": "Une pépite de fer. D'où son nom.",
+ "oc:tooltip.keyboard": "Peut être attaché à un écran pour permettre la saisie.",
+ "oc:tooltip.hologram0": "Un affichage volumétrique qui peut être contrôlé par des ordinateurs pour montrer des structures de voxel arbitraires.\nRésolution : §f48x32x48§7\nEchelle maxi : §f3x§7\nColorimétrie : §fMonochrome§7",
+ "oc:tooltip.hologram1": "Un affichage volumétrique qui peut être contrôlé par des ordinateurs pour montrer des structures de voxel arbitraires.\nRésolution : §f48x32x48§7\nEchelle maxi : §f4x§7\nColorimétrie : §fTricolore§7",
+ "oc:tooltip.linkedcard": "Elles sont fabriqué par paire et ne peuvent communiquer qu'avec leur Carte partenaire. Cependant, elles peuvent communiquer à travers n'importe quelle distance et même à travers les dimensions. L'énergie exigée pour envoyer un message est assez haute malgès tout.",
+ "oc:tooltip.linkedcard_channel": "§8Canal : %s§7",
+ "oc:tooltip.manual": "Toutes les informations vous pourriez probablement avoir besoin sur OpenComputers. Et plus. Au prix incroyablement bas de... §oveuillez appuyer sur R pour continuer§7.",
+ "oc:tooltip.materialcosts": "Prend [§f%s§7] pour les coûts des matériaux.",
+ "oc:tooltip.materials": "Materiaux :",
+ "oc:tooltip.memory": "Requis pour faire fonctionner les ordinateurs. Plus vous en avez, plus complexes les programmes seront utilisables.",
+ "oc:tooltip.microchip": "La puce anciennement circuit intégré. J'ai aucune idée du comment ça marche avec la redstone, mais ça marche.",
+ "oc:tooltip.microcontroller": "Les microcontrôleurs sont des ordinateurs résumés à l'essentiel. Ils sont destinés pour s'occuper de tâches très spécifiques, dirigant seulement l'unique programme que lui donne l'EEPROM qu'il intègre.",
+ "oc:tooltip.microcontrollercase": "Composant de base pour construire des microcontrôleurs. Placez-le dans un assembleur pour ajouter de nouveaux composants et assemblez un microcontrôleur.",
+ "oc:tooltip.motionsensor": "Peut détecter le mouvement d'êtres vivants à proximité. Demande une ligne de vue dégagée.",
+ "oc:tooltip.networkcard": "Permet à des ordinateurs distants de communiquer en s'envoyant des messages.",
+ "oc:tooltip.poweracceptor": "Vitesse de convertion d'énergie: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fBuildCraft en MJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fCharges de Factorization§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fIndustrialCraft² en EU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fMekanism en Joules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fThermal Expansion en RF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fResonant Engine en Coulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Convertis l'énergie d'autres mods en l'énergie requise pour faire fonctionner les ordinateurs.",
+ "oc:tooltip.powerdistributor": "Distribue l'énergie dans plusieurs réseaux. Utile pour partager cette énergie depuis un convertisseur vers différents sous-réseaux qui doivent rester séparés.",
+ "oc:tooltip.present": "... pour vos ennuis. Ouvrez ce cadeau pour une chance de recevoir quelques éléments d'OpenCompucters §kpsorti du chapeaut§7!\n§8 quand c'est le bon momment de recevoir un cadeau.§7",
+ "oc:tooltip.print.BeaconBase": "§8Fonctionne comme une base de balise.",
+ "oc:tooltip.print.LightValue": "§8Lumière émise : %s.",
+ "oc:tooltip.print.RedstoneLevel": "§8Sortie Redstone : %s.",
+ "oc:tooltip.printedcircuitboard": "Le composant basique pour les cartes, la mémoire, etc.",
+ "oc:tooltip.raid": "Permet de combiner trois disques durs dans un plus grand système de fichiers qui pourra être utilisé par tous les ordinateurs connectés.",
+ "oc:tooltip.rawcircuitboard": "Peut être durci dans n'importe quel four.",
+ "oc:tooltip.redstone": "Permet de recevoir et d'émettre des signaux de redstone autour du bloc. Contrôlable par n'importe quel ordinateur connecté à ce bloc. En gros, une carte redstone externe.",
+ "oc:tooltip.redstonecard.ProjectRed": "§fProjectRed§7 est §asupporté7.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 est §asupporté§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 est §asupporté§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "§fWireless Redstone (ChickenBones)§7 est §asupporté§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "§fWireless Redstone (SlimeVoid)§7 est §asupporté§7.",
+ "oc:tooltip.redstonecard": "Permet la réception et l'émission de signaux de redstone autour de l'ordinateur ou du robot.",
+ "oc:tooltip.robot": "Contrairement aux ordinateurs, les robots peuvent se déplacer et intéragir avec le monde comme un joueur le fait. Ils ne peuvent §opas§r§7 intéragir avec des composants d'ordinateur extérieurs, ceci dit !",
+ "oc:tooltip.robot_level": "§fNiveau§7: §a%s§7.",
+ "oc:tooltip.robot_storedenergy": "§fEnergie stockée§7: §a%s§7.",
+ "oc:tooltip.screen": "Affiche du texte, contrôlé par une Carte graphique dans un Boitier.\nRésolution maximum: §f%sx%s§7\nCouleurs maximales: §f%s§7",
+ "oc:tooltip.server": "Ceci est un serveur, il y en a beaucoup comme ca, mais celui-ci peut être amélioré avec des composants bien plus qu'un ordinateur peut l'être. Il peut être placé dans un support de serveur.",
+ "oc:tooltip.server.Components": "Composants installés :",
+ "oc:tooltip.rack": "Permet l'installation jusqu'à quatre serveurs.",
+ "oc:tooltip.switch": "Permet de connecter différents réseaux entre eux. Seulement des messages réseau seront transmis, les composants ne seront pas visibles via celui ci. A utiliser pour séparer des réseaux tout en leur permettant de communiquer entre eux, grâce aux Cartes réseau, par exemple.",
+ "oc:tooltip.tablet": "Une tablette, pour une Lua fraiche en route. Peut être forcé à l'arrêt par un accroupi-clique droit.",
+ "oc:tooltip.tabletcase": "Boitier de tablettes de base. Placez-le dans l'assembleur pour ajouter des composants et créez une tablette.",
+ "oc:tooltip.terminal": "Permet de contrôler un serveur à distance, tant que vous êtes à portée de lui. Fonctionne comme un écran-clavier portable. Maj-clique droit un serveur du support pour le lier au terminal.",
+ "oc:tooltip.tier": "§8Niv. %s",
+ "oc:tooltip.toolong": "Maintenez la touche [§f%s§7] pour plus d'informations.",
+ "oc:tooltip.transistor": "Un élément basique constituant la plupart des pièces d'un ordinateur. Il est un peu tordu, mais il fait son boulot.",
+ "oc:tooltip.upgradeangel": "Permet aux robots pour placer des blocs d'air mince, même s'il n'y a aucun point de référence.",
+ "oc:tooltip.upgradebattery": "Augmentez la quantité d'énergie qu'un robot peut stocker, le permettant de marcher plus longtemps sans devoir être rechargé.\nCapacité : §f%s§7",
+ "oc:tooltip.upgradechunkloader": "Si un robot se déplace dans une forêt sans personne à proximité, se déplace-il vraiment ? Cette amélioration s'assure qu'il le fait. Elle garde le chunk du robot chargé, mais consomme continuellement de l'énergie lors qu'il est actif.",
+ "oc:tooltip.upgradecontainercard": "Cette amélioration de conteneur permet l'installation ou le retrait dynamique d'une carte du robot assemblé.\nNiv. Maximum : §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "Cette amélioration de conteneur permet l'installation ou le retrait dynamique d'une amélioration du robot assemblé.\nNiv. Maximum : §f%s§7",
+ "oc:tooltip.upgradecrafting": "Permet aux robots d'utiliser le coin en haut à gauche de leur inventaire comme table d'artisanat. Vous devez respecter la position des objets comme pour un artisanat normal.",
+ "oc:tooltip.upgradedatabase": "Cette amélioration permet de stoquer les information de pile d'éléments pour une utilisation future d'autres composants. Notez que ceci doit être configuré à la main.\nEntrées supportées : §f%s§7",
+ "oc:tooltip.upgradeexperience": "Cette amélioration permet aux robots d'accumuler de l'experience en exécutant diverses opérations. Plus ils gagnent d'expérience, plus ils peuvent stocker de l'énergie, miner plus rapidement et utiliser les outils plus efficacement.",
+ "oc:tooltip.upgradegenerator": "Utilisé pour générer de l'énergie directement sur un robot, indépendament d'un chargeur. Consume du comburant (ex: charbon) pour une génération sur la durée, en fonction de l'efficacité du combustible.\n§fEfficacité§7: §a%s%%§7",
+ "oc:tooltip.upgradeinventory": "Cette amélioration donne un espace d'inventaire au robot. Sans l'une d'elles, les robots ne seraient pas capable de stocker des éléments en interne.",
+ "oc:tooltip.upgradeinventorycontroller": "Cette amélioration permet au robot plus de contrôle sur ses interactions avec les inventaires externes, et leur permet d'échanger leurs outils avec un élément de son inventaire.",
+ "oc:tooltip.upgradenavigation": "Utilisé pour déterminer la position et l'orientation d'un robot. Cette position est relative au centre de la zone (affichée sur une carte) ou l'amélioration a été créée.",
+ "oc:tooltip.upgradepiston": "Cette amélioration est très rentre-dedans. Elle permet de déplacer des blocs comme lors de l'utilisation d'un piston. malgré tout, cela §lne déplace pas§7 les entités.",
+ "oc:tooltip.upgradesign": "Permets de lire et d'écrire sur des panneaux.",
+ "oc:tooltip.upgradesolargenerator": "Utilisé pour générer de l'énergie directement sur un robot, indépendament d'un chargeur, via le soleil. Aucun bloc ne doit se trouver au-dessus du robot pour que cette génération fonctionne. Génère de l'énergie à %s%% de la vitesse d'un moteur stirling (BuildCraft).",
+ "oc:tooltip.upgradetank": "Cette amélioration donne un réservoire de fluides au robot. Sans l'une d'elles, les robots ne seraient pas capable de stocker des fluides en interne.",
+ "oc:tooltip.upgradetankcontroller": "Cette amélioration permet au robot plus de contrôle sur ses interactions avec les réservoirs externes, et leur permet de transférer les fluides avec un élément réservoir de fluide de son inventaire.",
+ "oc:tooltip.upgradetractorbeam": "Equipe le robot avec une technologie extrêmement avancée, surnommé \"l'aimant d'éléments\". Cela lui permet de prendre des éléments n'importe où 3 blocs autour de son emplacement.",
+ "oc:tooltip.wirelessnetworkcard": "Permet l'envoi de messages réseaux sans fil. Pensez à régler la §fforce du signal§7, sinon aucun paquet ne sera envoyé!",
+ "nei.options.inventory.oredict": "Montrez les noms OreDictionary",
+ "nei.options.inventory.oredict.true": "Vrai",
+ "nei.options.inventory.oredict.false": "Faux",
+ "option.oc.address": "Adresse",
+ "option.oc.componentName": "Nom du composant",
+ "option.oc.energy": "Énergie"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/it_IT.lang b/src/main/resources/assets/opencomputers/lang/it_IT.lang
deleted file mode 100644
index 11dfb3ec67..0000000000
--- a/src/main/resources/assets/opencomputers/lang/it_IT.lang
+++ /dev/null
@@ -1,271 +0,0 @@
-# Use [nl] to for a line break.
-
-# Blocks
-tile.oc.accesspoint.name=Punto di Accesso
-tile.oc.adapter.name=Adattatore
-tile.oc.assembler.name=Assemblatore Elettronico
-tile.oc.cable.name=Cavo
-tile.oc.capacitor.name=Condendatore
-tile.oc.case1.name=Computer Case (Livello 1)
-tile.oc.case2.name=Computer Case (Livello 2)
-tile.oc.case3.name=Computer Case (Livello 3)
-tile.oc.casecreative.name=Computer Case (Creativo)
-tile.oc.charger.name=Caricabatterie
-tile.oc.disassembler.name=Disassemblatore
-tile.oc.diskdrive.name=Unità Disco
-tile.oc.geolyzer.name=Geolyzer
-tile.oc.keyboard.name=Tastiera
-tile.oc.hologram1.name=Proiettore Ologrammi (Livello 1)
-tile.oc.hologram2.name=Proiettore Ologrammi (Livello 2)
-tile.oc.motionsensor.name=Sensore di Movimento
-tile.oc.powerconverter.name=Convertitore di Energia
-tile.oc.powerdistributor.name=Distributore di Energia
-tile.oc.redstone.name=Pietrarossa I/O
-tile.oc.robot.name=Robot
-tile.oc.robotafterimage.name=Robot
-tile.oc.screen1.name=Schermo (Livello 1)
-tile.oc.screen2.name=Schermo (Livello 2)
-tile.oc.screen3.name=Schermo (Livello 3)
-tile.oc.rack.name=Rack
-tile.oc.switch.name=Switch
-
-# Items
-item.oc.abstractbuscard.name=Scheda Bus Astratto
-item.oc.acid.name=Grog
-item.oc.alu.name=Unità Aritmetica Logica (ALU)
-item.oc.analyzer.name=Analizzatore
-item.oc.arrowkeys.name=Tasti Freccia
-item.oc.buttongroup.name=Gruppo di Pulsanti
-item.oc.cardbase.name=Scheda Base
-item.oc.circuitboard.name=Circuito
-item.oc.controlunit.name=Unità di Controllo (CU)
-item.oc.componentbus0.name=Bus Periferiche (Livello 1)
-item.oc.componentbus1.name=Bus Periferiche (Livello 2)
-item.oc.componentbus2.name=Bus Periferiche (Livello 3)
-item.oc.cpu0.name=Unità di Elaborazione Centrale (CPU) (Livello 1)
-item.oc.cpu1.name=Unità di Elaborazione Centrale (CPU) (Livello 2)
-item.oc.cpu2.name=Unità di Elaborazione Centrale (CPU) (Livello 3)
-item.oc.cuttingwire.name=Taglierina
-item.oc.debugcard.name=Scheda di Debug
-item.oc.disk.name=Disco
-item.oc.floppydisk.name=Disco Floppy
-item.oc.graphicscard0.name=Scheda Grafica (Livello 1)
-item.oc.graphicscard1.name=Scheda Grafica (Livello 2)
-item.oc.graphicscard2.name=Scheda Grafica (Livello 3)
-item.oc.harddiskdrive0.name=Disco Rigido (Livello 1)
-item.oc.harddiskdrive1.name=Disco Rigido (Livello 2)
-item.oc.harddiskdrive2.name=Disco Rigido (Livello 3)
-item.oc.internetcard.name=Scheda Internet
-item.oc.interweb.name=Interweb
-item.oc.ironnugget.name=Pepita di Ferro
-item.oc.linkedcard.name=Scheda Collegata
-item.oc.memory0.name=Memoria (Livello 1)
-item.oc.memory1.name=Memoria (Livello 1.5)
-item.oc.memory2.name=Memoria (Livello 2)
-item.oc.memory3.name=Memoria (Livello 2.5)
-item.oc.memory4.name=Memoria (Livello 3)
-item.oc.memory5.name=Memoria (Livello 3.5)
-item.oc.microchip0.name=Microchip (Livello 1)
-item.oc.microchip1.name=Microchip (Livello 2)
-item.oc.microchip2.name=Microchip (Livello 3)
-item.oc.networkcard.name=Scheda di Rete
-item.oc.numpad.name=Tastierino Numerico
-item.oc.printedcircuitboard.name=Circuito Stampato (PCB)
-item.oc.rawcircuitboard.name=Circuito Grezzo
-item.oc.redstonecard0.name=Scheda Pietrarossa (Livello 1)
-item.oc.redstonecard1.name=Scheda Pietrarossa (Livello 2)
-item.oc.server0.name=Server (Livello 1)
-item.oc.server1.name=Server (Livello 2)
-item.oc.server2.name=Server (Livello 3)
-item.oc.server3.name=Server (Creativo)
-item.oc.tablet.name=Tablet
-item.oc.tabletcase0.name=Custodia Tablet (Livello 1)
-item.oc.tabletcase1.name=Custodia Tablet (Livello 2)
-item.oc.tabletcase3.name=Custodia Tablet (Creativo)
-item.oc.terminal.name=Terminale Remoto
-item.oc.transistor.name=Transistor
-item.oc.upgradeangel.name=Upgrade Angel
-item.oc.upgradebattery0.name=Upgrade Batteria (Livello 1)
-item.oc.upgradebattery1.name=Upgrade Batteria (Livello 2)
-item.oc.upgradebattery2.name=Upgrade Batteria (Livello 3)
-item.oc.upgradechunkloader.name=Upgrade Chunkloader
-item.oc.upgradecontainercard0.name=Contenitore Schede (Livello 1)
-item.oc.upgradecontainercard1.name=Contenitore Schede (Livello 2)
-item.oc.upgradecontainercard2.name=Contenitore Schede (Livello 3)
-item.oc.upgradecontainerupgrade0.name=Upgrade Contenitore (Livello 1)
-item.oc.upgradecontainerupgrade1.name=Upgrade Contenitore (Livello 2)
-item.oc.upgradecontainerupgrade2.name=Upgrade Contenitore (Livello 3)
-item.oc.upgradecrafting.name=Upgrade Crafting
-item.oc.upgradeexperience.name=Upgrade Esperienza
-item.oc.upgradegenerator.name=Upgrade Generatore
-item.oc.upgradeinventory.name=Upgrade Inventario
-item.oc.upgradeinventorycontroller.name=Upgrade Controllore Inventario
-item.oc.upgradenavigation.name=Upgrade Navigazione
-item.oc.upgradepiston.name=Upgrade Pistoni
-item.oc.upgradesign.name=Upgrade I/O Cartelli
-item.oc.upgradesolargenerator.name=Upgrade Panneli Solari
-item.oc.upgradetank.name=Upgrade Taniche
-item.oc.upgradetankcontroller.name=Upgrade Controllore Taniche
-item.oc.upgradetractorbeam.name=Upgrade Raggio Traente
-item.oc.wirelessnetworkcard0.name=Scheda di Rete Wireless (Livello 1)
-item.oc.wirelessnetworkcard1.name=Scheda di Rete Wireless (Livello 2)
-
-# GUI
-oc:gui.Analyzer.Address=§6Indirizzo§f: %s
-oc:gui.Analyzer.AddressCopied=Indirizzo copiato negli appunti.
-oc:gui.Analyzer.ChargerSpeed=§6Velocità ricarica§f: %s
-oc:gui.Analyzer.ComponentName=§6Nome componente§f: %s
-oc:gui.Analyzer.Components=§6Numero componenti connessi§f: %s
-oc:gui.Analyzer.LastError=§6Ultimo errore§f: %s
-oc:gui.Analyzer.RobotName=§6Nome§f: %s
-oc:gui.Analyzer.RobotOwner=§6Proprietario§f: %s
-oc:gui.Analyzer.RobotXp=§6Esperienza§f: %s (Livelli %s)
-oc:gui.Analyzer.StoredEnergy=§6Energia immagazzinata§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Totale energia immagazzinata§f: %s
-oc:gui.Analyzer.Users=§6Utenti§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Potenza segnale§f: %s
-oc:gui.Assembler.Collect=Collect output
-oc:gui.Assembler.Complexity=Complessità: %s/%s
-oc:gui.Assembler.InsertCase=Inserisci un case
-oc:gui.Assembler.InsertCPU=Inserisci una CPU
-oc:gui.Assembler.InsertRAM=Inserisci della RAM
-oc:gui.Assembler.Progress=Progresso: %s%% (%s)
-oc:gui.Assembler.Run=Assembla
-oc:gui.Assembler.Warnings=§eAttenzione§7: Mancano i componenti raccomandati.
-oc:gui.Assembler.Warning.GraphicsCard=Scheda Grafica
-oc:gui.Assembler.Warning.Inventory=Upgrade Inventario
-oc:gui.Assembler.Warning.Keyboard=Tastiera
-oc:gui.Assembler.Warning.OS=Disco di Boot
-oc:gui.Assembler.Warning.Screen=Schermo
-oc:gui.Chat.NewVersion=Una nuova versione è disponibile: %s
-oc:gui.Chat.WarningFingerprint=§cATTENZIONE§f - mancata corrispondenza dei fingerprint! Atteso '§a%s§f' ma ottenuto '§e%s§f'. Tranne nel caso tu sia un mod che stai utilizzando una versione decomppilata, è §lfortemente§f raccomantado riscaricare OpenComputers, perché il file JAR che stai utilizzando potrebbe essere stato corrotto.
-oc:gui.Chat.WarningLuaFallback=Le librerie Lua Native non sono disponibili, i computers non saranno in gredo di mantenere il loro stato di persostenza. Essi verranno riavviati quando il chunk viene ricaricato.
-oc:gui.Chat.WarningProjectRed=Stai utilizzando una versione di Project: Red che è incompatibile con OpenComputers. Prova ad aggriornare la tua versione di Project: Red.
-oc:gui.Error.ComponentOverflow=Troppi componenti connessi al computer.
-oc:gui.Error.InternalError=Errore interno, per favore vedi il file di log. Questo è probabilmente un bug.
-oc:gui.Error.NoCPU=Nessuna CPU instllata nel computer.
-oc:gui.Error.NoEnergy=Energia insufficiente.
-oc:gui.Error.NoRAM=Nessuna RAM installata nel computer.
-oc:gui.Error.OutOfMemory=Memoria esaurita.
-oc:gui.Robot.Power=Energia
-oc:gui.Robot.TurnOff=Spegni
-oc:gui.Robot.TurnOn=Accendi
-oc:gui.Rack.None=Nessuno
-oc:gui.Rack.Back=Indietro
-oc:gui.Rack.Bottom=Basso
-oc:gui.Rack.Left=Sinistra
-oc:gui.Rack.Right=Destra
-oc:gui.Rack.Top=Alto
-oc:gui.Switch.TransferRate=Tasso di ciclo
-oc:gui.Switch.PacketsPerCycle=Pacchetti / ciclo
-oc:gui.Switch.QueueSize=Dimensione coda
-oc:gui.Terminal.InvalidKey=Tasto invalido, molto probabilmente un altro terminale è stato collegato al server.
-oc:gui.Terminal.OutOfRange=Nessun segnale
-
-# Containers
-oc:container.accesspoint=Punto di accesso
-oc:container.adapter=Adattatore
-oc:container.charger=Caricabatterie
-oc:container.case=Computer
-oc:container.disassembler=Disassemblatore
-oc:container.diskdrive=Unità Disco
-oc:container.server=Server
-oc:container.rack=Rack
-oc:container.switch=Switch
-oc:container.tabletwrapper=Tablet
-
-# Keybinds
-key.materialCosts=Mostra Costi Materiali
-key.clipboardPaste=Copia negli Appunti
-
-# Item / Block Tooltips
-oc:tooltip.accesspoint=Funziona come uno Switch, ma può anche ricevere pacchetti wireless ed inoltrare pacchetti ricevuti via cavo in modo wireless.
-oc:tooltip.abstractbuscard=Consente di interagire con il bus astratto di §fStargateTech 2§7 inviando e ricevendo pacchetti LIP.
-oc:tooltip.acid=Un liquido altamente tossico, normalmente consumato solo da alcuni pirati. Grazie alla sua natura corrosiva è particolarmente adatto per l'incisione dei circuiti stampati.
-oc:tooltip.adapter=Utilizzato per controllare blocchi che non sono componenti, come blocchi vanilla di minecraft e blocchi di altri mod.
-oc:tooltip.alu=Calcola le somme così non devi farlo tu. Potrebbe essere meglgio così.
-oc:tooltip.analyzer=Utilizzato per mostrare informazioni riguardo i blocchi, come il loro §findirizzo§7 e il loro §fnome del componente§7.[nl] Inoltre mostra gli errori che hanno causato un crash del computer, se non è stato spento normalmente.
-oc:tooltip.assembler=Permette di costruire robot e altri dispositivi da un certo numero di parti di computer.
-oc:tooltip.cable=Un modo economico per connettere i blocchi.
-oc:tooltip.capacitor=Immagazzina energia per un uso successivo. Può essere riempito e svuotato molto rapidamente.
-oc:tooltip.cardbase=Come indica il nome, questo è l'elemento di base per tutte le schede di espansione.
-oc:tooltip.case=Il case del computer è l'elemento di base per i computer e ospita le §fschede di espansione§7, la §fRAM§7 e il §fdisco rigido§7.[nl] Slots: §f%s§7
-oc:tooltip.charger=Trasferisce energia nei robot adiacenti. La velocità di trasferimento dipende dal §fsegnale di pietrarossa§7 applicato, dove nessun segnale significa di non ricaricare i robot e segnale massimo significa ricarica alla massima velocità.
-oc:tooltip.circuitboard=Ora stiamo ottenendo qualcosa. Può essere inciso per ottenere un circuito stampato.
-oc:tooltip.controlunit=Questa è l'unità che ... controlla ... cose. È necessario per costruire una CPU. Quindi sì, è assolutamente importante.
-oc:tooltip.componentbus=Questa espansione consente ai server di comunicare con più componenti, allo stesso tempo, in modo simile a come fanno le CPU.[nl] Componenti supportati: §f%s§7
-oc:tooltip.cpu=Una componente essenziale di tutti i computer. La frequenza di clock è un po' inaffidabile, ma cosa vi aspettate quando viene eseguito da una meridiana tascabile?[nl] Componenti supportati: §f%s§7
-oc:tooltip.cpu.Architecture=Architettura: §f%s§7
-oc:tooltip.cuttingwire=Usato per tagliare i blocchi di argilla in circuiti. Si rompe dopo l'uso, che rende probabilmente lo rende strumento più inefficiente mai visto.
-oc:tooltip.debugcard=Oggetto per la modalità creativa, permette manipolare il mondo per rendere il testing più facile. Utilizzare a proprio rischio e pericolo.
-oc:tooltip.disassembler=Separa gli oggetti nelle loro componenti originali. §lAttenzione§7: gli oggetti restituiti hanno il %s%% di probabilità di rompersi nel processo!
-oc:tooltip.disk=Mezzo primitivo che può essere utilizzato per costruire dispositivi di memorizzazione persistente.
-oc:tooltip.diskdrive.CC=Floppy di ComputerCraft sono §asupportati§7.
-oc:tooltip.diskdrive=Permette di leggere e scrivere floppy. Può essere installato in robot per consentire in seguito l'inserimento di floppy.
-oc:tooltip.geolyzer=Permette la scansione di durezza dei blocchi della zona circostante. Questa informazione può essere utile per generare ologrammi della zona o per rilevare minerali.
-oc:tooltip.graphicscard=Usato per cambiare ciò che è visualizzato sullo schermo.[nl] Risoluzione massima: §f%sx%s§7[nl] Massima profondità di colore: §f%s§7[nl] Operazioni/ciclo: §f%s§7
-oc:tooltip.internetcard=Questa scheda consente di effettuare richieste HTTP e l'utilizzo di socket TCP reali.
-oc:tooltip.interweb=Congratulazioni, hai vinto un (1) interweb. È possibile connettersi ad esso utilizzando una scheda di Internet. Attenzione: non alimentare i troll.
-oc:tooltip.ironnugget=Una pepita fatta di ferro, ecco perché si chiama Pepita di Ferro, duh ...
-oc:tooltip.keyboard=Può essere attaccato agli schermi per consentire la digitazione su di essi.
-oc:tooltip.hologram0=Un display volumetrico che può essere controllato da computer per visualizzare le strutture voxel arbitrarie.[nl] Risoluzione: §f48x32x48§7 [nl] Scala massima: §f3x§7 [nl] Profondità di colore: §fMonocromatico§7
-oc:tooltip.hologram1=Un display volumetrico che può essere controllato da computer per visualizzare le strutture voxel arbitrarie.[nl] Risoluzione: §f48x32x48§7 [nl] Scala massima: §f4x§7 [nl] Profondità di colore: §fTricolore§7
-oc:tooltip.linkedcard=Questi sono realizzati a coppie, e possono comunicare solo con la loro scheda associata. Tuttavia, essi possono comunicare attraverso qualsiasi distanza, e anche attraverso le dimensioni. L'energia richiesta per inviare un messaggio però è piuttosto alta.
-oc:tooltip.linkedcard_channel=§8Canale: %s§7
-oc:tooltip.materialcosts=Tieni premuto [§f%s§7] per il costo in materiali.
-oc:tooltip.materials=Materiali:
-oc:tooltip.memory=Necessaria per far funzionare i computer. Più ne hai, più complessi i programmi che possono essere eseguiti.
-oc:tooltip.microchip=Il chip precedentemente noto come circuito integrato. Non ho idea del perché questo funziona con la pietrarossa, ma lo fa.
-oc:tooltip.motionsensor=In grado di rilevare il movimento di esseri viventi nelle vicinanze. Richiede linea di vista ininterrotta.
-oc:tooltip.networkcard=Consente ai computer remoti connessi da altri blocchi (come i cavi) di comunicare con l'invio di messaggi.
-oc:tooltip.poweracceptor=Velocità di conversione di energia: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fBuildCraft MJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fFactorization Charge§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fIndustrialCraft² EU§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fMekanism Joules§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fThermal Expansion RF§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=Converte l'energia da altri mod nel tipo di energia interna. Tassi di conversione:
-oc:tooltip.powerdistributor=Distribuisce l'eenergia tra reti diverse. Questo è utile per la condivisione di energia immessa nel sistema da un convertitore tra le diverse sotto-reti che dovrebbero rimanere separati.
-oc:tooltip.printedcircuitboard=L'elemento di base per schede di espansione, per la memoria e così via.
-oc:tooltip.rawcircuitboard=Può essere indurito in qualsiasi forno o fornace compatibile.
-oc:tooltip.redstone=Permette la lettura e l'emissione di segnali di pietrarossa attorno tutto il blocco. Può essere controllato da qualsiasi computer che è collegato. Questo è fondamentalmente come una scheda di pietrarossa esterna.
-oc:tooltip.redstonecard.ProjectRed=§fProjectRed§7 è §asupportato§7.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 è §asupportato§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 è §asupportato§7.
-oc:tooltip.redstonecard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 è §asupportato§7.
-oc:tooltip.redstonecard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 è §asupportato§7.
-oc:tooltip.redstonecard=Permette la lettura e l'emissione di segnali di pietrarossa attorno tutto il computer o robot.
-oc:tooltip.robot=A differenza dei computer, i robot possono muoversi e interagire con il mondo, molto simile a come può fare un giocatore. Tuttavia §onon§7 possono interagire con componenti esterni!U
-# the underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fLivelli§7: §a%s§7
-oc:tooltip.robot_storedenergy=§fEnergia immagazzinata§7: §a%s§7
-oc:tooltip.screen=Mostra del testo, contollato da una scheda grafica contenuta nel case del computer.[nl] Risoluzione massima: §f%sx%s§7[nl] Profondità di colore massima: §f%s§7
-oc:tooltip.server=Questo è un server, ci sono tanti come lui, ma questo può essere aggiornato con i componenti in modo simile a un case del computer. Può essere avviato inserendolo in un rack di server.
-oc:tooltip.server.Components=Componenti installati:
-oc:tooltip.rack=Permette l'installazione di un massimo di quattro server. Utilizzare un terminale remoto per accedere ai server contenuti in questo server rack.
-oc:tooltip.switch=Consente il collegamento di reti diverse tra loro. Solo i messaggi di rete saranno inoltrati attraverso il blocco, i componenti non saranno invece visibili Utilizzarlo per separare le reti pur consentendo la comunicazione utilizzando schede di rete, per esempio.
-oc:tooltip.tablet=Un computer tablet, per del Lua fresco in movimento. Può essere forzato lo spegnimento usandolo mentre si preme maiusc.
-oc:tooltip.tabletcase=Case di base per i tablet. Posizionarlo in assembler per aggiungere componenti e creare un tablet PC.
-oc:tooltip.terminal=Permette il controllo di un server in remoto, fino a quando si è nella portata di esso. Agisce come uno schermo portatile e una tastiera. Utilizzare i tasti maiusc-destro del mouse su un server in un rack di server per associare il terminale ad esso.
-oc:tooltip.livello=§8Livello %s
-oc:tooltip.toolong=Tenere premuto [§f%s§7] per un tooltip dettagliato.
-oc:tooltip.transistor=Un elemento fondamentale in molte altre parti del computer. È un po' contorto, ma fa il suo lavoro.
-oc:tooltip.upgradeangel=Consente ai robot di posizionare i blocchi nel nulla, anche se non vi è alcun blocco di riferimento.
-oc:tooltip.upgradebattery=Aumenta la quantità di energia che un robot è in grado di immagazzinare, permettendogli di lavorare più a lungo senza dover essere ricaricato. [nl] capacità: §f%s§7
-oc:tooltip.upgradechunkloader=Se un robot si muove in una foresta e non c'è nessuno intorno per vederlo, si muove veramente? Questo aggiornamento consente di essere certi che lo faccia. Mantiene il chunk dove si trova il robot caricato, ma consuma continuamente energia, mentre è attivo.
-oc:tooltip.upgradecontainercard=Questo aggiornamento consente l'installazione e la rimozione di schede da un robot assemblato dinamicamente. [nl] Livello massimo: §f%s§7
-oc:tooltip.upgradecontainerupgrade=Questo aggiornamento consente l'installazione e la rimozione di upgrade da un robot assemblato dinamicamente. [nl] Livello massimo: §f%s§7
-oc:tooltip.upgradecrafting=Consente robot per utilizzare l'area in alto a sinistra del loro inventario per il crafting di oggetti. Gli oggetti devono essere allineati come sarebbero in un banco da lavoro.
-oc:tooltip.upgradeexperience=Questo aggiornamento consente di robot di accumulare esperienza, quando effettuano diverse operazioni. Maggiore è la loro esperienza, più energia sono in grado di memorizzare, più velocemente possono raccogliere blocchi e più efficientemente utilizzano gli strumenti.
-oc:tooltip.upgradegenerator=Può essere usato per generare energia dal combustibile mentre si è in movimento. Brucia oggetti per produrre energia nel corso del tempo, in base al loro valore di carburante.[nl] §fEfficienza§7: §a%s%%§7
-oc:tooltip.upgradeinventory=Questo aggiornamento fornisce spazio nell'inventario al robot. Senza uno di questi, i robot non saranno in grado di immagazzinare gli oggetti internamente.
-oc:tooltip.upgradeinventorycontroller=Questo aggiornamento permette al robot più controllo nel modo in cui interagisce con gli inventari esterni, e gli permette di scambiare il suo strumento equipaggiato con uno nel suo inventario.
-oc:tooltip.upgradenavigation=Può essere usato per determinare la posizione e l'orientamento del robot. La posizione è relativa al centro della mappa che è stata utilizzata per il crafting tale aggiornamento.
-oc:tooltip.upgradepiston=Questo aggiornamentp è molto spinto. Permette di spingere i blocchi, in modo simile ad un pistone. Tuttavia §lnon§7 muove le entità.
-oc:tooltip.upgradesign=Consente la lettura del testo e sulla scrittura del testo sui cartelli.
-oc:tooltip.upgradesolargenerator=Può essere usato per generare energia dalla luce del sole. Richiede una chiara linea di vista verso il cielo sopra il robot. Genera energia al %s%% della velocità di un motore Stirling.
-oc:tooltip.upgradetank=Questo aggiornamento fornisce un serbatoio per lo stoccaggio di liquidi al robot. Senza uno di questi, i robot non saranno in grado di immagazzinare i fluidi internamente.
-oc:tooltip.upgradetankcontroller=Questo aggiornamento permette al robot più controllo nel modo in cui interagisce con serbatoi esterni, e permette di trasferire i fluidi dentro e fuori dal serbatoio nel suo inventario.
-oc:tooltip.upgradetractorbeam=Dota il robot con tecnologia estremamente avanzata, soprannominato il "Magnet Item". Consente a raccogliere oggetti ovunque entro 3 blocchi dalla sua posizione.
-oc:tooltip.wirelessnetworkcard=Consente invio di messaggi wireless in aggiunta a quelli normali. È possibile regolare la §fpotenza del segnale§7 per controllare quanto lontano i messaggi vengono inviati. Una più elevata potenza del segnale richiede un maggior consumo energetico.
diff --git a/src/main/resources/assets/opencomputers/lang/it_it.json b/src/main/resources/assets/opencomputers/lang/it_it.json
new file mode 100644
index 0000000000..56be5eaaaa
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/it_it.json
@@ -0,0 +1,260 @@
+{
+ "tile.oc.accesspoint": "Punto di Accesso",
+ "tile.oc.adapter": "Adattatore",
+ "tile.oc.assembler": "Assemblatore Elettronico",
+ "tile.oc.cable": "Cavo",
+ "tile.oc.capacitor": "Condendatore",
+ "tile.oc.case1": "Computer Case (Livello 1)",
+ "tile.oc.case2": "Computer Case (Livello 2)",
+ "tile.oc.case3": "Computer Case (Livello 3)",
+ "tile.oc.casecreative": "Computer Case (Creativo)",
+ "tile.oc.charger": "Caricabatterie",
+ "tile.oc.disassembler": "Disassemblatore",
+ "tile.oc.diskdrive": "Unità Disco",
+ "tile.oc.geolyzer": "Geolyzer",
+ "tile.oc.keyboard": "Tastiera",
+ "tile.oc.hologram1": "Proiettore Ologrammi (Livello 1)",
+ "tile.oc.hologram2": "Proiettore Ologrammi (Livello 2)",
+ "tile.oc.motionsensor": "Sensore di Movimento",
+ "tile.oc.powerconverter": "Convertitore di Energia",
+ "tile.oc.powerdistributor": "Distributore di Energia",
+ "tile.oc.redstone": "Pietrarossa I/O",
+ "tile.oc.robot": "Robot",
+ "tile.oc.robotafterimage": "Robot",
+ "tile.oc.screen1": "Schermo (Livello 1)",
+ "tile.oc.screen2": "Schermo (Livello 2)",
+ "tile.oc.screen3": "Schermo (Livello 3)",
+ "tile.oc.rack": "Rack",
+ "tile.oc.switch": "Switch",
+ "item.oc.abstractbuscard": "Scheda Bus Astratto",
+ "item.oc.acid": "Grog",
+ "item.oc.alu": "Unità Aritmetica Logica (ALU)",
+ "item.oc.analyzer": "Analizzatore",
+ "item.oc.arrowkeys": "Tasti Freccia",
+ "item.oc.buttongroup": "Gruppo di Pulsanti",
+ "item.oc.cardbase": "Scheda Base",
+ "item.oc.circuitboard": "Circuito",
+ "item.oc.controlunit": "Unità di Controllo (CU)",
+ "item.oc.componentbus0": "Bus Periferiche (Livello 1)",
+ "item.oc.componentbus1": "Bus Periferiche (Livello 2)",
+ "item.oc.componentbus2": "Bus Periferiche (Livello 3)",
+ "item.oc.cpu0": "Unità di Elaborazione Centrale (CPU) (Livello 1)",
+ "item.oc.cpu1": "Unità di Elaborazione Centrale (CPU) (Livello 2)",
+ "item.oc.cpu2": "Unità di Elaborazione Centrale (CPU) (Livello 3)",
+ "item.oc.cuttingwire": "Taglierina",
+ "item.oc.debugcard": "Scheda di Debug",
+ "item.oc.disk": "Disco",
+ "item.oc.floppydisk": "Disco Floppy",
+ "item.oc.graphicscard0": "Scheda Grafica (Livello 1)",
+ "item.oc.graphicscard1": "Scheda Grafica (Livello 2)",
+ "item.oc.graphicscard2": "Scheda Grafica (Livello 3)",
+ "item.oc.harddiskdrive0": "Disco Rigido (Livello 1)",
+ "item.oc.harddiskdrive1": "Disco Rigido (Livello 2)",
+ "item.oc.harddiskdrive2": "Disco Rigido (Livello 3)",
+ "item.oc.internetcard": "Scheda Internet",
+ "item.oc.interweb": "Interweb",
+ "item.oc.ironnugget": "Pepita di Ferro",
+ "item.oc.linkedcard": "Scheda Collegata",
+ "item.oc.memory0": "Memoria (Livello 1)",
+ "item.oc.memory1": "Memoria (Livello 1.5)",
+ "item.oc.memory2": "Memoria (Livello 2)",
+ "item.oc.memory3": "Memoria (Livello 2.5)",
+ "item.oc.memory4": "Memoria (Livello 3)",
+ "item.oc.memory5": "Memoria (Livello 3.5)",
+ "item.oc.microchip0": "Microchip (Livello 1)",
+ "item.oc.microchip1": "Microchip (Livello 2)",
+ "item.oc.microchip2": "Microchip (Livello 3)",
+ "item.oc.networkcard": "Scheda di Rete",
+ "item.oc.numpad": "Tastierino Numerico",
+ "item.oc.printedcircuitboard": "Circuito Stampato (PCB)",
+ "item.oc.rawcircuitboard": "Circuito Grezzo",
+ "item.oc.redstonecard0": "Scheda Pietrarossa (Livello 1)",
+ "item.oc.redstonecard1": "Scheda Pietrarossa (Livello 2)",
+ "item.oc.server0": "Server (Livello 1)",
+ "item.oc.server1": "Server (Livello 2)",
+ "item.oc.server2": "Server (Livello 3)",
+ "item.oc.server3": "Server (Creativo)",
+ "item.oc.tablet": "Tablet",
+ "item.oc.tabletcase0": "Custodia Tablet (Livello 1)",
+ "item.oc.tabletcase1": "Custodia Tablet (Livello 2)",
+ "item.oc.tabletcase3": "Custodia Tablet (Creativo)",
+ "item.oc.terminal": "Terminale Remoto",
+ "item.oc.transistor": "Transistor",
+ "item.oc.upgradeangel": "Upgrade Angel",
+ "item.oc.upgradebattery0": "Upgrade Batteria (Livello 1)",
+ "item.oc.upgradebattery1": "Upgrade Batteria (Livello 2)",
+ "item.oc.upgradebattery2": "Upgrade Batteria (Livello 3)",
+ "item.oc.upgradechunkloader": "Upgrade Chunkloader",
+ "item.oc.upgradecontainercard0": "Contenitore Schede (Livello 1)",
+ "item.oc.upgradecontainercard1": "Contenitore Schede (Livello 2)",
+ "item.oc.upgradecontainercard2": "Contenitore Schede (Livello 3)",
+ "item.oc.upgradecontainerupgrade0": "Upgrade Contenitore (Livello 1)",
+ "item.oc.upgradecontainerupgrade1": "Upgrade Contenitore (Livello 2)",
+ "item.oc.upgradecontainerupgrade2": "Upgrade Contenitore (Livello 3)",
+ "item.oc.upgradecrafting": "Upgrade Crafting",
+ "item.oc.upgradeexperience": "Upgrade Esperienza",
+ "item.oc.upgradegenerator": "Upgrade Generatore",
+ "item.oc.upgradeinventory": "Upgrade Inventario",
+ "item.oc.upgradeinventorycontroller": "Upgrade Controllore Inventario",
+ "item.oc.upgradenavigation": "Upgrade Navigazione",
+ "item.oc.upgradepiston": "Upgrade Pistoni",
+ "item.oc.upgradesign": "Upgrade I/O Cartelli",
+ "item.oc.upgradesolargenerator": "Upgrade Panneli Solari",
+ "item.oc.upgradetank": "Upgrade Taniche",
+ "item.oc.upgradetankcontroller": "Upgrade Controllore Taniche",
+ "item.oc.upgradetractorbeam": "Upgrade Raggio Traente",
+ "item.oc.wirelessnetworkcard0": "Scheda di Rete Wireless (Livello 1)",
+ "item.oc.wirelessnetworkcard1": "Scheda di Rete Wireless (Livello 2)",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "oc:gui.Analyzer.Address": "§6Indirizzo§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Indirizzo copiato negli appunti.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Velocità ricarica§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Nome componente§f: %s",
+ "oc:gui.Analyzer.Components": "§6Numero componenti connessi§f: %s",
+ "oc:gui.Analyzer.LastError": "§6Ultimo errore§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Nome§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Proprietario§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Esperienza§f: %s (Livelli %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6Energia immagazzinata§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Totale energia immagazzinata§f: %s",
+ "oc:gui.Analyzer.Users": "§6Utenti§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Potenza segnale§f: %s",
+ "oc:gui.Assembler.Collect": "Collect output",
+ "oc:gui.Assembler.Complexity": "Complessità: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Inserisci un case",
+ "oc:gui.Assembler.InsertCPU": "Inserisci una CPU",
+ "oc:gui.Assembler.InsertRAM": "Inserisci della RAM",
+ "oc:gui.Assembler.Progress": "Progresso: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Assembla",
+ "oc:gui.Assembler.Warnings": "§eAttenzione§7: Mancano i componenti raccomandati.",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Scheda Grafica",
+ "oc:gui.Assembler.Warning.Inventory": "Upgrade Inventario",
+ "oc:gui.Assembler.Warning.Keyboard": "Tastiera",
+ "oc:gui.Assembler.Warning.OS": "Disco di Boot",
+ "oc:gui.Assembler.Warning.Screen": "Schermo",
+ "oc:gui.Chat.NewVersion": "Una nuova versione è disponibile: %s",
+ "oc:gui.Chat.WarningFingerprint": "§cATTENZIONE§f - mancata corrispondenza dei fingerprint! Atteso '§a%s§f' ma ottenuto '§e%s§f'. Tranne nel caso tu sia un mod che stai utilizzando una versione decomppilata, è §lfortemente§f raccomantado riscaricare OpenComputers, perché il file JAR che stai utilizzando potrebbe essere stato corrotto.",
+ "oc:gui.Chat.WarningLuaFallback": "Le librerie Lua Native non sono disponibili, i computers non saranno in gredo di mantenere il loro stato di persostenza. Essi verranno riavviati quando il chunk viene ricaricato.",
+ "oc:gui.Chat.WarningProjectRed": "Stai utilizzando una versione di Project: Red che è incompatibile con OpenComputers. Prova ad aggriornare la tua versione di Project: Red.",
+ "oc:gui.Error.ComponentOverflow": "Troppi componenti connessi al computer.",
+ "oc:gui.Error.InternalError": "Errore interno, per favore vedi il file di log. Questo è probabilmente un bug.",
+ "oc:gui.Error.NoCPU": "Nessuna CPU instllata nel computer.",
+ "oc:gui.Error.NoEnergy": "Energia insufficiente.",
+ "oc:gui.Error.NoRAM": "Nessuna RAM installata nel computer.",
+ "oc:gui.Error.OutOfMemory": "Memoria esaurita.",
+ "oc:gui.Robot.Power": "Energia",
+ "oc:gui.Robot.TurnOff": "Spegni",
+ "oc:gui.Robot.TurnOn": "Accendi",
+ "oc:gui.Rack.None": "Nessuno",
+ "oc:gui.Rack.Back": "Indietro",
+ "oc:gui.Rack.Bottom": "Basso",
+ "oc:gui.Rack.Left": "Sinistra",
+ "oc:gui.Rack.Right": "Destra",
+ "oc:gui.Rack.Top": "Alto",
+ "oc:gui.Switch.TransferRate": "Tasso di ciclo",
+ "oc:gui.Switch.PacketsPerCycle": "Pacchetti / ciclo",
+ "oc:gui.Switch.QueueSize": "Dimensione coda",
+ "oc:gui.Terminal.InvalidKey": "Tasto invalido, molto probabilmente un altro terminale è stato collegato al server.",
+ "oc:gui.Terminal.OutOfRange": "Nessun segnale",
+ "oc:container.accesspoint": "Punto di accesso",
+ "oc:container.adapter": "Adattatore",
+ "oc:container.charger": "Caricabatterie",
+ "oc:container.case": "Computer",
+ "oc:container.disassembler": "Disassemblatore",
+ "oc:container.diskdrive": "Unità Disco",
+ "oc:container.server": "Server",
+ "oc:container.rack": "Rack",
+ "oc:container.switch": "Switch",
+ "oc:container.tabletwrapper": "Tablet",
+ "key.opencomputers.materialCosts": "Mostra Costi Materiali",
+ "key.opencomputers.clipboardPaste": "Copia negli Appunti",
+ "oc:tooltip.accesspoint": "Funziona come uno Switch, ma può anche ricevere pacchetti wireless ed inoltrare pacchetti ricevuti via cavo in modo wireless.",
+ "oc:tooltip.abstractbuscard": "Consente di interagire con il bus astratto di §fStargateTech 2§7 inviando e ricevendo pacchetti LIP.",
+ "oc:tooltip.acid": "Un liquido altamente tossico, normalmente consumato solo da alcuni pirati. Grazie alla sua natura corrosiva è particolarmente adatto per l'incisione dei circuiti stampati.",
+ "oc:tooltip.adapter": "Utilizzato per controllare blocchi che non sono componenti, come blocchi vanilla di minecraft e blocchi di altri mod.",
+ "oc:tooltip.alu": "Calcola le somme così non devi farlo tu. Potrebbe essere meglgio così.",
+ "oc:tooltip.analyzer": "Utilizzato per mostrare informazioni riguardo i blocchi, come il loro §findirizzo§7 e il loro §fnome del componente§7.\nInoltre mostra gli errori che hanno causato un crash del computer, se non è stato spento normalmente.",
+ "oc:tooltip.assembler": "Permette di costruire robot e altri dispositivi da un certo numero di parti di computer.",
+ "oc:tooltip.cable": "Un modo economico per connettere i blocchi.",
+ "oc:tooltip.capacitor": "Immagazzina energia per un uso successivo. Può essere riempito e svuotato molto rapidamente.",
+ "oc:tooltip.cardbase": "Come indica il nome, questo è l'elemento di base per tutte le schede di espansione.",
+ "oc:tooltip.case": "Il case del computer è l'elemento di base per i computer e ospita le §fschede di espansione§7, la §fRAM§7 e il §fdisco rigido§7.\nSlots: §f%s§7",
+ "oc:tooltip.charger": "Trasferisce energia nei robot adiacenti. La velocità di trasferimento dipende dal §fsegnale di pietrarossa§7 applicato, dove nessun segnale significa di non ricaricare i robot e segnale massimo significa ricarica alla massima velocità.",
+ "oc:tooltip.circuitboard": "Ora stiamo ottenendo qualcosa. Può essere inciso per ottenere un circuito stampato.",
+ "oc:tooltip.controlunit": "Questa è l'unità che ... controlla ... cose. È necessario per costruire una CPU. Quindi sì, è assolutamente importante.",
+ "oc:tooltip.componentbus": "Questa espansione consente ai server di comunicare con più componenti, allo stesso tempo, in modo simile a come fanno le CPU.\nComponenti supportati: §f%s§7",
+ "oc:tooltip.cpu": "Una componente essenziale di tutti i computer. La frequenza di clock è un po' inaffidabile, ma cosa vi aspettate quando viene eseguito da una meridiana tascabile?\nComponenti supportati: §f%s§7",
+ "oc:tooltip.cpu.Architecture": "Architettura: §f%s§7",
+ "oc:tooltip.cuttingwire": "Usato per tagliare i blocchi di argilla in circuiti. Si rompe dopo l'uso, che rende probabilmente lo rende strumento più inefficiente mai visto.",
+ "oc:tooltip.debugcard": "Oggetto per la modalità creativa, permette manipolare il mondo per rendere il testing più facile. Utilizzare a proprio rischio e pericolo.",
+ "oc:tooltip.disassembler": "Separa gli oggetti nelle loro componenti originali. §lAttenzione§7: gli oggetti restituiti hanno il %s%% di probabilità di rompersi nel processo!",
+ "oc:tooltip.disk": "Mezzo primitivo che può essere utilizzato per costruire dispositivi di memorizzazione persistente.",
+ "oc:tooltip.diskdrive.CC": "Floppy di ComputerCraft sono §asupportati§7.",
+ "oc:tooltip.diskdrive": "Permette di leggere e scrivere floppy. Può essere installato in robot per consentire in seguito l'inserimento di floppy.",
+ "oc:tooltip.geolyzer": "Permette la scansione di durezza dei blocchi della zona circostante. Questa informazione può essere utile per generare ologrammi della zona o per rilevare minerali.",
+ "oc:tooltip.graphicscard": "Usato per cambiare ciò che è visualizzato sullo schermo.\nRisoluzione massima: §f%sx%s§7\nMassima profondità di colore: §f%s§7\nOperazioni/ciclo: §f%s§7",
+ "oc:tooltip.internetcard": "Questa scheda consente di effettuare richieste HTTP e l'utilizzo di socket TCP reali.",
+ "oc:tooltip.interweb": "Congratulazioni, hai vinto un (1) interweb. È possibile connettersi ad esso utilizzando una scheda di Internet. Attenzione: non alimentare i troll.",
+ "oc:tooltip.ironnugget": "Una pepita fatta di ferro, ecco perché si chiama Pepita di Ferro, duh ...",
+ "oc:tooltip.keyboard": "Può essere attaccato agli schermi per consentire la digitazione su di essi.",
+ "oc:tooltip.hologram0": "Un display volumetrico che può essere controllato da computer per visualizzare le strutture voxel arbitrarie.\nRisoluzione: §f48x32x48§7\nScala massima: §f3x§7\nProfondità di colore: §fMonocromatico§7",
+ "oc:tooltip.hologram1": "Un display volumetrico che può essere controllato da computer per visualizzare le strutture voxel arbitrarie.\nRisoluzione: §f48x32x48§7\nScala massima: §f4x§7\nProfondità di colore: §fTricolore§7",
+ "oc:tooltip.linkedcard": "Questi sono realizzati a coppie, e possono comunicare solo con la loro scheda associata. Tuttavia, essi possono comunicare attraverso qualsiasi distanza, e anche attraverso le dimensioni. L'energia richiesta per inviare un messaggio però è piuttosto alta.",
+ "oc:tooltip.linkedcard_channel": "§8Canale: %s§7",
+ "oc:tooltip.materialcosts": "Tieni premuto [§f%s§7] per il costo in materiali.",
+ "oc:tooltip.materials": "Materiali:",
+ "oc:tooltip.memory": "Necessaria per far funzionare i computer. Più ne hai, più complessi i programmi che possono essere eseguiti.",
+ "oc:tooltip.microchip": "Il chip precedentemente noto come circuito integrato. Non ho idea del perché questo funziona con la pietrarossa, ma lo fa.",
+ "oc:tooltip.motionsensor": "In grado di rilevare il movimento di esseri viventi nelle vicinanze. Richiede linea di vista ininterrotta.",
+ "oc:tooltip.networkcard": "Consente ai computer remoti connessi da altri blocchi (come i cavi) di comunicare con l'invio di messaggi.",
+ "oc:tooltip.poweracceptor": "Velocità di conversione di energia: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fBuildCraft MJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fFactorization Charge§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fIndustrialCraft² EU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fMekanism Joules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fThermal Expansion RF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fResonant Engine Coulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Converte l'energia da altri mod nel tipo di energia interna. Tassi di conversione:",
+ "oc:tooltip.powerdistributor": "Distribuisce l'eenergia tra reti diverse. Questo è utile per la condivisione di energia immessa nel sistema da un convertitore tra le diverse sotto-reti che dovrebbero rimanere separati.",
+ "oc:tooltip.printedcircuitboard": "L'elemento di base per schede di espansione, per la memoria e così via.",
+ "oc:tooltip.rawcircuitboard": "Può essere indurito in qualsiasi forno o fornace compatibile.",
+ "oc:tooltip.redstone": "Permette la lettura e l'emissione di segnali di pietrarossa attorno tutto il blocco. Può essere controllato da qualsiasi computer che è collegato. Questo è fondamentalmente come una scheda di pietrarossa esterna.",
+ "oc:tooltip.redstonecard.ProjectRed": "§fProjectRed§7 è §asupportato§7.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 è §asupportato§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 è §asupportato§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "§fWireless Redstone (ChickenBones)§7 è §asupportato§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "§fWireless Redstone (SlimeVoid)§7 è §asupportato§7.",
+ "oc:tooltip.redstonecard": "Permette la lettura e l'emissione di segnali di pietrarossa attorno tutto il computer o robot.",
+ "oc:tooltip.robot": "A differenza dei computer, i robot possono muoversi e interagire con il mondo, molto simile a come può fare un giocatore. Tuttavia §onon§7 possono interagire con componenti esterni!U",
+ "oc:tooltip.robot_level": "§fLivelli§7: §a%s§7",
+ "oc:tooltip.robot_storedenergy": "§fEnergia immagazzinata§7: §a%s§7",
+ "oc:tooltip.screen": "Mostra del testo, contollato da una scheda grafica contenuta nel case del computer.\nRisoluzione massima: §f%sx%s§7\nProfondità di colore massima: §f%s§7",
+ "oc:tooltip.server": "Questo è un server, ci sono tanti come lui, ma questo può essere aggiornato con i componenti in modo simile a un case del computer. Può essere avviato inserendolo in un rack di server.",
+ "oc:tooltip.server.Components": "Componenti installati:",
+ "oc:tooltip.rack": "Permette l'installazione di un massimo di quattro server. Utilizzare un terminale remoto per accedere ai server contenuti in questo server rack.",
+ "oc:tooltip.switch": "Consente il collegamento di reti diverse tra loro. Solo i messaggi di rete saranno inoltrati attraverso il blocco, i componenti non saranno invece visibili Utilizzarlo per separare le reti pur consentendo la comunicazione utilizzando schede di rete, per esempio.",
+ "oc:tooltip.tablet": "Un computer tablet, per del Lua fresco in movimento. Può essere forzato lo spegnimento usandolo mentre si preme maiusc.",
+ "oc:tooltip.tabletcase": "Case di base per i tablet. Posizionarlo in assembler per aggiungere componenti e creare un tablet PC.",
+ "oc:tooltip.terminal": "Permette il controllo di un server in remoto, fino a quando si è nella portata di esso. Agisce come uno schermo portatile e una tastiera. Utilizzare i tasti maiusc-destro del mouse su un server in un rack di server per associare il terminale ad esso.",
+ "oc:tooltip.livello": "§8Livello %s",
+ "oc:tooltip.toolong": "Tenere premuto [§f%s§7] per un tooltip dettagliato.",
+ "oc:tooltip.transistor": "Un elemento fondamentale in molte altre parti del computer. È un po' contorto, ma fa il suo lavoro.",
+ "oc:tooltip.upgradeangel": "Consente ai robot di posizionare i blocchi nel nulla, anche se non vi è alcun blocco di riferimento.",
+ "oc:tooltip.upgradebattery": "Aumenta la quantità di energia che un robot è in grado di immagazzinare, permettendogli di lavorare più a lungo senza dover essere ricaricato.\ncapacità: §f%s§7",
+ "oc:tooltip.upgradechunkloader": "Se un robot si muove in una foresta e non c'è nessuno intorno per vederlo, si muove veramente? Questo aggiornamento consente di essere certi che lo faccia. Mantiene il chunk dove si trova il robot caricato, ma consuma continuamente energia, mentre è attivo.",
+ "oc:tooltip.upgradecontainercard": "Questo aggiornamento consente l'installazione e la rimozione di schede da un robot assemblato dinamicamente.\nLivello massimo: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "Questo aggiornamento consente l'installazione e la rimozione di upgrade da un robot assemblato dinamicamente.\nLivello massimo: §f%s§7",
+ "oc:tooltip.upgradecrafting": "Consente robot per utilizzare l'area in alto a sinistra del loro inventario per il crafting di oggetti. Gli oggetti devono essere allineati come sarebbero in un banco da lavoro.",
+ "oc:tooltip.upgradeexperience": "Questo aggiornamento consente di robot di accumulare esperienza, quando effettuano diverse operazioni. Maggiore è la loro esperienza, più energia sono in grado di memorizzare, più velocemente possono raccogliere blocchi e più efficientemente utilizzano gli strumenti.",
+ "oc:tooltip.upgradegenerator": "Può essere usato per generare energia dal combustibile mentre si è in movimento. Brucia oggetti per produrre energia nel corso del tempo, in base al loro valore di carburante.\n§fEfficienza§7: §a%s%%§7",
+ "oc:tooltip.upgradeinventory": "Questo aggiornamento fornisce spazio nell'inventario al robot. Senza uno di questi, i robot non saranno in grado di immagazzinare gli oggetti internamente.",
+ "oc:tooltip.upgradeinventorycontroller": "Questo aggiornamento permette al robot più controllo nel modo in cui interagisce con gli inventari esterni, e gli permette di scambiare il suo strumento equipaggiato con uno nel suo inventario.",
+ "oc:tooltip.upgradenavigation": "Può essere usato per determinare la posizione e l'orientamento del robot. La posizione è relativa al centro della mappa che è stata utilizzata per il crafting tale aggiornamento.",
+ "oc:tooltip.upgradepiston": "Questo aggiornamentp è molto spinto. Permette di spingere i blocchi, in modo simile ad un pistone. Tuttavia §lnon§7 muove le entità.",
+ "oc:tooltip.upgradesign": "Consente la lettura del testo e sulla scrittura del testo sui cartelli.",
+ "oc:tooltip.upgradesolargenerator": "Può essere usato per generare energia dalla luce del sole. Richiede una chiara linea di vista verso il cielo sopra il robot. Genera energia al %s%% della velocità di un motore Stirling.",
+ "oc:tooltip.upgradetank": "Questo aggiornamento fornisce un serbatoio per lo stoccaggio di liquidi al robot. Senza uno di questi, i robot non saranno in grado di immagazzinare i fluidi internamente.",
+ "oc:tooltip.upgradetankcontroller": "Questo aggiornamento permette al robot più controllo nel modo in cui interagisce con serbatoi esterni, e permette di trasferire i fluidi dentro e fuori dal serbatoio nel suo inventario.",
+ "oc:tooltip.upgradetractorbeam": "Dota il robot con tecnologia estremamente avanzata, soprannominato il \"Magnet Item\". Consente a raccogliere oggetti ovunque entro 3 blocchi dalla sua posizione.",
+ "oc:tooltip.wirelessnetworkcard": "Consente invio di messaggi wireless in aggiunta a quelli normali. È possibile regolare la §fpotenza del segnale§7 per controllare quanto lontano i messaggi vengono inviati. Una più elevata potenza del segnale richiede un maggior consumo energetico."
+}
diff --git a/src/main/resources/assets/opencomputers/lang/pt_BR.lang b/src/main/resources/assets/opencomputers/lang/pt_BR.lang
deleted file mode 100644
index 6ac0a419f5..0000000000
--- a/src/main/resources/assets/opencomputers/lang/pt_BR.lang
+++ /dev/null
@@ -1,490 +0,0 @@
-# This is the Brazilian portuguese translation based on master english file.
-#Author: Hilton W. Silva (hws689)
-# Updated by guilherme-puida in 03/01/2021
-
-# Blocks
-tile.oc.accesspoint.name=§cPonto de Acesso§7
-tile.oc.adapter.name=Adaptador
-tile.oc.assembler.name=Montador Eletrônico
-tile.oc.cable.name=Cabo
-tile.oc.capacitor.name=Capacitador
-tile.oc.carpetedCapacitor.name=Capacitador com Tapete
-tile.oc.case1.name=Gabinete (Nível 1)
-tile.oc.case2.name=Gabinete (Nível 2)
-tile.oc.case3.name=Gabinete (Nível 3)
-tile.oc.casecreative.name=Gabinete (Criativo)
-tile.oc.chameliumblock.name=Bloco Camaleão
-tile.oc.charger.name=Carregador
-tile.oc.disassembler.name=Desmontador
-tile.oc.diskdrive.name=Unidade de Disco
-tile.oc.endstone.name=Pedra do Fim
-tile.oc.geolyzer.name=Geonalizador
-tile.oc.hologram1.name=Projetor Holográfico (Nível 1)
-tile.oc.hologram2.name=Projetor Holográfico (Nível 2)
-tile.oc.keyboard.name=Teclado
-tile.oc.microcontroller.name=Microcontrolador
-tile.oc.motionsensor.name=Sensor de Movimento
-tile.oc.netsplitter.name=Divisor de Rede
-tile.oc.powerconverter.name=Conversor de Energia
-tile.oc.powerdistributor.name=Distribuidor de Energia
-tile.oc.print.name=Impressão 3D
-tile.oc.printer.name=Impressora 3D
-tile.oc.raid.name=Raid
-tile.oc.redstone.name= E/S de Redstone
-tile.oc.relay.name=Relé
-tile.oc.robot.name=Robô
-tile.oc.robotafterimage.name=Robô
-tile.oc.screen1.name=Monitor (Nível 1)
-tile.oc.screen2.name=Monitor (Nível 2)
-tile.oc.screen3.name=Monitor (Nível 3)
-tile.oc.rack.name=Rack
-tile.oc.switch.name=§cSwitch§7
-tile.oc.transposer.name=Transpositor
-tile.oc.waypoint.name=Ponto de Passagem
-
-# Items
-item.oc.abstractbuscard.name=Placa de Barramento Abstrata
-item.oc.acid.name=Grogue
-item.oc.alu.name=Unidade Lógica Aritmética (ULA)
-item.oc.analyzer.name=Analizador
-item.oc.apu0.name=Unidade de Processamento Acelerado (UPA) (Nível 1)
-item.oc.apu1.name=Unidade de Processamento Acelerado (UPA) (Nível 2)
-item.oc.apu2.name=Unidade de Processamento Acelerado (UPA) (Criativo)
-item.oc.arrowkeys.name=Setas do Teclado
-item.oc.buttongroup.name=Grupo de Botões
-item.oc.cardbase.name=Base de Cartão
-item.oc.chamelium.name=Camaleão
-item.oc.circuitboard.name=Placa de Circuito
-item.oc.componentbus0.name=Componente de Barramento (Nível 1)
-item.oc.componentbus1.name=Componente de Barramento (Nível 2)
-item.oc.componentbus2.name=Componente de Barramento (Nível 3)
-item.oc.componentbus3.name=Componente de Barramento (Criativo)
-item.oc.controlunit.name=Unidade de Controle (UC)
-item.oc.cpu0.name=Unidade Central de Processamento (CPU) (Nível 1)
-item.oc.cpu1.name=Unidade Central de Processamento (CPU) (Nível 2)
-item.oc.cpu2.name=Unidade Central de Processamento (CPU) (Nível 3)
-item.oc.cuttingwire.name=Fio de Corte
-item.oc.datacard0.name=Cartão de Dados (Nível 1)
-item.oc.datacard1.name=Cartão de Dados (Nível 2)
-item.oc.datacard2.name=Cartão de Dados (Nível 3)
-item.oc.debugcard.name=Cartão de Depuração
-item.oc.debugger.name=Depurador de Rede
-item.oc.diamondchip.name=Chip de Diamante
-item.oc.disk.name=Prato do Disco
-item.oc.diskdrivemountable.name=Unidade de Disco
-item.oc.drone.name=Drone
-item.oc.dronecase0.name=Carcaça de Drone (Nível 1)
-item.oc.dronecase1.name=Carcaça de Drone (Nível 2)
-item.oc.dronecase3.name=Carcaça de Drone (Criativo)
-item.oc.eeprom.name=EEPROM
-item.oc.floppydisk.name=Disquete
-item.oc.graphicscard0.name=Placa de Vídeo (Nível 1)
-item.oc.graphicscard1.name=Placa de Vídeo (Nível 2)
-item.oc.graphicscard2.name=Placa de Vídeo (Nível 3)
-item.oc.harddiskdrive0.name=Disco Rígido (Nível 1)
-item.oc.harddiskdrive1.name=Disco Rígido (Nível 2)
-item.oc.harddiskdrive2.name=Disco Rígido (Nível 3)
-item.oc.hoverboots.name=Botas Voadoras
-item.oc.inkcartridge.name=Cartucho de Tinta
-item.oc.inkcartridgeempty.name=Cartucho de Tinta (Vazio)
-item.oc.internetcard.name=Cartão de Internet
-item.oc.interweb.name=Interweb
-item.oc.ironnugget.name=Pepita de Ferro
-item.oc.linkedcard.name=Cartão Vinculado
-item.oc.manual.name=Manual do OpenComputers
-item.oc.memory0.name=Memória (Nível 1)
-item.oc.memory1.name=Memória (Nível 1.5)
-item.oc.memory2.name=Memória (Nível 2)
-item.oc.memory3.name=Memória (Nível 2.5)
-item.oc.memory4.name=Memória (Nível 3)
-item.oc.memory5.name=Memória (Nível 3.5)
-item.oc.microchip0.name=Circuito Integrado (Nível 1)
-item.oc.microchip1.name=Circuito Integrado (Nível 2)
-item.oc.microchip2.name=Circuito Integrado (Nível 3)
-item.oc.microcontrollercase0.name=Carcaça do Microcontrolador (Nível 1)
-item.oc.microcontrollercase1.name=Carcaça do Microcontrolador (Nível 2)
-item.oc.microcontrollercase3.name=Carcaça do Microcontrolador (Criativo)
-item.oc.nanomachines.name=Nanomáquinas
-item.oc.networkcard.name=Cartão de Rede
-item.oc.numpad.name=Teclado Numérico
-item.oc.present.name=Uma coisinha...
-item.oc.printedcircuitboard.name=Placa de Circuito Impresso (PCB)
-item.oc.rawcircuitboard.name=Placa de Circuito Crua
-item.oc.redstonecard0.name=Cartão de Redstone (Nível 1)
-item.oc.redstonecard1.name=Cartão de Redstone (Nível 2)
-item.oc.server0.name=Servidor (Nível 1)
-item.oc.server1.name=Servidor (Nível 2)
-item.oc.server2.name=Servidor (Nível 3)
-item.oc.server3.name=Servidor (Criativo)
-item.oc.tablet.name=Tablet
-item.oc.tabletcase0.name=Carcaça de Tablet (Nível 1)
-item.oc.tabletcase1.name=Carcaça de Tablet (Nível 2)
-item.oc.tabletcase3.name=Carcaça de Tablet (Criativo)
-item.oc.terminal.name=Terminal Remoto
-item.oc.terminalserver.name=Servidor de Terminal
-item.oc.texturepicker.name=Selecionador de Textura
-item.oc.transistor.name=Transistor
-item.oc.upgradeangel.name=Aprimoramento Angelical
-item.oc.upgradebattery0.name=Aprimoramento de Bateria (Nível 1)
-item.oc.upgradebattery1.name=Aprimoramento de Bateria (Nível 2)
-item.oc.upgradebattery2.name=Aprimoramento de Bateria (Nível 3)
-item.oc.upgradechunkloader.name=Aprimoramento de Chunkloader
-item.oc.upgradecontainercard0.name=Contêiner de Cartão (Nível 1)
-item.oc.upgradecontainercard1.name=Contêiner de Cartão (Nível 2)
-item.oc.upgradecontainercard2.name=Contêiner de Cartão (Nível 3)
-item.oc.upgradecontainerupgrade0.name=Aprimoramento de Contêiner (Nível 1)
-item.oc.upgradecontainerupgrade1.name=Aprimoramento de Contêiner (Nível 2)
-item.oc.upgradecontainerupgrade2.name=Aprimoramento de Contêiner (Nível 3)
-item.oc.upgradecrafting.name=Aprimoramento de Construção
-item.oc.upgradedatabase0.name=Aprimoramento de Banco de Dados (Nível 1)
-item.oc.upgradedatabase1.name=Aprimoramento de Banco de Dados (Nível 2)
-item.oc.upgradedatabase2.name=Aprimoramento de Banco de Dados (Nível 3)
-item.oc.upgradeexperience.name=Aprimoramento de Experiência
-item.oc.upgradegenerator.name=Aprimoramento de Gerador
-item.oc.upgradehover0.name=Aprimoramento de Flutuação (Nível 1)
-item.oc.upgradehover1.name=Aprimoramento de Flutuação (Nível 2)
-item.oc.upgradeinventory.name=Aprimoramento de Inventário
-item.oc.upgradeinventorycontroller.name=Aprimoramento de Controlador de Inventário
-item.oc.upgradeleash.name=Aprimoramento de Correia
-item.oc.upgradeMF.name=MFU
-item.oc.upgradenavigation.name=Aprimoramento de Navegação
-item.oc.upgradepiston.name=Aprimoramento de Pistão
-item.oc.upgradesign.name=Aprimoramento de Sinal de E/S
-item.oc.upgradesolargenerator.name=Aprimoramento de Gerador Solar
-item.oc.upgradetank.name=Aprimoramento de Tanque
-item.oc.upgradetankcontroller.name=Aprimoramento de Controlador de Tanque
-item.oc.upgradetractorbeam.name=Aprimoramento de Raio Trator
-item.oc.upgradetrading.name=Aprimoramento de Troca
-item.oc.wirelessnetworkcard0.name=Cartão de Rede Sem Fio (Nível 1)
-item.oc.wirelessnetworkcard1.name=Cartão de Rede Sem Fio (Nível 2)
-item.oc.worldsensorcard.name=Cartão de Sensor de Mundo
-item.oc.wrench.name=Chave de fenda-boca
-
-# Entities
-entity.oc.Drone.name=Drone
-
-# GUI
-oc:gui.Analyzer.Address=§6Endereço§f: %s
-oc:gui.Analyzer.AddressCopied=Endereço copiado para a área de transferência.
-oc:gui.Analyzer.ChargerSpeed=§6Velocidade da carga§f: %s
-oc:gui.Analyzer.ComponentName=§6Nome do componente§f: %s
-oc:gui.Analyzer.Components=§6Número de componentes conectados§f: %s
-oc:gui.Analyzer.CopyToClipboard=Clique para copiar para a área de transferência.
-oc:gui.Analyzer.LastError=§6Último erro§f: %s
-oc:gui.Analyzer.RobotName=§6Nome§f: %s
-oc:gui.Analyzer.RobotOwner=§6Dono§f: %s
-oc:gui.Analyzer.RobotXp=§6Experiência§f: %s (Nível %s)
-oc:gui.Analyzer.StoredEnergy=§6Energia armazenada§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Total de energia armazenada§f: %s
-oc:gui.Analyzer.Users=§6Usuários§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Força do sinal§f: %s
-oc:gui.Assembler.Collect=Saída do coletador
-oc:gui.Assembler.Complexity=Complexidade: %s/%s
-oc:gui.Assembler.InsertCase=Insira uma parte base
-oc:gui.Assembler.InsertCPU=Insira uma CPU
-oc:gui.Assembler.InsertRAM=Insira alguma RAM
-oc:gui.Assembler.Progress=Progresso: %s%% (%s)
-oc:gui.Assembler.Run=Montar
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=Placa de Vídeo
-oc:gui.Assembler.Warning.Inventory=Aprimoramento de Inventário
-oc:gui.Assembler.Warning.Keyboard=Teclado
-oc:gui.Assembler.Warning.OS=Mídia Inicializável
-oc:gui.Assembler.Warning.Screen=Monitor
-oc:gui.Assembler.Warnings=§eAtenção§7: Componentes recomendados ausentes.
-oc:gui.Chat.NewVersion=Uma nova versão está disponível: %s
-oc:gui.Chat.TextureName=§7Nome da textura é §a%s§f.
-oc:gui.Chat.WarningClassTransformer=Houve um erro §cerros§f ao rodar o 'class transformer'. Por favor relate isso, junto com o seu arquivo de log (completo!) FML §alatest.log§f/§afml-server-latest.log§f , obrigado!
-oc:gui.Chat.WarningFingerprint=§cATENÇÃO§f - impressão digital não reconhecida! Experado '§a%s§f' mas recebido '§e%s§f'. A não ser que você seja um desenvolvedor e esteja rodando uma versão desofuscada, é §lextremamente§f recomendável que baixe novamente o OpenComputers, por que o JAR que está usando talvez esteja adulterado.
-oc:gui.Chat.WarningLink=Não foi possível abrir o atalho: %s
-oc:gui.Chat.WarningLuaFallback=Bibliotecas nativas do Lua não disponíveis, computadores não serão capazes de persistir seus estados. Eles reinicializarão quando chunks descarregarem.
-oc:gui.Chat.WarningProjectRed=Você está usando uma versão do Project: Red que é incompativel com OpenComputers. Tente atualizar sua versão do Project: Red.
-oc:gui.Chat.WarningRecipes=Houve erros ao carregar uma ou mais receitas. Alguns itens não poderão ser construídos. Verifique seu arquivo de log para mais informações.
-oc:gui.Chat.WarningSimpleComponent=Um addon (seu?) usa a interface §aSimpleComponent§f que faz §ealgo errado§f. A lógica de componente não pode ser injetada. Por favor verifique seu arquivo de log para mais informações.
-oc:gui.Drive.Managed=Gerenciado
-oc:gui.Drive.Unmanaged=Não Gerenciado
-oc:gui.Drive.ReadOnlyLock=Bloqueado
-oc:gui.Drive.ReadOnlyLockWarning=§Somente leitura§r. Isso não pode ser removido, exceto quando o disco é formatado.
-oc:gui.Drive.Warning=§lAtençaõ§r: mudança de modos resultará em perca de todos os dados do disco!
-oc:gui.Error.ComponentOverflow=Muitos componentes conectados ao computador.
-oc:gui.Error.InternalError=Erro interno, por favor veja o arquivo de log. Isto é provavelmente um erro.
-oc:gui.Error.NoCPU=Não há CPU instalada no computador.
-oc:gui.Error.NoEnergy=Energia insuficiente.
-oc:gui.Error.NoRAM=Não há RAM instalada no computador.
-oc:gui.Error.OutOfMemory=Sem memória.
-oc:gui.Manual.Blocks=Blocos do OpenComputers
-oc:gui.Manual.Home=Início
-oc:gui.Manual.Items=Itens do OpenComputers
-oc:gui.Manual.Warning.BlockMissing=Bloco indisponível.
-oc:gui.Manual.Warning.ImageMissing=Imagem não encontrada.
-oc:gui.Manual.Warning.ItemMissing=Item indisponível.
-oc:gui.Manual.Warning.OreDictMissing=Entrada no dicionário de minérios indisponível.
-oc:gui.Raid.Warning=§4Adicionar um disco o formata.[nl] Remover um disco limpa a raid.
-oc:gui.Robot.Power=Energia
-oc:gui.Robot.TurnOff=Desligar
-oc:gui.Robot.TurnOn=Ligar[nl]§7Use um Analizador para verficar problemas.§r
-oc:gui.Rack.Back=Voltar
-oc:gui.Rack.Bottom=Baixo
-oc:gui.Rack.Left=Esquerda
-oc:gui.Rack.None=Nenhum
-oc:gui.Rack.Right=Direita
-oc:gui.Rack.Enabled=Habilitado
-oc:gui.Rack.Disabled=Disabilitado
-oc:gui.Rack.RelayModeTooltip=Modo de relé
-oc:gui.Rack.Top=Cima
-oc:gui.Switch.PacketsPerCycle=Pacotes / ciclo
-oc:gui.Switch.QueueSize=Tamanho da fila
-oc:gui.Switch.TransferRate=Taxa do ciclo
-oc:gui.Terminal.InvalidKey=Chave inválida, provavelmente outro terminal foi conectado ao servidor.
-oc:gui.Terminal.OutOfRange=Sem sinal.
-
-# Containers
-oc:container.accesspoint=Ponto de Acesso
-oc:container.adapter=Adaptador
-oc:container.case=Computador
-oc:container.charger=Carregador
-oc:container.disassembler=Desmontador
-oc:container.diskdrive=Unidade de disco
-oc:container.printer=Impressora
-oc:container.raid=Raid
-oc:container.relay=Relé
-oc:container.server=Servidor
-oc:container.rack=Rack
-oc:container.switch=Switch
-oc:container.tabletwrapper=Tablet
-
-# Keybinds
-key.clipboardPaste=Colar da área de transferência
-key.materialCosts=Mostrar custo dos materiais
-
-# Item / Block Tooltips
-oc:tooltip.accesspoint=Atua como um Switch, mas adicionalmente recebe pacotes sem fio e retransmite pacotes com fio sem fio.
-oc:tooltip.abstractbuscard=Permite interagir com o barramento abstrato de §fStargateTech 2§7 enviando e recebendo pacotes LIP.
-oc:tooltip.acid=Um pseudo-liquido altamente tóxico, usualmente consumidos por alguns piratas (ihic!). Também, todavia, pode ser útil de outros modos.
-oc:tooltip.adapter=Usado para controlar blocos que não são componentes, tal como blocos vanillas ou de outros mods.
-oc:tooltip.alu=Adiciona números que você não têm. Bem melhor assim.
-oc:tooltip.analyzer=Usado para mostrar informações sobre os blocos, tal como seu §fendereço§7 e §fnome do componente§7.[nl] Também mostra o erro que causou um computador travar se não foi desligado normalmente.
-oc:tooltip.apu=Isso é um CPU com um GPU integrado (ou IGP), quando você apenas precisa deste slot de placa .[nl] Componentes Suportados: §f%s§7[nl] Resolução mãxima: §f%sx%s§7[nl] Densidade de cores máxima: §f%s§7[nl] Operações/tick: §f%s§7
-oc:tooltip.assembler=Permite construir robôs e outros dispositivos com várias partes de computador.
-oc:tooltip.cable=Uma maneira barata de conectar os blocos.
-oc:tooltip.capacitor=Armazena energia para usar mais tarde. Pode ser enchido e esvaziado rapidamente.
-oc:tooltip.cardbase=Como o nome diz, este é o bloco de construção básico para os cartões de expansão.
-oc:tooltip.carpetedcapacitor=Armazena energia para uso posterior. Pode ser carregado e descarregado rapidamente. Carrega quando uma ovelha ou jaguatirica anda sobre o mesmo.
-oc:tooltip.case=O gabinete é o bloco básico para computadores e guarda os §fcartões de extensão§7, §fRAM§7 e §fdiscos rígidos§7.[nl] Slots: §f%s§7
-oc:tooltip.chamelium=Matéria prima para as imressões 3D. Não ingerir: talvez leve a cegueira e um lapso temporário de presença.
-oc:tooltip.chameliumblock=Agradável e Limpo. Usado para formas coloridas nas impressões 3D, ou para simplesmente ter, um bloco colorido para decorar sua linda e chamativa base.
-oc:tooltip.charger=Transfere energia dos capacitores para robôs e drones adjacentes. A taxa de energia depende do §fsinal de redstone§7 vindo, onde sem sinal não carrega os dispositivos, e quanto mais forte o sinal maior será a velocidade de carregamento. Pode ser usado também para carregar tablets e unidades de disco de acesso em tablets.
-oc:tooltip.circuitboard=Agora estamos chegando em algum lugar. Pode ser cozido para obter uma placa de circuito impresso.
-oc:tooltip.controlunit=Está é a unidade que... controla... coisas. Você precisa disso para construir a CPU. Então é tipo, totalmente importante.
-oc:tooltip.componentbus=Está expansão permite aos servidores comunicarem com mais componentes ao mesmo tempo, similar como os CPUs fazem.[nl] Componentes Suportados: §f%s§7
-oc:tooltip.cpu=Um componente essencial para todos os computadores. O clock (relógio/taxa do processamento) é um tanto quanto que duvidoso, mas o que você espera se ele roda num relógio de sol de bolso?[nl] Componentes Suportados: §f%s§7
-oc:tooltip.cpu.Architecture=Arquitetura: §f%s§7
-oc:tooltip.cuttingwire=Usado para cortar blocos de argila em formato de placas de circuito. Quebra quando usa, o que provavelmente é a pior ferramenta de todas.
-oc:tooltip.datacard0=Provê um conjuto de algoritmos tal como hash e desinflar/inflar.
-oc:tooltip.datacard1=Provê um conjuto de algoritmos tal como hash, encriptação AES e desinflar/inflar.
-oc:tooltip.datacard2=Provê um conjuto de algoritmos tal como hash, encriptação AES, criptografia de curva elíptica e desinflar/inflar.
-oc:tooltip.debugcard=Item do modo criativo, permite manipular o mundo para fazer testes facieis. Use por sua conta e risco.
-oc:tooltip.debugger=Pode ser usado para depurar informações na grade de rede interna do OC. Somente use se for instruído por um desenvolvedor.
-oc:tooltip.diamondchip=Um pedacinho de um diamante uma vez impecável. Ele nunca será o mesmo de novo.
-oc:tooltip.disassembler=Separa os itens em seus componentes originais. §lAtenção§7: o item retornado tem uma chance de %s%% de quebrar no processo!
-oc:tooltip.disk=Uma mídia primitiva que pode ser usada para construir dispositvos de armazenamentos contínuos.
-oc:tooltip.diskdrive.CC=Disquetes do ComputerCraft são §asuportados§7.
-oc:tooltip.diskdrive=Permite escrever e ler disquetes. Pode ser instalado em robôs para permitir inserir disquetes mais tarde.
-oc:tooltip.diskdrivemountable=Provê a mesma funcionalidade de uma unidade de disco normal, mas só pode ser instalado em um rack.
-oc:tooltip.diskusage=Uso de disco: %s/%s Byte
-oc:tooltip.disklocked=Bloqueado por: %s
-oc:tooltip.diskmodemanaged=Modo: Gerenciado
-oc:tooltip.diskmodeunmanaged=Modo: Não gerenciado
-oc:tooltip.drone=Drones são leves, com reconhecimento rápido de unidades com espaço interno limitado.
-oc:tooltip.dronecase=Está carcaça é usada para montar drones no montador. Ele tem um espaço para uma pequena quantidade de componentes e provê levitação com a pedra do fim.
-oc:tooltip.eeprom=Pequeno armazenamento programável que contem a BIOS dos computadores usado para iniciá-los.
-oc:tooltip.fakeendstone=Quase igual a coisa real, emula até mesmo sua levitação!
-oc:tooltip.geolyzer=Permite escanear a dureza da área ao redor de blocos sólidos. Essa informação pode ser útil para geração de hologramas de área ou para detectar minérios.
-oc:tooltip.graphicscard=Usado para mudar o que é mostrado nos monitores.[nl] Máxima resolução: §f%sx%s§7[nl] Máxima profundidade de cores: §f%s§7[nl] Operações/tick: §f%s§7
-oc:tooltip.hoverboots=Pule alto, caia devagar, caminhe melhor. Isso e mais, com as mais novas e patenteadas Botas Voadoras (TM).
-oc:tooltip.inkcartridge=Usado para carregar tinta nas impressoras 3D. Por razões misteriosas ele não tem que permanecer na impressora.
-oc:tooltip.inkcartridgeempty=Este cartucho de tinta foi usado até secar. Recarregue isso usando corantes. Ou jogue-o fora. Veja minha cara de preocupado -.-.
-oc:tooltip.internetcard=Este cartão faz requisições HTTP usa protocolos TCP reais.
-oc:tooltip.interweb=Parabéns, você ganhou um (1) interweb. Você pode conectar a isso usando um Cartão de Internet. Cuidado: não alimente os trolls.
-oc:tooltip.ironnugget=Uma pepita feita de ferro, por isso é chamado de Pepita de Ferro, darrr...
-oc:tooltip.keyboard=Pode ser anexados aos monitores para permitir digitar neles.
-oc:tooltip.hologram0=Uma exibição volumétrica que pode ser controlado por computadores para exibir estruturas de voxel arbitrárias.[nl] Resolução: §f48x32x48§7 [nl] Escala máxima: §f3x§7 [nl] Profundidade de cores: §fMonocromatico§7
-oc:tooltip.hologram1=Uma exibição volumétrica que pode ser controlado por computadores para exibir estruturas de voxel arbitrárias.[nl] Resolução: §f48x32x48§7 [nl] Escala máxima: §f4x§7 [nl] Profundidade de cores: §fTricolor§7
-oc:tooltip.linkedcard=Eles são construidos em pares, e só pode comunicar-se com seu par. Entretanto, eles podem se comunicar em qualquer distância, e também cruzar dimensões. A energia requerida para enviar a mensagem é altíssima.
-oc:tooltip.linkedcard_channel=§8Canal: %s§7
-oc:tooltip.manual=Toda informaçâo que você provalvemente precisará do OpenComputers. E mais. Por um preço inacreditável de... §opor favor pressiona R para continuar§7.
-oc:tooltip.materialcosts=Segure [§f%s§7] para custos do material.
-oc:tooltip.materials=Materiais:
-oc:tooltip.memory=Requerida para fazer os computadores funcionarem. Quanto mais tiver, mais complexos podem ser os programas.
-oc:tooltip.microchip=Um chip conhecido formalmente como Circuito Integrado. Eu não tenho ideia porque isso funciona com redstone, mas funciona.
-oc:tooltip.microcontroller=Microcontroladores são mini computadores. Eles são usadas para cuidar de tarefas específicas, rodando um único programa que é provido pela EEPROM consruida dentro dele.[nl] §cNão pode conectar com componentes externos.§7
-oc:tooltip.microcontrollercase=Componente básico para construir microcontroladores. Coloque-o em um montador para adicionar novos componentes e montar um microcontrolador.
-oc:tooltip.motionsensor=Pode detectar movimento de formas de vidas próximas. Requer visão direta.
-oc:tooltip.nanomachines=Unidade de controle e um grupo de nanomáquinas pra ingerir, se você tiver coragem.
-oc:tooltip.networkcard=Permite que computadores distantes conectem por outros blocos (como cabos) para comunicar-se enviando mensagens um para o outro.
-oc:tooltip.poweracceptor=Velocidade da conversão de energia: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fBuildCraft MJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fCarregamento do Factorization§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fIndustrialCraft² EU§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fMekanism Joules§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fThermal Expansion RF§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=Converte energia de outros mods para o tipo de energia interna. Taxa de conversão:
-oc:tooltip.powerdistributor=Distribui energia por meio de diferentes redes. Isto é útil para compartilhar fluxo de energia de seu sistema para outro conversor em diferentes sub-redes que podem manter separados.
-oc:tooltip.present=... para seus problemas. Abra este presente para ter uma chance de receber §kum grande tesouro§7![nl]§8Construa itens do OpenComputers para ter uma chance de receber presente.§7
-oc:tooltip.print.BeaconBase=§8Funciona como uma base do sinalizador.
-oc:tooltip.print.LightValue=§8Luz emitida: %s.
-oc:tooltip.print.RedstoneLevel=§8Saída da Redstone: %s.
-oc:tooltip.printedcircuitboard=O bloco de construção básico para cartões de expansão, memória e outros.
-oc:tooltip.printer=Permite imprimir blocos com forma definida pelo usuário usando o Camaleão (nome lindo?) e Cartucho de Tinta. Deve ser configurado usando um computador. Deixe longe do alcance das crianças. Porque sim.
-oc:tooltip.raid=Permite cobinar três discos rigídos em um único grande arquivo de sistema que pode ser usado por todos os computadores conectados.
-oc:tooltip.rawcircuitboard=Pode ser endurecido em qualquer fornalha compátivel.
-oc:tooltip.redstone=Permite ler e emitir sinais de redstone ao redor do bloco. Pode ser controlado por qualquer computador que o bloco estiver conectado. Isto é básicamente um cartão de redstone externo.
-oc:tooltip.redstonecard.ProjectRed=§fProjectRed§7 é §asuportado§7.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 é §asuportado§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 é §asuportado§7.
-oc:tooltip.redstonecard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 é §asuportado§7.
-oc:tooltip.redstonecard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 é §asuportado§7.
-oc:tooltip.redstonecard=Permite ler e emitir sinais de redstone ao redor do robô computadorizado.
-oc:tooltip.relay=Permite conectar diversas redes uma com a outra. Somente mensagens de rede serão passadas, componentes não serão vísiveis através disto. Use para separar redes e continuar permitindo comunicação usando Cartões de Rede, por exemplo.
-oc:tooltip.robot=Diferente de computadores, robôs podem mover-se por ai e interagir com o mundo parecido com o que um jogador faz.[nl] §cNão pode conectar-se com componentes externos.§7
-# The underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fNível§7: §a%s§7
-oc:tooltip.robot_storedenergy=§fEnergia armazenada§7: §a%s§7
-oc:tooltip.screen=Mostra texto, controlado por uma placa de vídeo em um Gabinete.[nl] Resolução máxima: §f%sx%s§7[nl] Densidade máxima: §f%s§7
-oc:tooltip.server=Isto é um servidor: existem muitos como este, mas este pode ser aprimorado com componentes como um gabinete pode ser. Ele pode ser ligado inserindo-o em um rack de servidor.
-oc:tooltip.server.Components=Componentes instalados:
-oc:tooltip.rack=Permite a instalação de até quatro servidores ou outros montáveis.
-oc:tooltip.switch=Permite conectar várias redes uma com a outra. Somente mensagens de rede serão transmitidas, componentes não serão vísiveis. Use-o para separar redes permitindo comunicação usando Cartões de Rede, por exemplo.
-oc:tooltip.tablet=Um tablet, para usar Lua de maneira portátil. Pode ser forçado a desligar se abaixando e ativando-o.
-oc:tooltip.tabletcase=Carcaça básica para tablets. Coloque-o no montador para adicionar componentes e criar um tablet.
-oc:tooltip.terminal=Permite controlar um servidor remotamente, enquanto estiver no seu alcance. Atua como monitor e teclados portateis. Shift + Botão Direito em um servidor em um rack para vincular um terminal.
-oc:tooltip.terminalserver=Backend para que Terminais remotos possam ser conectados para prover controle remoto. Contém um monitor virtual e um teclado.
-oc:tooltip.texturepicker=Esta ferramente mostra uma string descrevendo uma superfície de bloco, para usar na impressora 3D e definir formas. Não são nomes de texturas, nana nina não.
-oc:tooltip.tier=§8Nível %s
-oc:tooltip.netsplitter=Atua como um conector dinâmico. Conectividade de cada lado pode ser mudada batendo-a com uma chave. Conectividade de todos os lados podem ser invertidas aplicando um sinal de redstone.
-oc:tooltip.toolong=Segure [§f%s§7] para uma dica detalhada.
-oc:tooltip.transistor=Um elemento básico para outras partes de computador. É um pouco torto, mas faz seu trabalho.
-oc:tooltip.transposer=Permite transferir automaticamente itens e fluidos entre inventários adjacentes e recipientes de fluidos.
-oc:tooltip.upgradeangel=Permite que robôs coloquem blocos no ar, mesmo sem um ponto de apoio.
-oc:tooltip.upgradebattery=Aumenta a quantidade de energia que o dispositivo pode armazenar, permitindo que trabalhe mais tempo sem precisa recarregar. [nl] Capacidade: §f%s§7
-oc:tooltip.upgradechunkloader=Se um robô move-se em uma floresta e ninguém é capaz de ver ele, ele está se mexendo ou não? Este aprimoramento faz ter certeza que sim. Isto mantêm um chunk em que um dispositvo está carregado, mas consome energia continuamente enquanto ativo.
-oc:tooltip.upgradecontainercard=Este aprimoramento de contêiner permite dinamicamente instalar e remover um cartão de um dispositivo montado. [nl] Nível máximo: §f%s§7
-oc:tooltip.upgradecontainerupgrade=Este aprimoramento de contêiner permite dinamicamente instalar e remover outro aprimoramento de um dispositivo montado. [nl] Nível máximo: §f%s§7
-oc:tooltip.upgradecrafting=Permite que robôs usem o canto superior esquerdo de seu inventário para construir objetos. Os itens devem estar posicionados como se estivessem numa mesa de trabalho.
-oc:tooltip.upgradedatabase=Este aprimoramento permite armazenar informação de pilha de itens para ser usado por outros componentes.[nl] Entradas suportadas: §f%s§7
-oc:tooltip.upgradeexperience=Este aprimoramento permite que robôs acumulem experiência efetuando diversas operações. Quanto mais experiência estiver, mais energia pode armazenar, mais rápido pode cortar blocos e mais efeciente ele usa as ferramentas.
-oc:tooltip.upgradegenerator=Pode ser usado para gerar combustível em movimento. Queima itens para gerar energia o tempo todo, baseado em seus valores de combustível.[nl] §fEfeciencia§7: §a%s%%§7
-oc:tooltip.upgradehover=Este aprimoramento permite que robôs voem acima do solo sem precisar escalar paredes.[nl] Altura máxima: §f%s§7
-oc:tooltip.upgradeinventory=Este aprimoramento provê espaço no inventário para robôs ou drones. Sem um destes, eles não serão capazes de armazenar itens internamente.
-oc:tooltip.upgradeinventorycontroller=Este aprimoramento permite que robôs e drones tenham mais controle de como eles interagem com o inventário externo, e permite que robôs troquem sua ferramenta equipada com algum item do seu inventário.
-oc:tooltip.upgrademf=Permite que adaptadores acessem blocos não adjacentes.
-oc:tooltip.upgrademf.Linked=§fConexão estabelecida§7
-oc:tooltip.upgrademf.Unlinked=§fSem conexão§7
-oc:tooltip.upgradeleash=Permite que alguns dispostivos, como drones, coloquem animais em coleiras. MUITOSSSS ANIMAIIIIIIss.
-oc:tooltip.upgradenavigation=Pode ser usado para determinar a posição e orientação de um dispositivo. A posição é relativa ao centro do mapa que foi usado para construir este aprimoramento.
-oc:tooltip.upgradepiston=Este aprimoramento tem um movimento agressivo. Permite mexer blocos, como se estivesse usando um pistão. Isto §lnão§7 move entidades.
-oc:tooltip.upgradesign=Permite ler e escrever em placas de texto.
-oc:tooltip.upgradesolargenerator=Pode ser usado para gerar energia solar em movimento. Requer uma linha de visão limpa do céu acima do dispositivo. Gera energia em %s%% da velocidade de um Motor Stirling.
-oc:tooltip.upgradetank=Este aprimoramento provê um armazenamento de tanque ou fluidos para robôs e drones. Sem um destes, ele não será capaz de armazenar fluidos internamente.
-oc:tooltip.upgradetankcontroller=Este aprimoramento permite que robôs e drones tenham mais controle de como eles interagem com tanques externos, e permite que ele transfira fluidos para os tanques e dos tanques.
-oc:tooltip.upgradetractorbeam=Equipa um dispositivo com uma tecnologia extremamente avançada, codenome "Imã". Permite que dispositivos capturem blocos com o raio de 3 blocos de sua localização.
-oc:tooltip.upgradetrading=Permite que robôs e drones façam trocas com Aldeões.
-oc:tooltip.waypoint=Provê um ponto de referência para os dispositvos com um aprimoramento de navegação.
-oc:tooltip.wirelessnetworkcard=Permite enviar mensagens de rede além do meio normal. Você pode ajustar a §fforça do sinal§7 para controlar o quão longe as mensagens vão. Altos níveis de força de sinal resulta em alto consumo de energia.
-oc:tooltip.worldsensorcard=Permite ler informações sobre o mundo, como gravidade e/ou se tem uma atmosfera respirável. Use os resultados por sua conta e risco. O fabricando não se responsabiliza por danos corporais ou materias por decisões causadas sobre as saídas dos cartões. Nós temos advogados. E dinheiro. Então nem tente.
-oc:tooltip.wrench=Um híbrido entre uma Chave de fenda e uma Chave de boca, esta ferramenta é fácil de usar, mas díficil de dominar.
-
-#Achievements
-achievement.oc.adapter=Ai que delicia cara.
-achievement.oc.adapter.desc=Interagiu com blocos de outros mods e também do Minecraft vanilla!
-achievement.oc.assembler=Explêndido
-achievement.oc.assembler.desc=Hora de dominar o mundo!
-achievement.oc.cable=Não é um Fio Sujo
-achievement.oc.cable.desc=Com a tecnologia patenteada de anti-espaguete.
-achievement.oc.capacitor=Baterias inclusas
-achievement.oc.capacitor.desc=Você não pode parar isso.
-achievement.oc.card=Aceitamos Cartões
-achievement.oc.card.desc=Para sua conveniência. Sem segundas intenções, prometo.
-achievement.oc.case=Em Caso de Problemas
-achievement.oc.case.desc=Porque torres quadradas são as melhores.
-achievement.oc.charger=Tá bom, vamo lá
-achievement.oc.charger.desc=Carrreeegaaaan- poxa, esqueci do sinal de redstone de novo.
-achievement.oc.chip=Todas as Pequenas Coisas
-achievement.oc.chip.desc=Porque tubos a vácuo são coisa do passado.
-achievement.oc.cpu=Overclocked
-achievement.oc.cpu.desc=Hora de fazer uso destes ciclos computacionais.
-achievement.oc.disassembler=Vamo quebra tudo!
-achievement.oc.disassembler.desc=Caso suas ideias brilhantes não sejam tão brilhantes assim.
-achievement.oc.diskDrive=Roda a Roda.
-achievement.oc.diskDrive.desc=Capacidade inferior mas um som lindíssimo.
-achievement.oc.drone=Voando alto.
-achievement.oc.drone.desc=Mantenha a calma e jogue-o para fora do planeta.
-achievement.oc.eeprom=Só pode ter um
-achievement.oc.eeprom.desc=Por computador, claro. Para manter a ordem da inicialização, entendeu?
-achievement.oc.floppy=Um ri- disco
-achievement.oc.floppy.desc=Velho, mas ainda funciona.
-achievement.oc.geolyzer=Pra dentro da Terra
-achievement.oc.geolyzer.desc=Têm qualidades extraordinárias.
-achievement.oc.graphicsCard=Ultima Geração
-achievement.oc.graphicsCard.desc=Assim pode ser ... ann... rendereziado. Ah sim sim.
-achievement.oc.hdd=HDD Melhor que HD
-achievement.oc.hdd.desc=Não espere, não é isso que significa. Bom, você entendeu...
-achievement.oc.hologram=Próxima Dimensão
-achievement.oc.hologram.desc=Porque 2D é chato. Ou não é?
-achievement.oc.keyboard=PegadorDeSujeira3000
-achievement.oc.keyboard.desc=É altamente recomendável resistir o impulso de girar eles no ar.
-achievement.oc.microcontroller=Irmanzinha
-achievement.oc.microcontroller.desc=O irmãozinho do computador.
-achievement.oc.motionSensor=Mexe ae que quero vê
-achievement.oc.motionSensor.desc=Igual a Steve Swagger.
-achievement.oc.networkCard=Agora Estamos Falando!
-achievement.oc.networkCard.desc=Mantenha contato com esses parentes distantes.
-achievement.oc.openOS=Buti
-achievement.oc.openOS.desc=Um SO para - espere, já usei essa antes? Droga.
-achievement.oc.powerDistributor=Compartilhar é Amar
-achievement.oc.powerDistributor.desc=Quando você precisa de ajuda para equilibrar toda essa energia.
-achievement.oc.rack=Mas que potência
-achievement.oc.rack.desc=Sim, os racks de servidores são potentes.
-achievement.oc.raid=LFG
-achievement.oc.raid.desc=Heroíco valeuflws.
-achievement.oc.ram=Random Access Memories (Memórias de Acesso Aleatório)
-achievement.oc.ram.desc=Parabéns, Você está fazendo isso certo.
-achievement.oc.redstoneCard=Con... tato
-achievement.oc.redstoneCard.desc=Hora de ser análogo.
-achievement.oc.redstoneIO=Hello from the outside...
-achievement.oc.redstoneIO.desc=Levando os sinais de redstone para onde quiser.
-achievement.oc.robot=Bip Bip
-achievement.oc.robot.desc=EXTERMINAR!
-achievement.oc.screen=Tentou desligar e ligar de novo?
-achievement.oc.screen.desc=Não, de verdade. Um pulso de redstone pode alternar o monitor entre ligado e desligado.
-achievement.oc.server=Dedicado
-achievement.oc.server.desc=Servidores na nuvem, aqui vamos nós.
-achievement.oc.switch=Topologia Complexa
-achievement.oc.switch.desc=Evite embalagens baratas devido a possibilidade de pacotes perdidos.
-achievement.oc.tablet=Não Engula
-achievement.oc.tablet.desc=Mantenha longe do alcance das crianças para evitar cobranças exageradas no seu cartão de crédito.
-achievement.oc.transistor=Onipresente
-achievement.oc.transistor.desc=Crie um Transistor para começar.
-achievement.oc.wirelessNetworkCard=Sinais
-achievement.oc.wirelessNetworkCard.desc=Hora de ir onde nenhum pacote foi antes.
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code.
-death.attack.oc.nanomachinesOverload.1=%s foi muito ganancioso.
-death.attack.oc.nanomachinesOverload.2=%s teve um ataque de nervos.
-death.attack.oc.nanomachinesOverload.3=As nanomáquinas de %s estão fora de controle.
-death.attack.oc.nanomachinesHungry.1=%s foi comido por nanomáquinas.
-death.attack.oc.nanomachinesHungry.2=%s não alimentou suas nanomáquinas.
-death.attack.oc.nanomachinesHungry.3=%s foi digerido.
-
-# NEI Integration
-nei.options.inventory.oredict=Mostre nomes do OreDictionary
-nei.options.inventory.oredict.true=Sim
-nei.options.inventory.oredict.false=Não
-nei.usage.oc.Manual=Open Manual
-
-# Waila Integration
-option.oc.address=Endereço
-option.oc.componentName=Nome do Componente
-option.oc.energy=Energia
diff --git a/src/main/resources/assets/opencomputers/lang/pt_PT.lang b/src/main/resources/assets/opencomputers/lang/pt_PT.lang
deleted file mode 100644
index 23e0772fe6..0000000000
--- a/src/main/resources/assets/opencomputers/lang/pt_PT.lang
+++ /dev/null
@@ -1,137 +0,0 @@
-# This is the portuguese lang file, adapted from the english master file.
-#
-# CHANGES:
-# LordFokas (6-JAN-2014): first translation from en_US to pt_PT.
-# It's not perfect, but it's hard to translate, especially because
-# given I'm a Computer Science Engineering student, I tend to mix in
-# technical english words. I suggest someone less involved with CSE to
-# try and revise my translation.
-#
-#########################################################################
-
-
-# Blocks
-tile.oc.adapter.name=Adaptador
-tile.oc.cable.name=Cabo
-tile.oc.capacitor.name=Condensador
-tile.oc.case1.name=Caixa Básica
-tile.oc.case2.name=Caixa Avançada
-tile.oc.case3.name=Caixa Superior
-tile.oc.charger.name=Carregador
-tile.oc.diskdrive.name=Drive de Disquetes
-tile.oc.keyboard.name=Teclado
-tile.oc.powerconverter.name=Conversor de Energia
-tile.oc.powerdistributor.name=Distribuidor de Energia
-tile.oc.redstone.name=E/S de Redstone
-tile.oc.robot.name=Robô
-tile.oc.robotafterimage.name=Robô
-tile.oc.screen1.name=Ecrã Básico
-tile.oc.screen2.name=Ecrã Avançado
-tile.oc.screen3.name=Ecrã Superior
-tile.oc.switch.name=Roteador
-
-# Items
-item.oc.acid.name=Grogue
-item.oc.alu.name=Unidade Aritmética e Lógica
-item.oc.analyzer.name=Analizador
-item.oc.arrowkeys.name=Setas
-item.oc.buttongroup.name=Grupo de Botões
-item.oc.cardbase.name=Placa Base
-item.oc.circuitboard.name=Placa de Circuitos
-item.oc.controlunit.name=Unidade de Controlo
-item.oc.cpu.name=Processador
-item.oc.cuttingwire.name=Arame de Corte
-item.oc.disk.name=Disco
-item.oc.floppydisk.name=Disquete
-item.oc.graphicscard0.name=Placa Gráfica Básica
-item.oc.graphicscard1.name=Placa Gráfica Avançada
-item.oc.graphicscard2.name=Placa Gráfica Superior
-item.oc.harddiskdrive.name=Disco Rígido
-item.oc.ironnugget.name=Pepita de Ferro
-item.oc.memory.name=Memória
-item.oc.microchip0.name=Circuito Integrado Simples
-item.oc.microchip1.name=Circuito Integrado Avançado
-item.oc.microchip2.name=Circuito Integrado Superior
-item.oc.networkcard.name=Placa de Rede
-item.oc.numpad.name=Teclado Numérico
-item.oc.printedcircuitboard.name=Placa de Circuitos Impressos
-item.oc.rawcircuitboard.name=Placa de Circuitos Vazia
-item.oc.redstonecard.name=Placa de Redstone
-item.oc.transistor.name=Transístor
-item.oc.upgradecrafting.name=Melhoramento: Fabrico
-item.oc.upgradegenerator.name=Melhoramento: Gerador
-item.oc.upgradenavigation.name=Melhoramento: Navegação
-item.oc.upgradesign.name=Melhoramento: Escrita e Leitura de Placas
-item.oc.upgradesolargenerator.name=Melhoramento: Gerador Solar
-item.oc.wirelessnetworkcard0.name=Placa de Rede sem Fios
-item.oc.WirelessNetworkCard1.name=Placa de Rede sem Fios
-
-# GUI
-oc:gui.Analyzer.Address=§6Endereço§f: %s
-oc:gui.Analyzer.ComponentName=§6Nome do Componente§f: %s
-oc:gui.Analyzer.LastError=§6Último erro§f: %s
-oc:gui.Analyzer.RobotName=§6Nome§f: %s
-oc:gui.Analyzer.RobotOwner=§6Proprietário§f: %s
-oc:gui.Analyzer.RobotXp=§6Experiência§f: %s
-oc:gui.Analyzer.StoredEnergy=§6Energia Armazenada§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Total de Energia Armazenada§f: %s
-oc:gui.Analyzer.Users=§6Utilizadores§f: %s
-oc:gui.Robot.Power=Energia
-oc:gui.Robot.TurnOff=Desligar
-oc:gui.Robot.TurnOn=Ligar
-
-# Containers
-oc:container.case=Computador
-oc:container.charger=Carregador
-oc:container.diskdrive=Drive de Disquetes
-oc:container.switch=Roteador
-
-# Item / Block Tooltips
-oc:tooltip.acid=Um líquido muito tóxico, geralmente apenas consumido por alguns piratas. Graças à sua natureza corrosiva é perfeito para gravar placas de circuitos.
-oc:tooltip.adapter=Usado para controlar blocos que não sejam componentes, tais como blocos do Minecraft Vanilla ou de outros mods.
-oc:tooltip.alu=Faz cálculos por ti. Talvez seja melhor assim.
-oc:tooltip.analyzer=Usado para mostrar informação acerca de blocos, tais como o seu §fendereço§7 e §fnome de componente§7.[nl] também mostra o erro que fez o computador crashar caso este não se tenha desligado normalmente.
-oc:tooltip.cable=Uma forma barata de conectar blocos.
-oc:tooltip.capacitor=Armazena energia para ser usada mais tarde. Pode encher e esvaziar-se muito rapidamente.
-oc:tooltip.cardbase=Como o nome indica, é o componente básico para construir placas de expansão.
-oc:tooltip.case=A Caixa é o bloco básico para a construção de computadores e contém as §fplacas de expansão§7, §fRAM§7 e §fdiscos rígidos§7.[nl] Slots: §f%s§7
-oc:tooltip.charger=Transfere energia dos condensadores para robôs adjacentes. A taxa de transferência depende do §fsinal de redstone§7 aplicado, onde nenhum sinal significa não carregar, e o sinal máximo significa carregar à velocidade máxima.
-oc:tooltip.circuitboard=Agora estamos a chegar a algum lado. Pode ser gravada para obter uma placa de circuitos impressos.
-oc:tooltip.controlunit=Esta é a unidade que... controla... coisas. Precisas dela para montar um Processador. Portanto, sim, pode-se dizer que é importante.
-oc:tooltip.cpu=Um componente essencial de qualquer computador. A frequencia é pouco fiável, mas o que é que esperas quando corre com um relógio de sol?
-oc:tooltip.cuttingwire=Usado para cortar blocos de barro na forma de uma placa. Parte-se ao fim de um uso, o que faz dela a ferramenta menos eficiente de sempre.
-oc:tooltip.disk=Um meio primitivo que pode ser usado para construir dispositivos de armazenamento persistente.
-oc:tooltip.diskdrive.CC=Disquetes do ComputerCraft são §asuportadas§7.
-oc:tooltip.diskdrive=Permite ler e escrever dados em Disquetes.
-oc:tooltip.graphicscard=Usado para alterar o que é mostrado nos ecrãs.[nl] Resolução máxima: §f%sx%s§7[nl] Profundidade de cor máxima: §f%s§7[nl] Operações/ciclo: §f%s§7
-oc:tooltip.ironnugget=Uma pepita feita de ferro, por isso é que se chama Pepita de Ferro, duh...
-oc:tooltip.keyboard=Pode ligar-se a um ecrã para permitir escrever através dele.
-oc:tooltip.memory=Necessária para poder usar um computador. Quanta mais RAM tiveres, mais complexos são os programas que podes correr.
-oc:tooltip.microchip=Um chip antes conhecido por Circuito Integrado. Não faço ideia como é que isto funciona com redstone, mas funciona.
-oc:tooltip.networkcard=Permite a computadores distantes ligados por blocos (tais como Cabos) comunicar enviando mensagens entre eles.
-oc:tooltip.powerconverter.BuildCraft=§fMJ de Buildcraft§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fEU de IndustrialCraft²§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fRF de Thermal Expansion§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fCoulombs de Resonant Engine§7: §a%s:%s§7
-oc:tooltip.powerconverter=Converte energia de outros mods para o tipo de energia usado internamente. Taxas de conversão:
-oc:tooltip.powerdistributor=Distribui energia entre diferentes redes. É util para alimentar várias redes separadas através de uma fonte de energia partilhada.
-oc:tooltip.printedcircuitboard=O componente básico de placas de expansão, memórias e afins.
-oc:tooltip.rawcircuitboard=Pode ser endurecida em qualquer fornalha.
-oc:tooltip.redstone=Permite receber e emitir sinais de redstone. Pode ser controlado por qualquer computador ao qual o bloco esteja conectado. Basicamente isto é uma placa de controlo de redstone.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 é §asuportado§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 é §asuportado§7.
-oc:tooltip.redstonecard=Permite ao computador ou robô receber e emitir sinais de redstone.
-oc:tooltip.robot=Ao contrário dos computadores, os robôs podem mover-se e interagir com o mundo como um jogado. No entanto, eles §onão§r§7 podem interagir com componentes externos!
-# the underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fNível§7: §a%s§7.
-oc:tooltip.robot_storedenergy=§fEnergia Armazenada§7: §a%s§7.
-oc:tooltip.screen=Mostra texto, controlado por uma placa gráfica numa Caixa.[nl] Resolução máxima: §f%sx%s§7[nl] Profundidade de cor máxima: §f%s§7
-oc:tooltip.switch=Permite interligar redes diferentes. Apenas pacotes de rede serão passados, componentes não serão visiveis em redes vizinhas. Usa isto para separar várias redes e ao mesmo tempo permitir comunicação através de placas de rede, por exemplo.
-oc:tooltip.toolong=Prime [§f%s§7] para uma descrição detalhada.
-oc:tooltip.transistor=Um componente básico do hardware do computador. É um pouco retorcido, mas faz o seu trabalho.
-oc:tooltip.upgradecrafting=Permite aos robôs usar a parte superior esquerda do seu inventório para fabricar objectos. Os itens têm de estar alinhados como numa mesa de fabrico.
-oc:tooltip.upgradegenerator=Pode ser usado para gerar energia a partir de combustível. Queima itens para gerar energia ao longo do tempo, dependendo da energia que pode ser extraída de cada componente.[nl] §fEficiência§7: §a%s%%§7
-oc:tooltip.upgradenavigation=Pode ser usado para determinar a posição e orientação do robô. A posição é relativa ao centro do mapa usado para fabricar este melhoramento.
-oc:tooltip.upgradesign=Permiter ler e escrever texto em Placas.
-oc:tooltip.upgradesolargenerator=Pode ser usado para gerar energia a partir da luz solar. Requer exposição directa à luz solar. Gera energia a %s%% da velocidade de um motor a carvão.
-oc:tooltip.wirelessnetworkcard=Permite trocar mensagens em redes com e sem fios. Certifica-te que defines a §fforça do sinal§7 ou nenhum pacote será enviado via redes sem fios!
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/lang/pt_br.json b/src/main/resources/assets/opencomputers/lang/pt_br.json
new file mode 100644
index 0000000000..2fb67eae36
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/pt_br.json
@@ -0,0 +1,465 @@
+{
+ "tile.oc.accesspoint": "§cPonto de Acesso§7",
+ "tile.oc.adapter": "Adaptador",
+ "tile.oc.assembler": "Montador Eletrônico",
+ "tile.oc.cable": "Cabo",
+ "tile.oc.capacitor": "Capacitador",
+ "tile.oc.carpetedCapacitor": "Capacitador com Tapete",
+ "tile.oc.case1": "Gabinete (Nível 1)",
+ "tile.oc.case2": "Gabinete (Nível 2)",
+ "tile.oc.case3": "Gabinete (Nível 3)",
+ "tile.oc.casecreative": "Gabinete (Criativo)",
+ "tile.oc.chameliumblock": "Bloco Camaleão",
+ "tile.oc.charger": "Carregador",
+ "tile.oc.disassembler": "Desmontador",
+ "tile.oc.diskdrive": "Unidade de Disco",
+ "tile.oc.endstone": "Pedra do Fim",
+ "tile.oc.geolyzer": "Geonalizador",
+ "tile.oc.hologram1": "Projetor Holográfico (Nível 1)",
+ "tile.oc.hologram2": "Projetor Holográfico (Nível 2)",
+ "tile.oc.keyboard": "Teclado",
+ "tile.oc.microcontroller": "Microcontrolador",
+ "tile.oc.motionsensor": "Sensor de Movimento",
+ "tile.oc.netsplitter": "Divisor de Rede",
+ "tile.oc.powerconverter": "Conversor de Energia",
+ "tile.oc.powerdistributor": "Distribuidor de Energia",
+ "tile.oc.print": "Impressão 3D",
+ "tile.oc.printer": "Impressora 3D",
+ "tile.oc.raid": "Raid",
+ "tile.oc.redstone": " E/S de Redstone",
+ "tile.oc.relay": "Relé",
+ "tile.oc.robot": "Robô",
+ "tile.oc.robotafterimage": "Robô",
+ "tile.oc.screen1": "Monitor (Nível 1)",
+ "tile.oc.screen2": "Monitor (Nível 2)",
+ "tile.oc.screen3": "Monitor (Nível 3)",
+ "tile.oc.rack": "Rack",
+ "tile.oc.switch": "§cSwitch§7",
+ "tile.oc.transposer": "Transpositor",
+ "tile.oc.waypoint": "Ponto de Passagem",
+ "item.oc.abstractbuscard": "Placa de Barramento Abstrata",
+ "item.oc.acid": "Grogue",
+ "item.oc.alu": "Unidade Lógica Aritmética (ULA)",
+ "item.oc.analyzer": "Analizador",
+ "item.oc.apu0": "Unidade de Processamento Acelerado (UPA) (Nível 1)",
+ "item.oc.apu1": "Unidade de Processamento Acelerado (UPA) (Nível 2)",
+ "item.oc.apu2": "Unidade de Processamento Acelerado (UPA) (Criativo)",
+ "item.oc.arrowkeys": "Setas do Teclado",
+ "item.oc.buttongroup": "Grupo de Botões",
+ "item.oc.cardbase": "Base de Cartão",
+ "item.oc.chamelium": "Camaleão",
+ "item.oc.circuitboard": "Placa de Circuito",
+ "item.oc.componentbus0": "Componente de Barramento (Nível 1)",
+ "item.oc.componentbus1": "Componente de Barramento (Nível 2)",
+ "item.oc.componentbus2": "Componente de Barramento (Nível 3)",
+ "item.oc.componentbus3": "Componente de Barramento (Criativo)",
+ "item.oc.controlunit": "Unidade de Controle (UC)",
+ "item.oc.cpu0": "Unidade Central de Processamento (CPU) (Nível 1)",
+ "item.oc.cpu1": "Unidade Central de Processamento (CPU) (Nível 2)",
+ "item.oc.cpu2": "Unidade Central de Processamento (CPU) (Nível 3)",
+ "item.oc.cuttingwire": "Fio de Corte",
+ "item.oc.datacard0": "Cartão de Dados (Nível 1)",
+ "item.oc.datacard1": "Cartão de Dados (Nível 2)",
+ "item.oc.datacard2": "Cartão de Dados (Nível 3)",
+ "item.oc.debugcard": "Cartão de Depuração",
+ "item.oc.debugger": "Depurador de Rede",
+ "item.oc.diamondchip": "Chip de Diamante",
+ "item.oc.disk": "Prato do Disco",
+ "item.oc.diskdrivemountable": "Unidade de Disco",
+ "item.oc.drone": "Drone",
+ "item.oc.dronecase0": "Carcaça de Drone (Nível 1)",
+ "item.oc.dronecase1": "Carcaça de Drone (Nível 2)",
+ "item.oc.dronecase3": "Carcaça de Drone (Criativo)",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.floppydisk": "Disquete",
+ "item.oc.graphicscard0": "Placa de Vídeo (Nível 1)",
+ "item.oc.graphicscard1": "Placa de Vídeo (Nível 2)",
+ "item.oc.graphicscard2": "Placa de Vídeo (Nível 3)",
+ "item.oc.harddiskdrive0": "Disco Rígido (Nível 1)",
+ "item.oc.harddiskdrive1": "Disco Rígido (Nível 2)",
+ "item.oc.harddiskdrive2": "Disco Rígido (Nível 3)",
+ "item.oc.hoverboots": "Botas Voadoras",
+ "item.oc.inkcartridge": "Cartucho de Tinta",
+ "item.oc.inkcartridgeempty": "Cartucho de Tinta (Vazio)",
+ "item.oc.internetcard": "Cartão de Internet",
+ "item.oc.interweb": "Interweb",
+ "item.oc.ironnugget": "Pepita de Ferro",
+ "item.oc.linkedcard": "Cartão Vinculado",
+ "item.oc.manual": "Manual do OpenComputers",
+ "item.oc.memory0": "Memória (Nível 1)",
+ "item.oc.memory1": "Memória (Nível 1.5)",
+ "item.oc.memory2": "Memória (Nível 2)",
+ "item.oc.memory3": "Memória (Nível 2.5)",
+ "item.oc.memory4": "Memória (Nível 3)",
+ "item.oc.memory5": "Memória (Nível 3.5)",
+ "item.oc.microchip0": "Circuito Integrado (Nível 1)",
+ "item.oc.microchip1": "Circuito Integrado (Nível 2)",
+ "item.oc.microchip2": "Circuito Integrado (Nível 3)",
+ "item.oc.microcontrollercase0": "Carcaça do Microcontrolador (Nível 1)",
+ "item.oc.microcontrollercase1": "Carcaça do Microcontrolador (Nível 2)",
+ "item.oc.microcontrollercase3": "Carcaça do Microcontrolador (Criativo)",
+ "item.oc.nanomachines": "Nanomáquinas",
+ "item.oc.networkcard": "Cartão de Rede",
+ "item.oc.numpad": "Teclado Numérico",
+ "item.oc.present": "Uma coisinha...",
+ "item.oc.printedcircuitboard": "Placa de Circuito Impresso (PCB)",
+ "item.oc.rawcircuitboard": "Placa de Circuito Crua",
+ "item.oc.redstonecard0": "Cartão de Redstone (Nível 1)",
+ "item.oc.redstonecard1": "Cartão de Redstone (Nível 2)",
+ "item.oc.server0": "Servidor (Nível 1)",
+ "item.oc.server1": "Servidor (Nível 2)",
+ "item.oc.server2": "Servidor (Nível 3)",
+ "item.oc.server3": "Servidor (Criativo)",
+ "item.oc.tablet": "Tablet",
+ "item.oc.tabletcase0": "Carcaça de Tablet (Nível 1)",
+ "item.oc.tabletcase1": "Carcaça de Tablet (Nível 2)",
+ "item.oc.tabletcase3": "Carcaça de Tablet (Criativo)",
+ "item.oc.terminal": "Terminal Remoto",
+ "item.oc.terminalserver": "Servidor de Terminal",
+ "item.oc.texturepicker": "Selecionador de Textura",
+ "item.oc.transistor": "Transistor",
+ "item.oc.upgradeangel": "Aprimoramento Angelical",
+ "item.oc.upgradebattery0": "Aprimoramento de Bateria (Nível 1)",
+ "item.oc.upgradebattery1": "Aprimoramento de Bateria (Nível 2)",
+ "item.oc.upgradebattery2": "Aprimoramento de Bateria (Nível 3)",
+ "item.oc.upgradechunkloader": "Aprimoramento de Chunkloader",
+ "item.oc.upgradecontainercard0": "Contêiner de Cartão (Nível 1)",
+ "item.oc.upgradecontainercard1": "Contêiner de Cartão (Nível 2)",
+ "item.oc.upgradecontainercard2": "Contêiner de Cartão (Nível 3)",
+ "item.oc.upgradecontainerupgrade0": "Aprimoramento de Contêiner (Nível 1)",
+ "item.oc.upgradecontainerupgrade1": "Aprimoramento de Contêiner (Nível 2)",
+ "item.oc.upgradecontainerupgrade2": "Aprimoramento de Contêiner (Nível 3)",
+ "item.oc.upgradecrafting": "Aprimoramento de Construção",
+ "item.oc.upgradedatabase0": "Aprimoramento de Banco de Dados (Nível 1)",
+ "item.oc.upgradedatabase1": "Aprimoramento de Banco de Dados (Nível 2)",
+ "item.oc.upgradedatabase2": "Aprimoramento de Banco de Dados (Nível 3)",
+ "item.oc.upgradeexperience": "Aprimoramento de Experiência",
+ "item.oc.upgradegenerator": "Aprimoramento de Gerador",
+ "item.oc.upgradehover0": "Aprimoramento de Flutuação (Nível 1)",
+ "item.oc.upgradehover1": "Aprimoramento de Flutuação (Nível 2)",
+ "item.oc.upgradeinventory": "Aprimoramento de Inventário",
+ "item.oc.upgradeinventorycontroller": "Aprimoramento de Controlador de Inventário",
+ "item.oc.upgradeleash": "Aprimoramento de Correia",
+ "item.oc.upgradeMF": "MFU",
+ "item.oc.upgradenavigation": "Aprimoramento de Navegação",
+ "item.oc.upgradepiston": "Aprimoramento de Pistão",
+ "item.oc.upgradesign": "Aprimoramento de Sinal de E/S",
+ "item.oc.upgradesolargenerator": "Aprimoramento de Gerador Solar",
+ "item.oc.upgradetank": "Aprimoramento de Tanque",
+ "item.oc.upgradetankcontroller": "Aprimoramento de Controlador de Tanque",
+ "item.oc.upgradetractorbeam": "Aprimoramento de Raio Trator",
+ "item.oc.upgradetrading": "Aprimoramento de Troca",
+ "item.oc.wirelessnetworkcard0": "Cartão de Rede Sem Fio (Nível 1)",
+ "item.oc.wirelessnetworkcard1": "Cartão de Rede Sem Fio (Nível 2)",
+ "item.oc.worldsensorcard": "Cartão de Sensor de Mundo",
+ "item.oc.wrench": "Chave de fenda-boca",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "Drone",
+ "oc:gui.Analyzer.Address": "§6Endereço§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Endereço copiado para a área de transferência.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Velocidade da carga§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Nome do componente§f: %s",
+ "oc:gui.Analyzer.Components": "§6Número de componentes conectados§f: %s",
+ "oc:gui.Analyzer.CopyToClipboard": "Clique para copiar para a área de transferência.",
+ "oc:gui.Analyzer.LastError": "§6Último erro§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Nome§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Dono§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Experiência§f: %s (Nível %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6Energia armazenada§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Total de energia armazenada§f: %s",
+ "oc:gui.Analyzer.Users": "§6Usuários§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Força do sinal§f: %s",
+ "oc:gui.Assembler.Collect": "Saída do coletador",
+ "oc:gui.Assembler.Complexity": "Complexidade: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Insira uma parte base",
+ "oc:gui.Assembler.InsertCPU": "Insira uma CPU",
+ "oc:gui.Assembler.InsertRAM": "Insira alguma RAM",
+ "oc:gui.Assembler.Progress": "Progresso: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Montar",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Placa de Vídeo",
+ "oc:gui.Assembler.Warning.Inventory": "Aprimoramento de Inventário",
+ "oc:gui.Assembler.Warning.Keyboard": "Teclado",
+ "oc:gui.Assembler.Warning.OS": "Mídia Inicializável",
+ "oc:gui.Assembler.Warning.Screen": "Monitor",
+ "oc:gui.Assembler.Warnings": "§eAtenção§7: Componentes recomendados ausentes.",
+ "oc:gui.Chat.NewVersion": "Uma nova versão está disponível: %s",
+ "oc:gui.Chat.TextureName": "§7Nome da textura é §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "Houve um erro §cerros§f ao rodar o 'class transformer'. Por favor relate isso, junto com o seu arquivo de log (completo!) FML §alatest.log§f/§afml-server-latest.log§f , obrigado!",
+ "oc:gui.Chat.WarningFingerprint": "§cATENÇÃO§f - impressão digital não reconhecida! Experado '§a%s§f' mas recebido '§e%s§f'. A não ser que você seja um desenvolvedor e esteja rodando uma versão desofuscada, é §lextremamente§f recomendável que baixe novamente o OpenComputers, por que o JAR que está usando talvez esteja adulterado.",
+ "oc:gui.Chat.WarningLink": "Não foi possível abrir o atalho: %s",
+ "oc:gui.Chat.WarningLuaFallback": "Bibliotecas nativas do Lua não disponíveis, computadores não serão capazes de persistir seus estados. Eles reinicializarão quando chunks descarregarem.",
+ "oc:gui.Chat.WarningProjectRed": "Você está usando uma versão do Project: Red que é incompativel com OpenComputers. Tente atualizar sua versão do Project: Red.",
+ "oc:gui.Chat.WarningRecipes": "Houve erros ao carregar uma ou mais receitas. Alguns itens não poderão ser construídos. Verifique seu arquivo de log para mais informações.",
+ "oc:gui.Drive.Managed": "Gerenciado",
+ "oc:gui.Drive.Unmanaged": "Não Gerenciado",
+ "oc:gui.Drive.ReadOnlyLock": "Bloqueado",
+ "oc:gui.Drive.ReadOnlyLockWarning": "§Somente leitura§r. Isso não pode ser removido, exceto quando o disco é formatado.",
+ "oc:gui.Drive.Warning": "§lAtençaõ§r: mudança de modos resultará em perca de todos os dados do disco!",
+ "oc:gui.Error.ComponentOverflow": "Muitos componentes conectados ao computador.",
+ "oc:gui.Error.InternalError": "Erro interno, por favor veja o arquivo de log. Isto é provavelmente um erro.",
+ "oc:gui.Error.NoCPU": "Não há CPU instalada no computador.",
+ "oc:gui.Error.NoEnergy": "Energia insuficiente.",
+ "oc:gui.Error.NoRAM": "Não há RAM instalada no computador.",
+ "oc:gui.Error.OutOfMemory": "Sem memória.",
+ "oc:gui.Manual.Blocks": "Blocos do OpenComputers",
+ "oc:gui.Manual.Home": "Início",
+ "oc:gui.Manual.Items": "Itens do OpenComputers",
+ "oc:gui.Manual.Warning.BlockMissing": "Bloco indisponível.",
+ "oc:gui.Manual.Warning.ImageMissing": "Imagem não encontrada.",
+ "oc:gui.Manual.Warning.ItemMissing": "Item indisponível.",
+ "oc:gui.Manual.Warning.OreDictMissing": "Entrada no dicionário de minérios indisponível.",
+ "oc:gui.Raid.Warning": "§4Adicionar um disco o formata.\nRemover um disco limpa a raid.",
+ "oc:gui.Robot.Power": "Energia",
+ "oc:gui.Robot.TurnOff": "Desligar",
+ "oc:gui.Robot.TurnOn": "Ligar\n§7Use um Analizador para verficar problemas.§r",
+ "oc:gui.Rack.Back": "Voltar",
+ "oc:gui.Rack.Bottom": "Baixo",
+ "oc:gui.Rack.Left": "Esquerda",
+ "oc:gui.Rack.None": "Nenhum",
+ "oc:gui.Rack.Right": "Direita",
+ "oc:gui.Rack.Enabled": "Habilitado",
+ "oc:gui.Rack.Disabled": "Disabilitado",
+ "oc:gui.Rack.RelayModeTooltip": "Modo de relé",
+ "oc:gui.Rack.Top": "Cima",
+ "oc:gui.Switch.PacketsPerCycle": "Pacotes / ciclo",
+ "oc:gui.Switch.QueueSize": "Tamanho da fila",
+ "oc:gui.Switch.TransferRate": "Taxa do ciclo",
+ "oc:gui.Terminal.InvalidKey": "Chave inválida, provavelmente outro terminal foi conectado ao servidor.",
+ "oc:gui.Terminal.OutOfRange": "Sem sinal.",
+ "oc:container.accesspoint": "Ponto de Acesso",
+ "oc:container.adapter": "Adaptador",
+ "oc:container.case": "Computador",
+ "oc:container.charger": "Carregador",
+ "oc:container.disassembler": "Desmontador",
+ "oc:container.diskdrive": "Unidade de disco",
+ "oc:container.printer": "Impressora",
+ "oc:container.raid": "Raid",
+ "oc:container.relay": "Relé",
+ "oc:container.server": "Servidor",
+ "oc:container.rack": "Rack",
+ "oc:container.switch": "Switch",
+ "oc:container.tabletwrapper": "Tablet",
+ "key.opencomputers.clipboardPaste": "Colar da área de transferência",
+ "key.opencomputers.materialCosts": "Mostrar custo dos materiais",
+ "oc:tooltip.accesspoint": "Atua como um Switch, mas adicionalmente recebe pacotes sem fio e retransmite pacotes com fio sem fio.",
+ "oc:tooltip.abstractbuscard": "Permite interagir com o barramento abstrato de §fStargateTech 2§7 enviando e recebendo pacotes LIP.",
+ "oc:tooltip.acid": "Um pseudo-liquido altamente tóxico, usualmente consumidos por alguns piratas (ihic!). Também, todavia, pode ser útil de outros modos.",
+ "oc:tooltip.adapter": "Usado para controlar blocos que não são componentes, tal como blocos vanillas ou de outros mods.",
+ "oc:tooltip.alu": "Adiciona números que você não têm. Bem melhor assim.",
+ "oc:tooltip.analyzer": "Usado para mostrar informações sobre os blocos, tal como seu §fendereço§7 e §fnome do componente§7.\nTambém mostra o erro que causou um computador travar se não foi desligado normalmente.",
+ "oc:tooltip.apu": "Isso é um CPU com um GPU integrado (ou IGP), quando você apenas precisa deste slot de placa .\nComponentes Suportados: §f%s§7\nResolução mãxima: §f%sx%s§7\nDensidade de cores máxima: §f%s§7\nOperações/tick: §f%s§7",
+ "oc:tooltip.assembler": "Permite construir robôs e outros dispositivos com várias partes de computador.",
+ "oc:tooltip.cable": "Uma maneira barata de conectar os blocos.",
+ "oc:tooltip.capacitor": "Armazena energia para usar mais tarde. Pode ser enchido e esvaziado rapidamente.",
+ "oc:tooltip.cardbase": "Como o nome diz, este é o bloco de construção básico para os cartões de expansão.",
+ "oc:tooltip.carpetedcapacitor": "Armazena energia para uso posterior. Pode ser carregado e descarregado rapidamente. Carrega quando uma ovelha ou jaguatirica anda sobre o mesmo.",
+ "oc:tooltip.case": "O gabinete é o bloco básico para computadores e guarda os §fcartões de extensão§7, §fRAM§7 e §fdiscos rígidos§7.\nSlots: §f%s§7",
+ "oc:tooltip.chamelium": "Matéria prima para as imressões 3D. Não ingerir: talvez leve a cegueira e um lapso temporário de presença.",
+ "oc:tooltip.chameliumblock": "Agradável e Limpo. Usado para formas coloridas nas impressões 3D, ou para simplesmente ter, um bloco colorido para decorar sua linda e chamativa base.",
+ "oc:tooltip.charger": "Transfere energia dos capacitores para robôs e drones adjacentes. A taxa de energia depende do §fsinal de redstone§7 vindo, onde sem sinal não carrega os dispositivos, e quanto mais forte o sinal maior será a velocidade de carregamento. Pode ser usado também para carregar tablets e unidades de disco de acesso em tablets.",
+ "oc:tooltip.circuitboard": "Agora estamos chegando em algum lugar. Pode ser cozido para obter uma placa de circuito impresso.",
+ "oc:tooltip.controlunit": "Está é a unidade que... controla... coisas. Você precisa disso para construir a CPU. Então é tipo, totalmente importante.",
+ "oc:tooltip.componentbus": "Está expansão permite aos servidores comunicarem com mais componentes ao mesmo tempo, similar como os CPUs fazem.\nComponentes Suportados: §f%s§7",
+ "oc:tooltip.cpu": "Um componente essencial para todos os computadores. O clock (relógio/taxa do processamento) é um tanto quanto que duvidoso, mas o que você espera se ele roda num relógio de sol de bolso?\nComponentes Suportados: §f%s§7",
+ "oc:tooltip.cpu.Architecture": "Arquitetura: §f%s§7",
+ "oc:tooltip.cuttingwire": "Usado para cortar blocos de argila em formato de placas de circuito. Quebra quando usa, o que provavelmente é a pior ferramenta de todas.",
+ "oc:tooltip.datacard0": "Provê um conjuto de algoritmos tal como hash e desinflar/inflar.",
+ "oc:tooltip.datacard1": "Provê um conjuto de algoritmos tal como hash, encriptação AES e desinflar/inflar.",
+ "oc:tooltip.datacard2": "Provê um conjuto de algoritmos tal como hash, encriptação AES, criptografia de curva elíptica e desinflar/inflar.",
+ "oc:tooltip.debugcard": "Item do modo criativo, permite manipular o mundo para fazer testes facieis. Use por sua conta e risco.",
+ "oc:tooltip.debugger": "Pode ser usado para depurar informações na grade de rede interna do OC. Somente use se for instruído por um desenvolvedor.",
+ "oc:tooltip.diamondchip": "Um pedacinho de um diamante uma vez impecável. Ele nunca será o mesmo de novo.",
+ "oc:tooltip.disassembler": "Separa os itens em seus componentes originais. §lAtenção§7: o item retornado tem uma chance de %s%% de quebrar no processo!",
+ "oc:tooltip.disk": "Uma mídia primitiva que pode ser usada para construir dispositvos de armazenamentos contínuos.",
+ "oc:tooltip.diskdrive.CC": "Disquetes do ComputerCraft são §asuportados§7.",
+ "oc:tooltip.diskdrive": "Permite escrever e ler disquetes. Pode ser instalado em robôs para permitir inserir disquetes mais tarde.",
+ "oc:tooltip.diskdrivemountable": "Provê a mesma funcionalidade de uma unidade de disco normal, mas só pode ser instalado em um rack.",
+ "oc:tooltip.diskusage": "Uso de disco: %s/%s Byte",
+ "oc:tooltip.disklocked": "Bloqueado por: %s",
+ "oc:tooltip.diskmodemanaged": "Modo: Gerenciado",
+ "oc:tooltip.diskmodeunmanaged": "Modo: Não gerenciado",
+ "oc:tooltip.drone": "Drones são leves, com reconhecimento rápido de unidades com espaço interno limitado.",
+ "oc:tooltip.dronecase": "Está carcaça é usada para montar drones no montador. Ele tem um espaço para uma pequena quantidade de componentes e provê levitação com a pedra do fim.",
+ "oc:tooltip.eeprom": "Pequeno armazenamento programável que contem a BIOS dos computadores usado para iniciá-los.",
+ "oc:tooltip.fakeendstone": "Quase igual a coisa real, emula até mesmo sua levitação!",
+ "oc:tooltip.geolyzer": "Permite escanear a dureza da área ao redor de blocos sólidos. Essa informação pode ser útil para geração de hologramas de área ou para detectar minérios.",
+ "oc:tooltip.graphicscard": "Usado para mudar o que é mostrado nos monitores.\nMáxima resolução: §f%sx%s§7\nMáxima profundidade de cores: §f%s§7\nOperações/tick: §f%s§7",
+ "oc:tooltip.hoverboots": "Pule alto, caia devagar, caminhe melhor. Isso e mais, com as mais novas e patenteadas Botas Voadoras (TM).",
+ "oc:tooltip.inkcartridge": "Usado para carregar tinta nas impressoras 3D. Por razões misteriosas ele não tem que permanecer na impressora.",
+ "oc:tooltip.inkcartridgeempty": "Este cartucho de tinta foi usado até secar. Recarregue isso usando corantes. Ou jogue-o fora. Veja minha cara de preocupado -.-.",
+ "oc:tooltip.internetcard": "Este cartão faz requisições HTTP usa protocolos TCP reais.",
+ "oc:tooltip.interweb": "Parabéns, você ganhou um (1) interweb. Você pode conectar a isso usando um Cartão de Internet. Cuidado: não alimente os trolls.",
+ "oc:tooltip.ironnugget": "Uma pepita feita de ferro, por isso é chamado de Pepita de Ferro, darrr...",
+ "oc:tooltip.keyboard": "Pode ser anexados aos monitores para permitir digitar neles.",
+ "oc:tooltip.hologram0": "Uma exibição volumétrica que pode ser controlado por computadores para exibir estruturas de voxel arbitrárias.\nResolução: §f48x32x48§7\nEscala máxima: §f3x§7\nProfundidade de cores: §fMonocromatico§7",
+ "oc:tooltip.hologram1": "Uma exibição volumétrica que pode ser controlado por computadores para exibir estruturas de voxel arbitrárias.\nResolução: §f48x32x48§7\nEscala máxima: §f4x§7\nProfundidade de cores: §fTricolor§7",
+ "oc:tooltip.linkedcard": "Eles são construidos em pares, e só pode comunicar-se com seu par. Entretanto, eles podem se comunicar em qualquer distância, e também cruzar dimensões. A energia requerida para enviar a mensagem é altíssima.",
+ "oc:tooltip.linkedcard_channel": "§8Canal: %s§7",
+ "oc:tooltip.manual": "Toda informaçâo que você provalvemente precisará do OpenComputers. E mais. Por um preço inacreditável de... §opor favor pressiona R para continuar§7.",
+ "oc:tooltip.materialcosts": "Segure [§f%s§7] para custos do material.",
+ "oc:tooltip.materials": "Materiais:",
+ "oc:tooltip.memory": "Requerida para fazer os computadores funcionarem. Quanto mais tiver, mais complexos podem ser os programas.",
+ "oc:tooltip.microchip": "Um chip conhecido formalmente como Circuito Integrado. Eu não tenho ideia porque isso funciona com redstone, mas funciona.",
+ "oc:tooltip.microcontroller": "Microcontroladores são mini computadores. Eles são usadas para cuidar de tarefas específicas, rodando um único programa que é provido pela EEPROM consruida dentro dele.\n§cNão pode conectar com componentes externos.§7",
+ "oc:tooltip.microcontrollercase": "Componente básico para construir microcontroladores. Coloque-o em um montador para adicionar novos componentes e montar um microcontrolador.",
+ "oc:tooltip.motionsensor": "Pode detectar movimento de formas de vidas próximas. Requer visão direta.",
+ "oc:tooltip.nanomachines": "Unidade de controle e um grupo de nanomáquinas pra ingerir, se você tiver coragem.",
+ "oc:tooltip.networkcard": "Permite que computadores distantes conectem por outros blocos (como cabos) para comunicar-se enviando mensagens um para o outro.",
+ "oc:tooltip.poweracceptor": "Velocidade da conversão de energia: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fBuildCraft MJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fCarregamento do Factorization§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fIndustrialCraft² EU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fMekanism Joules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fThermal Expansion RF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fResonant Engine Coulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Converte energia de outros mods para o tipo de energia interna. Taxa de conversão:",
+ "oc:tooltip.powerdistributor": "Distribui energia por meio de diferentes redes. Isto é útil para compartilhar fluxo de energia de seu sistema para outro conversor em diferentes sub-redes que podem manter separados.",
+ "oc:tooltip.present": "... para seus problemas. Abra este presente para ter uma chance de receber §kum grande tesouro§7!\n§8Construa itens do OpenComputers para ter uma chance de receber presente.§7",
+ "oc:tooltip.print.BeaconBase": "§8Funciona como uma base do sinalizador.",
+ "oc:tooltip.print.LightValue": "§8Luz emitida: %s.",
+ "oc:tooltip.print.RedstoneLevel": "§8Saída da Redstone: %s.",
+ "oc:tooltip.printedcircuitboard": "O bloco de construção básico para cartões de expansão, memória e outros.",
+ "oc:tooltip.printer": "Permite imprimir blocos com forma definida pelo usuário usando o Camaleão (nome lindo?) e Cartucho de Tinta. Deve ser configurado usando um computador. Deixe longe do alcance das crianças. Porque sim.",
+ "oc:tooltip.raid": "Permite cobinar três discos rigídos em um único grande arquivo de sistema que pode ser usado por todos os computadores conectados.",
+ "oc:tooltip.rawcircuitboard": "Pode ser endurecido em qualquer fornalha compátivel.",
+ "oc:tooltip.redstone": "Permite ler e emitir sinais de redstone ao redor do bloco. Pode ser controlado por qualquer computador que o bloco estiver conectado. Isto é básicamente um cartão de redstone externo.",
+ "oc:tooltip.redstonecard.ProjectRed": "§fProjectRed§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "§fWireless Redstone (ChickenBones)§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "§fWireless Redstone (SlimeVoid)§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard": "Permite ler e emitir sinais de redstone ao redor do robô computadorizado.",
+ "oc:tooltip.relay": "Permite conectar diversas redes uma com a outra. Somente mensagens de rede serão passadas, componentes não serão vísiveis através disto. Use para separar redes e continuar permitindo comunicação usando Cartões de Rede, por exemplo.",
+ "oc:tooltip.robot": "Diferente de computadores, robôs podem mover-se por ai e interagir com o mundo parecido com o que um jogador faz.\n§cNão pode conectar-se com componentes externos.§7",
+ "oc:tooltip.robot_level": "§fNível§7: §a%s§7",
+ "oc:tooltip.robot_storedenergy": "§fEnergia armazenada§7: §a%s§7",
+ "oc:tooltip.screen": "Mostra texto, controlado por uma placa de vídeo em um Gabinete.\nResolução máxima: §f%sx%s§7\nDensidade máxima: §f%s§7",
+ "oc:tooltip.server": "Isto é um servidor: existem muitos como este, mas este pode ser aprimorado com componentes como um gabinete pode ser. Ele pode ser ligado inserindo-o em um rack de servidor.",
+ "oc:tooltip.server.Components": "Componentes instalados:",
+ "oc:tooltip.rack": "Permite a instalação de até quatro servidores ou outros montáveis.",
+ "oc:tooltip.switch": "Permite conectar várias redes uma com a outra. Somente mensagens de rede serão transmitidas, componentes não serão vísiveis. Use-o para separar redes permitindo comunicação usando Cartões de Rede, por exemplo.",
+ "oc:tooltip.tablet": "Um tablet, para usar Lua de maneira portátil. Pode ser forçado a desligar se abaixando e ativando-o.",
+ "oc:tooltip.tabletcase": "Carcaça básica para tablets. Coloque-o no montador para adicionar componentes e criar um tablet.",
+ "oc:tooltip.terminal": "Permite controlar um servidor remotamente, enquanto estiver no seu alcance. Atua como monitor e teclados portateis. Shift + Botão Direito em um servidor em um rack para vincular um terminal.",
+ "oc:tooltip.terminalserver": "Backend para que Terminais remotos possam ser conectados para prover controle remoto. Contém um monitor virtual e um teclado.",
+ "oc:tooltip.texturepicker": "Esta ferramente mostra uma string descrevendo uma superfície de bloco, para usar na impressora 3D e definir formas. Não são nomes de texturas, nana nina não.",
+ "oc:tooltip.tier": "§8Nível %s",
+ "oc:tooltip.netsplitter": "Atua como um conector dinâmico. Conectividade de cada lado pode ser mudada batendo-a com uma chave. Conectividade de todos os lados podem ser invertidas aplicando um sinal de redstone.",
+ "oc:tooltip.toolong": "Segure [§f%s§7] para uma dica detalhada.",
+ "oc:tooltip.transistor": "Um elemento básico para outras partes de computador. É um pouco torto, mas faz seu trabalho.",
+ "oc:tooltip.transposer": "Permite transferir automaticamente itens e fluidos entre inventários adjacentes e recipientes de fluidos.",
+ "oc:tooltip.upgradeangel": "Permite que robôs coloquem blocos no ar, mesmo sem um ponto de apoio.",
+ "oc:tooltip.upgradebattery": "Aumenta a quantidade de energia que o dispositivo pode armazenar, permitindo que trabalhe mais tempo sem precisa recarregar.\nCapacidade: §f%s§7",
+ "oc:tooltip.upgradechunkloader": "Se um robô move-se em uma floresta e ninguém é capaz de ver ele, ele está se mexendo ou não? Este aprimoramento faz ter certeza que sim. Isto mantêm um chunk em que um dispositvo está carregado, mas consome energia continuamente enquanto ativo.",
+ "oc:tooltip.upgradecontainercard": "Este aprimoramento de contêiner permite dinamicamente instalar e remover um cartão de um dispositivo montado.\nNível máximo: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "Este aprimoramento de contêiner permite dinamicamente instalar e remover outro aprimoramento de um dispositivo montado.\nNível máximo: §f%s§7",
+ "oc:tooltip.upgradecrafting": "Permite que robôs usem o canto superior esquerdo de seu inventário para construir objetos. Os itens devem estar posicionados como se estivessem numa mesa de trabalho.",
+ "oc:tooltip.upgradedatabase": "Este aprimoramento permite armazenar informação de pilha de itens para ser usado por outros componentes.\nEntradas suportadas: §f%s§7",
+ "oc:tooltip.upgradeexperience": "Este aprimoramento permite que robôs acumulem experiência efetuando diversas operações. Quanto mais experiência estiver, mais energia pode armazenar, mais rápido pode cortar blocos e mais efeciente ele usa as ferramentas.",
+ "oc:tooltip.upgradegenerator": "Pode ser usado para gerar combustível em movimento. Queima itens para gerar energia o tempo todo, baseado em seus valores de combustível.\n§fEfeciencia§7: §a%s%%§7",
+ "oc:tooltip.upgradehover": "Este aprimoramento permite que robôs voem acima do solo sem precisar escalar paredes.\nAltura máxima: §f%s§7",
+ "oc:tooltip.upgradeinventory": "Este aprimoramento provê espaço no inventário para robôs ou drones. Sem um destes, eles não serão capazes de armazenar itens internamente.",
+ "oc:tooltip.upgradeinventorycontroller": "Este aprimoramento permite que robôs e drones tenham mais controle de como eles interagem com o inventário externo, e permite que robôs troquem sua ferramenta equipada com algum item do seu inventário.",
+ "oc:tooltip.upgrademf": "Permite que adaptadores acessem blocos não adjacentes.",
+ "oc:tooltip.upgrademf.Linked": "§fConexão estabelecida§7",
+ "oc:tooltip.upgrademf.Unlinked": "§fSem conexão§7",
+ "oc:tooltip.upgradeleash": "Permite que alguns dispostivos, como drones, coloquem animais em coleiras. MUITOSSSS ANIMAIIIIIIss.",
+ "oc:tooltip.upgradenavigation": "Pode ser usado para determinar a posição e orientação de um dispositivo. A posição é relativa ao centro do mapa que foi usado para construir este aprimoramento.",
+ "oc:tooltip.upgradepiston": "Este aprimoramento tem um movimento agressivo. Permite mexer blocos, como se estivesse usando um pistão. Isto §lnão§7 move entidades.",
+ "oc:tooltip.upgradesign": "Permite ler e escrever em placas de texto.",
+ "oc:tooltip.upgradesolargenerator": "Pode ser usado para gerar energia solar em movimento. Requer uma linha de visão limpa do céu acima do dispositivo. Gera energia em %s%% da velocidade de um Motor Stirling.",
+ "oc:tooltip.upgradetank": "Este aprimoramento provê um armazenamento de tanque ou fluidos para robôs e drones. Sem um destes, ele não será capaz de armazenar fluidos internamente.",
+ "oc:tooltip.upgradetankcontroller": "Este aprimoramento permite que robôs e drones tenham mais controle de como eles interagem com tanques externos, e permite que ele transfira fluidos para os tanques e dos tanques.",
+ "oc:tooltip.upgradetractorbeam": "Equipa um dispositivo com uma tecnologia extremamente avançada, codenome \"Imã\". Permite que dispositivos capturem blocos com o raio de 3 blocos de sua localização.",
+ "oc:tooltip.upgradetrading": "Permite que robôs e drones façam trocas com Aldeões.",
+ "oc:tooltip.waypoint": "Provê um ponto de referência para os dispositvos com um aprimoramento de navegação.",
+ "oc:tooltip.wirelessnetworkcard": "Permite enviar mensagens de rede além do meio normal. Você pode ajustar a §fforça do sinal§7 para controlar o quão longe as mensagens vão. Altos níveis de força de sinal resulta em alto consumo de energia.",
+ "oc:tooltip.worldsensorcard": "Permite ler informações sobre o mundo, como gravidade e/ou se tem uma atmosfera respirável. Use os resultados por sua conta e risco. O fabricando não se responsabiliza por danos corporais ou materias por decisões causadas sobre as saídas dos cartões. Nós temos advogados. E dinheiro. Então nem tente.",
+ "oc:tooltip.wrench": "Um híbrido entre uma Chave de fenda e uma Chave de boca, esta ferramenta é fácil de usar, mas díficil de dominar.",
+ "achievement.oc.adapter": "Ai que delicia cara.",
+ "achievement.oc.adapter.desc": "Interagiu com blocos de outros mods e também do Minecraft vanilla!",
+ "achievement.oc.assembler": "Explêndido",
+ "achievement.oc.assembler.desc": "Hora de dominar o mundo!",
+ "achievement.oc.cable": "Não é um Fio Sujo",
+ "achievement.oc.cable.desc": "Com a tecnologia patenteada de anti-espaguete.",
+ "achievement.oc.capacitor": "Baterias inclusas",
+ "achievement.oc.capacitor.desc": "Você não pode parar isso.",
+ "achievement.oc.card": "Aceitamos Cartões",
+ "achievement.oc.card.desc": "Para sua conveniência. Sem segundas intenções, prometo.",
+ "achievement.oc.case": "Em Caso de Problemas",
+ "achievement.oc.case.desc": "Porque torres quadradas são as melhores.",
+ "achievement.oc.charger": "Tá bom, vamo lá",
+ "achievement.oc.charger.desc": "Carrreeegaaaan- poxa, esqueci do sinal de redstone de novo.",
+ "achievement.oc.chip": "Todas as Pequenas Coisas",
+ "achievement.oc.chip.desc": "Porque tubos a vácuo são coisa do passado.",
+ "achievement.oc.cpu": "Overclocked",
+ "achievement.oc.cpu.desc": "Hora de fazer uso destes ciclos computacionais.",
+ "achievement.oc.disassembler": "Vamo quebra tudo!",
+ "achievement.oc.disassembler.desc": "Caso suas ideias brilhantes não sejam tão brilhantes assim.",
+ "achievement.oc.diskDrive": "Roda a Roda.",
+ "achievement.oc.diskDrive.desc": "Capacidade inferior mas um som lindíssimo.",
+ "achievement.oc.drone": "Voando alto.",
+ "achievement.oc.drone.desc": "Mantenha a calma e jogue-o para fora do planeta.",
+ "achievement.oc.eeprom": "Só pode ter um",
+ "achievement.oc.eeprom.desc": "Por computador, claro. Para manter a ordem da inicialização, entendeu?",
+ "achievement.oc.floppy": "Um ri- disco",
+ "achievement.oc.floppy.desc": "Velho, mas ainda funciona.",
+ "achievement.oc.geolyzer": "Pra dentro da Terra",
+ "achievement.oc.geolyzer.desc": "Têm qualidades extraordinárias.",
+ "achievement.oc.graphicsCard": "Ultima Geração",
+ "achievement.oc.graphicsCard.desc": "Assim pode ser ... ann... rendereziado. Ah sim sim.",
+ "achievement.oc.hdd": "HDD Melhor que HD",
+ "achievement.oc.hdd.desc": "Não espere, não é isso que significa. Bom, você entendeu...",
+ "achievement.oc.hologram": "Próxima Dimensão",
+ "achievement.oc.hologram.desc": "Porque 2D é chato. Ou não é?",
+ "achievement.oc.keyboard": "PegadorDeSujeira3000",
+ "achievement.oc.keyboard.desc": "É altamente recomendável resistir o impulso de girar eles no ar.",
+ "achievement.oc.microcontroller": "Irmanzinha",
+ "achievement.oc.microcontroller.desc": "O irmãozinho do computador.",
+ "achievement.oc.motionSensor": "Mexe ae que quero vê",
+ "achievement.oc.motionSensor.desc": "Igual a Steve Swagger.",
+ "achievement.oc.networkCard": "Agora Estamos Falando!",
+ "achievement.oc.networkCard.desc": "Mantenha contato com esses parentes distantes.",
+ "achievement.oc.openOS": "Buti",
+ "achievement.oc.openOS.desc": "Um SO para - espere, já usei essa antes? Droga.",
+ "achievement.oc.powerDistributor": "Compartilhar é Amar",
+ "achievement.oc.powerDistributor.desc": "Quando você precisa de ajuda para equilibrar toda essa energia.",
+ "achievement.oc.rack": "Mas que potência",
+ "achievement.oc.rack.desc": "Sim, os racks de servidores são potentes.",
+ "achievement.oc.raid": "LFG",
+ "achievement.oc.raid.desc": "Heroíco valeuflws.",
+ "achievement.oc.ram": "Random Access Memories (Memórias de Acesso Aleatório)",
+ "achievement.oc.ram.desc": "Parabéns, Você está fazendo isso certo.",
+ "achievement.oc.redstoneCard": "Con... tato",
+ "achievement.oc.redstoneCard.desc": "Hora de ser análogo.",
+ "achievement.oc.redstoneIO": "Hello from the outside...",
+ "achievement.oc.redstoneIO.desc": "Levando os sinais de redstone para onde quiser.",
+ "achievement.oc.robot": "Bip Bip",
+ "achievement.oc.robot.desc": "EXTERMINAR!",
+ "achievement.oc.screen": "Tentou desligar e ligar de novo?",
+ "achievement.oc.screen.desc": "Não, de verdade. Um pulso de redstone pode alternar o monitor entre ligado e desligado.",
+ "achievement.oc.server": "Dedicado",
+ "achievement.oc.server.desc": "Servidores na nuvem, aqui vamos nós.",
+ "achievement.oc.switch": "Topologia Complexa",
+ "achievement.oc.switch.desc": "Evite embalagens baratas devido a possibilidade de pacotes perdidos.",
+ "achievement.oc.tablet": "Não Engula",
+ "achievement.oc.tablet.desc": "Mantenha longe do alcance das crianças para evitar cobranças exageradas no seu cartão de crédito.",
+ "achievement.oc.transistor": "Onipresente",
+ "achievement.oc.transistor.desc": "Crie um Transistor para começar.",
+ "achievement.oc.wirelessNetworkCard": "Sinais",
+ "achievement.oc.wirelessNetworkCard.desc": "Hora de ir onde nenhum pacote foi antes.",
+ "death.attack.oc.nanomachinesOverload.1": "%s foi muito ganancioso.",
+ "death.attack.oc.nanomachinesOverload.2": "%s teve um ataque de nervos.",
+ "death.attack.oc.nanomachinesOverload.3": "As nanomáquinas de %s estão fora de controle.",
+ "death.attack.oc.nanomachinesHungry.1": "%s foi comido por nanomáquinas.",
+ "death.attack.oc.nanomachinesHungry.2": "%s não alimentou suas nanomáquinas.",
+ "death.attack.oc.nanomachinesHungry.3": "%s foi digerido.",
+ "nei.options.inventory.oredict": "Mostre nomes do OreDictionary",
+ "nei.options.inventory.oredict.true": "Sim",
+ "nei.options.inventory.oredict.false": "Não",
+ "nei.usage.oc.Manual": "Open Manual",
+ "option.oc.address": "Endereço",
+ "option.oc.componentName": "Nome do Componente",
+ "option.oc.energy": "Energia"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/pt_pt.json b/src/main/resources/assets/opencomputers/lang/pt_pt.json
new file mode 100644
index 0000000000..d6545483d0
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/pt_pt.json
@@ -0,0 +1,118 @@
+{
+ "tile.oc.adapter": "Adaptador",
+ "tile.oc.cable": "Cabo",
+ "tile.oc.capacitor": "Condensador",
+ "tile.oc.case1": "Caixa Básica",
+ "tile.oc.case2": "Caixa Avançada",
+ "tile.oc.case3": "Caixa Superior",
+ "tile.oc.charger": "Carregador",
+ "tile.oc.diskdrive": "Drive de Disquetes",
+ "tile.oc.keyboard": "Teclado",
+ "tile.oc.powerconverter": "Conversor de Energia",
+ "tile.oc.powerdistributor": "Distribuidor de Energia",
+ "tile.oc.redstone": "E/S de Redstone",
+ "tile.oc.robot": "Robô",
+ "tile.oc.robotafterimage": "Robô",
+ "tile.oc.screen1": "Ecrã Básico",
+ "tile.oc.screen2": "Ecrã Avançado",
+ "tile.oc.screen3": "Ecrã Superior",
+ "tile.oc.switch": "Roteador",
+ "item.oc.acid": "Grogue",
+ "item.oc.alu": "Unidade Aritmética e Lógica",
+ "item.oc.analyzer": "Analizador",
+ "item.oc.arrowkeys": "Setas",
+ "item.oc.buttongroup": "Grupo de Botões",
+ "item.oc.cardbase": "Placa Base",
+ "item.oc.circuitboard": "Placa de Circuitos",
+ "item.oc.controlunit": "Unidade de Controlo",
+ "item.oc.cpu": "Processador",
+ "item.oc.cuttingwire": "Arame de Corte",
+ "item.oc.disk": "Disco",
+ "item.oc.floppydisk": "Disquete",
+ "item.oc.graphicscard0": "Placa Gráfica Básica",
+ "item.oc.graphicscard1": "Placa Gráfica Avançada",
+ "item.oc.graphicscard2": "Placa Gráfica Superior",
+ "item.oc.harddiskdrive": "Disco Rígido",
+ "item.oc.ironnugget": "Pepita de Ferro",
+ "item.oc.memory": "Memória",
+ "item.oc.microchip0": "Circuito Integrado Simples",
+ "item.oc.microchip1": "Circuito Integrado Avançado",
+ "item.oc.microchip2": "Circuito Integrado Superior",
+ "item.oc.networkcard": "Placa de Rede",
+ "item.oc.numpad": "Teclado Numérico",
+ "item.oc.printedcircuitboard": "Placa de Circuitos Impressos",
+ "item.oc.rawcircuitboard": "Placa de Circuitos Vazia",
+ "item.oc.redstonecard": "Placa de Redstone",
+ "item.oc.transistor": "Transístor",
+ "item.oc.upgradecrafting": "Melhoramento: Fabrico",
+ "item.oc.upgradegenerator": "Melhoramento: Gerador",
+ "item.oc.upgradenavigation": "Melhoramento: Navegação",
+ "item.oc.upgradesign": "Melhoramento: Escrita e Leitura de Placas",
+ "item.oc.upgradesolargenerator": "Melhoramento: Gerador Solar",
+ "item.oc.wirelessnetworkcard0": "Placa de Rede sem Fios",
+ "item.oc.WirelessNetworkCard1": "Placa de Rede sem Fios",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "oc:gui.Analyzer.Address": "§6Endereço§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Nome do Componente§f: %s",
+ "oc:gui.Analyzer.LastError": "§6Último erro§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Nome§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Proprietário§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Experiência§f: %s",
+ "oc:gui.Analyzer.StoredEnergy": "§6Energia Armazenada§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Total de Energia Armazenada§f: %s",
+ "oc:gui.Analyzer.Users": "§6Utilizadores§f: %s",
+ "oc:gui.Robot.Power": "Energia",
+ "oc:gui.Robot.TurnOff": "Desligar",
+ "oc:gui.Robot.TurnOn": "Ligar",
+ "oc:container.case": "Computador",
+ "oc:container.charger": "Carregador",
+ "oc:container.diskdrive": "Drive de Disquetes",
+ "oc:container.switch": "Roteador",
+ "oc:tooltip.acid": "Um líquido muito tóxico, geralmente apenas consumido por alguns piratas. Graças à sua natureza corrosiva é perfeito para gravar placas de circuitos.",
+ "oc:tooltip.adapter": "Usado para controlar blocos que não sejam componentes, tais como blocos do Minecraft Vanilla ou de outros mods.",
+ "oc:tooltip.alu": "Faz cálculos por ti. Talvez seja melhor assim.",
+ "oc:tooltip.analyzer": "Usado para mostrar informação acerca de blocos, tais como o seu §fendereço§7 e §fnome de componente§7.\ntambém mostra o erro que fez o computador crashar caso este não se tenha desligado normalmente.",
+ "oc:tooltip.cable": "Uma forma barata de conectar blocos.",
+ "oc:tooltip.capacitor": "Armazena energia para ser usada mais tarde. Pode encher e esvaziar-se muito rapidamente.",
+ "oc:tooltip.cardbase": "Como o nome indica, é o componente básico para construir placas de expansão.",
+ "oc:tooltip.case": "A Caixa é o bloco básico para a construção de computadores e contém as §fplacas de expansão§7, §fRAM§7 e §fdiscos rígidos§7.\nSlots: §f%s§7",
+ "oc:tooltip.charger": "Transfere energia dos condensadores para robôs adjacentes. A taxa de transferência depende do §fsinal de redstone§7 aplicado, onde nenhum sinal significa não carregar, e o sinal máximo significa carregar à velocidade máxima.",
+ "oc:tooltip.circuitboard": "Agora estamos a chegar a algum lado. Pode ser gravada para obter uma placa de circuitos impressos.",
+ "oc:tooltip.controlunit": "Esta é a unidade que... controla... coisas. Precisas dela para montar um Processador. Portanto, sim, pode-se dizer que é importante.",
+ "oc:tooltip.cpu": "Um componente essencial de qualquer computador. A frequencia é pouco fiável, mas o que é que esperas quando corre com um relógio de sol?",
+ "oc:tooltip.cuttingwire": "Usado para cortar blocos de barro na forma de uma placa. Parte-se ao fim de um uso, o que faz dela a ferramenta menos eficiente de sempre.",
+ "oc:tooltip.disk": "Um meio primitivo que pode ser usado para construir dispositivos de armazenamento persistente.",
+ "oc:tooltip.diskdrive.CC": "Disquetes do ComputerCraft são §asuportadas§7.",
+ "oc:tooltip.diskdrive": "Permite ler e escrever dados em Disquetes.",
+ "oc:tooltip.graphicscard": "Usado para alterar o que é mostrado nos ecrãs.\nResolução máxima: §f%sx%s§7\nProfundidade de cor máxima: §f%s§7\nOperações/ciclo: §f%s§7",
+ "oc:tooltip.ironnugget": "Uma pepita feita de ferro, por isso é que se chama Pepita de Ferro, duh...",
+ "oc:tooltip.keyboard": "Pode ligar-se a um ecrã para permitir escrever através dele.",
+ "oc:tooltip.memory": "Necessária para poder usar um computador. Quanta mais RAM tiveres, mais complexos são os programas que podes correr.",
+ "oc:tooltip.microchip": "Um chip antes conhecido por Circuito Integrado. Não faço ideia como é que isto funciona com redstone, mas funciona.",
+ "oc:tooltip.networkcard": "Permite a computadores distantes ligados por blocos (tais como Cabos) comunicar enviando mensagens entre eles.",
+ "oc:tooltip.powerconverter.BuildCraft": "§fMJ de Buildcraft§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fEU de IndustrialCraft²§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fRF de Thermal Expansion§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fCoulombs de Resonant Engine§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Converte energia de outros mods para o tipo de energia usado internamente. Taxas de conversão:",
+ "oc:tooltip.powerdistributor": "Distribui energia entre diferentes redes. É util para alimentar várias redes separadas através de uma fonte de energia partilhada.",
+ "oc:tooltip.printedcircuitboard": "O componente básico de placas de expansão, memórias e afins.",
+ "oc:tooltip.rawcircuitboard": "Pode ser endurecida em qualquer fornalha.",
+ "oc:tooltip.redstone": "Permite receber e emitir sinais de redstone. Pode ser controlado por qualquer computador ao qual o bloco esteja conectado. Basicamente isto é uma placa de controlo de redstone.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 é §asuportado§7.",
+ "oc:tooltip.redstonecard": "Permite ao computador ou robô receber e emitir sinais de redstone.",
+ "oc:tooltip.robot": "Ao contrário dos computadores, os robôs podem mover-se e interagir com o mundo como um jogado. No entanto, eles §onão§r§7 podem interagir com componentes externos!",
+ "oc:tooltip.robot_level": "§fNível§7: §a%s§7.",
+ "oc:tooltip.robot_storedenergy": "§fEnergia Armazenada§7: §a%s§7.",
+ "oc:tooltip.screen": "Mostra texto, controlado por uma placa gráfica numa Caixa.\nResolução máxima: §f%sx%s§7\nProfundidade de cor máxima: §f%s§7",
+ "oc:tooltip.switch": "Permite interligar redes diferentes. Apenas pacotes de rede serão passados, componentes não serão visiveis em redes vizinhas. Usa isto para separar várias redes e ao mesmo tempo permitir comunicação através de placas de rede, por exemplo.",
+ "oc:tooltip.toolong": "Prime [§f%s§7] para uma descrição detalhada.",
+ "oc:tooltip.transistor": "Um componente básico do hardware do computador. É um pouco retorcido, mas faz o seu trabalho.",
+ "oc:tooltip.upgradecrafting": "Permite aos robôs usar a parte superior esquerda do seu inventório para fabricar objectos. Os itens têm de estar alinhados como numa mesa de fabrico.",
+ "oc:tooltip.upgradegenerator": "Pode ser usado para gerar energia a partir de combustível. Queima itens para gerar energia ao longo do tempo, dependendo da energia que pode ser extraída de cada componente.\n§fEficiência§7: §a%s%%§7",
+ "oc:tooltip.upgradenavigation": "Pode ser usado para determinar a posição e orientação do robô. A posição é relativa ao centro do mapa usado para fabricar este melhoramento.",
+ "oc:tooltip.upgradesign": "Permiter ler e escrever texto em Placas.",
+ "oc:tooltip.upgradesolargenerator": "Pode ser usado para gerar energia a partir da luz solar. Requer exposição directa à luz solar. Gera energia a %s%% da velocidade de um motor a carvão.",
+ "oc:tooltip.wirelessnetworkcard": "Permite trocar mensagens em redes com e sem fios. Certifica-te que defines a §fforça do sinal§7 ou nenhum pacote será enviado via redes sem fios!"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/ru_RU.lang b/src/main/resources/assets/opencomputers/lang/ru_RU.lang
deleted file mode 100644
index d85e8a8782..0000000000
--- a/src/main/resources/assets/opencomputers/lang/ru_RU.lang
+++ /dev/null
@@ -1,482 +0,0 @@
-# This is the Russian localization file.
-# Authors: YuRaNnNzZZ, Sodiet, Adaptivity, cyber01, makkarpov, dangranos
-# Use [nl] to for a line break.
-
-# Blocks
-tile.oc.accesspoint.name=§cТочка доступа§7
-tile.oc.adapter.name=Адаптер
-tile.oc.assembler.name=Сборщик
-tile.oc.cable.name=Кабель
-tile.oc.capacitor.name=Конденсатор энергии
-tile.oc.case1.name=Системный блок (1-ый уровень)
-tile.oc.case2.name=Системный блок (2-ой уровень)
-tile.oc.case3.name=Системный блок (3-ий уровень)
-tile.oc.casecreative.name=Системный блок (Творческий)
-tile.oc.chameliumblock.name=Блок хамелиума
-tile.oc.charger.name=Зарядное устройство
-tile.oc.disassembler.name=Разборщик
-tile.oc.diskdrive.name=Дисковод
-tile.oc.endstone.name=Камень края
-tile.oc.geolyzer.name=Геоанализатор
-tile.oc.hologram1.name=Голографический проектор (1-ый уровень)
-tile.oc.hologram2.name=Голографический проектор (2-ой уровень)
-tile.oc.keyboard.name=Клавиатура
-tile.oc.microcontroller.name=Микроконтроллер
-tile.oc.motionsensor.name=Датчик движения
-tile.oc.netsplitter.name=Сетевой переключатель
-tile.oc.powerconverter.name=Преобразователь энергии
-tile.oc.powerdistributor.name=Распределитель энергии
-tile.oc.print.name=3D модель
-tile.oc.printer.name=3D принтер
-tile.oc.raid.name=RAID
-tile.oc.redstone.name=Красный контроллер
-tile.oc.relay.name=Ретранслятор
-tile.oc.robot.name=Робот
-tile.oc.robotafterimage.name=Робот
-tile.oc.screen1.name=Монитор (1-ый уровень)
-tile.oc.screen2.name=Монитор (2-ой уровень)
-tile.oc.screen3.name=Монитор (3-ий уровень)
-tile.oc.rack.name=Серверная стойка
-tile.oc.switch.name=§cКоммутатор§7
-tile.oc.transposer.name=Транспозер
-tile.oc.waypoint.name=Путевая точка
-
-# Items
-item.oc.abstractbuscard.name=Карта абстрактной шины
-item.oc.acid.name=Кислота
-item.oc.alu.name=Арифметико-логическое устройство (АЛУ)
-item.oc.analyzer.name=Анализатор
-item.oc.apu0.name=Процессор с видеокартой (APU) (1-ый уровень)
-item.oc.apu1.name=Процессор с видеокартой (APU) (2-ой уровень)
-item.oc.apu2.name=Процессор с видеокартой (APU) (Творческий)
-item.oc.arrowkeys.name=Клавиши со стрелками
-item.oc.buttongroup.name=Группа кнопок
-item.oc.cardbase.name=Основа для карт
-item.oc.chamelium.name=Хамелиум
-item.oc.circuitboard.name=Нетравленая печатная плата
-item.oc.componentbus0.name=Компонентная шина (1-ый уровень)
-item.oc.componentbus1.name=Компонентная шина (2-ой уровень)
-item.oc.componentbus2.name=Компонентная шина (3-ий уровень)
-item.oc.controlunit.name=Устройство управления (УУ)
-item.oc.cpu0.name=Центральный процессор (ЦП) (1-ый уровень)
-item.oc.cpu1.name=Центральный процессор (ЦП) (2-ой уровень)
-item.oc.cpu2.name=Центральный процессор (ЦП) (3-ий уровень)
-item.oc.cuttingwire.name=Проволока
-item.oc.datacard0.name=Карта данных (1-ый уровень)
-item.oc.datacard1.name=Карта данных (2-ой уровень)
-item.oc.datacard2.name=Карта данных (3-ий уровень)
-item.oc.debugcard.name=Отладочная карта
-item.oc.debugger.name=Сетевой отладчик
-item.oc.diamondchip.name=Алмазный обломок
-item.oc.disk.name=Металлический диск
-item.oc.diskdrivemountable.name=Дисковод (для серверной стойки)
-item.oc.drone.name=Дрон
-item.oc.dronecase0.name=Корпус дрона (1-ый уровень)
-item.oc.dronecase1.name=Корпус дрона (2-ой уровень)
-item.oc.dronecase3.name=Корпус дрона (Креатив)
-item.oc.eeprom.name=EEPROM
-item.oc.floppydisk.name=Дискета
-item.oc.graphicscard0.name=Видеокарта (1-ый уровень)
-item.oc.graphicscard1.name=Видеокарта (2-ой уровень)
-item.oc.graphicscard2.name=Видеокарта (3-ий уровень)
-item.oc.harddiskdrive0.name=Жёсткий диск (1-ый уровень)
-item.oc.harddiskdrive1.name=Жёсткий диск (2-ой уровень)
-item.oc.harddiskdrive2.name=Жёсткий диск (3-ий уровень)
-item.oc.hoverboots.name=Парящие ботинки
-item.oc.inkcartridge.name=Картридж с чернилами
-item.oc.inkcartridgeempty.name=Картридж с чернилами (Пустой)
-item.oc.internetcard.name=Интернет карта
-item.oc.interweb.name=Интерпаутина
-item.oc.ironnugget.name=Железный самородок
-item.oc.linkedcard.name=Соединённая карта
-item.oc.manual.name=Руководство OpenComputers
-item.oc.memory0.name=Память (1-ый уровень)
-item.oc.memory1.name=Память (Уровень 1.5)
-item.oc.memory2.name=Память (2-ой уровень)
-item.oc.memory3.name=Память (Уровень 2.5)
-item.oc.memory4.name=Память (3-ий уровень)
-item.oc.memory5.name=Память (Уровень 3.5)
-item.oc.microchip0.name=Микрочип (1-ый уровень)
-item.oc.microchip1.name=Микрочип (2-ой уровень)
-item.oc.microchip2.name=Микрочип (3-ий уровень)
-item.oc.microcontrollercase0.name=Корпус микроконтроллера (1-ый уровень)
-item.oc.microcontrollercase1.name=Корпус микроконтроллера (2-ой уровень)
-item.oc.microcontrollercase3.name=Корпус микроконтроллера (Креатив)
-item.oc.nanomachines.name=Нанороботы
-item.oc.networkcard.name=Сетевая карта
-item.oc.numpad.name=Цифровой блок клавиш
-item.oc.present.name=Маленькое что-то...
-item.oc.printedcircuitboard.name=Печатная плата
-item.oc.rawcircuitboard.name=Основа для печатной платы
-item.oc.redstonecard0.name=Плата на красном камне (1-ый уровень)
-item.oc.redstonecard1.name=Плата на красном камне (2-ой уровень)
-item.oc.server0.name=Сервер (1-ый уровень)
-item.oc.server1.name=Сервер (2-ой уровень)
-item.oc.server2.name=Сервер (3-ий уровень)
-item.oc.server3.name=Сервер (Творческий)
-item.oc.tablet.name=Планшет
-item.oc.tabletcase0.name=Корпус планшета (1-ый уровень)
-item.oc.tabletcase1.name=Корпус планшета (2-ой уровень)
-item.oc.tabletcase3.name=Корпус планшета (Креатив)
-item.oc.terminal.name=Беспроводной терминал
-item.oc.terminalserver.name=Терминальный сервер
-item.oc.texturepicker.name=Определитель текстур
-item.oc.transistor.name=Транзистор
-item.oc.upgradeangel.name="Ангельское" улучшение
-item.oc.upgradebattery0.name=Улучшение "Ёмкость" (1-ый уровень)
-item.oc.upgradebattery1.name=Улучшение "Ёмкость" (2-ой уровень)
-item.oc.upgradebattery2.name=Улучшение "Ёмкость" (3-ий уровень)
-item.oc.upgradechunkloader.name=Улучшение "Загрузчик чанков"
-item.oc.upgradecontainercard0.name=Контейнер для карты (1-ый уровень)
-item.oc.upgradecontainercard1.name=Контейнер для карты (2-ой уровень)
-item.oc.upgradecontainercard2.name=Контейнер для карты (3-ий уровень)
-item.oc.upgradecontainerupgrade0.name=Контейнер для улучшения (1-ый уровень)
-item.oc.upgradecontainerupgrade1.name=Контейнер для улучшения (2-ой уровень)
-item.oc.upgradecontainerupgrade2.name=Контейнер для улучшения (3-ий уровень)
-item.oc.upgradecrafting.name=Улучшение "Верстак"
-item.oc.upgradedatabase0.name=Улучшение "База данных" (1-ый уровень)
-item.oc.upgradedatabase1.name=Улучшение "База данных" (2-ой уровень)
-item.oc.upgradedatabase2.name=Улучшение "База данных" (3-ий уровень)
-item.oc.upgradeexperience.name=Улучшение "Опыт"
-item.oc.upgradegenerator.name=Улучшение "Генератор"
-item.oc.upgradehover0.name=Улучшение "Парение" (1-ый уровень)
-item.oc.upgradehover1.name=Улучшение "Парение" (2-ый уровень)
-item.oc.upgradeinventory.name=Улучшение "Инвентарь"
-item.oc.upgradeinventorycontroller.name=Улучшение "Контроллер инвентаря"
-item.oc.upgradeleash.name=Улучшение "Поводок"
-item.oc.upgrademf.name=МФУ
-item.oc.upgradenavigation.name=Улучшение "Навигация"
-item.oc.upgradepiston.name=Улучшение "Поршень"
-item.oc.upgradesign.name=Улучшение "Контроллер табличек"
-item.oc.upgradesolargenerator.name=Улучшение "Солнечный генератор"
-item.oc.upgradetank.name=Улучшение "Бак для жидкостей"
-item.oc.upgradetankcontroller.name=Улучшение "Контроллер бака"
-item.oc.upgradetractorbeam.name=Улучшение "Притягивающий луч"
-item.oc.upgradetrading.name=Улучшение "Торговля"
-item.oc.wirelessnetworkcard0.name=Плата беспроводной сети (1-ый уровень)
-item.oc.wirelessnetworkcard1.name=Плата беспроводной сети (2-ой уровень)
-item.oc.worldsensorcard.name=Карта-мировой сенсор
-item.oc.wrench.name=Ключ
-
-# Entities
-entity.oc.Drone.name=Дрон
-
-# GUI
-oc:gui.Analyzer.Address=§6Адрес§f: %s
-oc:gui.Analyzer.AddressCopied=Адрес скопирован в буфер обмена.
-oc:gui.Analyzer.ChargerSpeed=§6Скорость зарядки§f: %s
-oc:gui.Analyzer.ComponentName=§6Имя компонента§f: %s
-oc:gui.Analyzer.Components=§6Количество подключенных компонентов§f: %s
-oc:gui.Analyzer.CopyToClipboard=Кликните для копирования в буфер обмена.
-oc:gui.Analyzer.LastError=§6Последняя ошибка§f: %s
-oc:gui.Analyzer.RobotName=§6Имя§f: %s
-oc:gui.Analyzer.RobotOwner=§6Владелец§f: %s
-oc:gui.Analyzer.RobotXp=§6Опыт§f: %s (Уровень: %s)
-oc:gui.Analyzer.StoredEnergy=§6Накоплено энергии§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Всего накоплено энергии§f: %s
-oc:gui.Analyzer.Users=§6Пользователи§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Уровень сигнала§f: %s
-oc:gui.Assembler.Collect=Заберите результат сборки
-oc:gui.Assembler.Complexity=Сложность: %s/%s
-oc:gui.Assembler.InsertCase=Вставьте системный блок
-oc:gui.Assembler.InsertCPU=Вставьте процессор
-oc:gui.Assembler.InsertRAM=Вставьте память
-oc:gui.Assembler.Progress=Прогресс: %s%% (%s)
-oc:gui.Assembler.Run=Собрать
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=Видеокарта
-oc:gui.Assembler.Warning.Inventory=Улучшение "Инвентарь"
-oc:gui.Assembler.Warning.Keyboard=Клавиатура
-oc:gui.Assembler.Warning.OS=Загрузочный диск
-oc:gui.Assembler.Warning.Screen=Монитор
-oc:gui.Assembler.Warnings=§eВнимание§7: Отсутствуют рекомендуемые компоненты.
-oc:gui.Chat.NewVersion=Доступна новая версия: %s
-oc:gui.Chat.TextureName=§7Имя текстуры: §a%s§f.
-oc:gui.Chat.WarningClassTransformer=Возникли §cошибки§f при преобразовании классов. Пожалуйста, сообщите об этом, а также приложите файл FML §alatest.log§f/§afml-server-latest.log§f!
-oc:gui.Chat.WarningFingerprint=§cВНИМАНИЕ§f - несовпадение отпечатка файла! Ожидаемый: '§a%s§f', полученный: '§e%s§f'. Если Вы не разработчик, использующий деобфусцированную версию мода, то §lкрайне§f желательно заново скачать OpenComputers, поскольку JAR-файл, возможно, был изменён.
-oc:gui.Chat.WarningLink=Невозможно открыть ссылку: %s
-oc:gui.Chat.WarningLuaFallback=Исходные библиотеки Lua не доступны, компьютеры не смогут сохранять своё состояние. Они перезагрузятся после выгрузки чанка.
-oc:gui.Chat.WarningProjectRed=Вы используете версию Project: Red, несовместимую с OpenComputers. Попробуйте обновить Project: Red.
-oc:gui.Chat.WarningRecipes=Произошла ошибка при загрузке одного или нескольких рецептов. Некоторые предметы могут не крафтиться. Проверьте логи, чобы узнать подробнее.
-oc:gui.Chat.WarningSimpleComponent=Некоторый мод §eневерно§f использует интрефейс §aSimpleComponent§f. Логика компонента не смогла быть внедрена. Проверьте логи, чобы узнать подробнее.
-oc:gui.Drive.Managed=Файловый режим
-oc:gui.Drive.Unmanaged=Блочный режим
-oc:gui.Drive.Warning=§lВнимание§r: переключение режимов очищает диск!
-oc:gui.Error.ComponentOverflow=Слишком много компонентов подключено к компьютеру.
-oc:gui.Error.InternalError=Возникла внутренняя ошибка, пожалуйста, посмотрите лог-файл. Возможно, это баг.
-oc:gui.Error.NoCPU=Не установлен процессор.
-oc:gui.Error.NoEnergy=Недостаточно энергии.
-oc:gui.Error.NoRAM=Не установлена память.
-oc:gui.Error.OutOfMemory=Недостаточно памяти.
-oc:gui.Manual.Blocks=Блоки OpenComputers
-oc:gui.Manual.Home=Главная страница
-oc:gui.Manual.Items=Предметы OpenComputers
-oc:gui.Manual.Warning.BlockMissing=Блок недоступен.
-oc:gui.Manual.Warning.ImageMissing=Изображение не найдено.
-oc:gui.Manual.Warning.ItemMissing=Предмет недоступен.
-oc:gui.Manual.Warning.OreDictMissing=Запись Ore Dictionary недоступна.
-oc:gui.Raid.Warning=§4Добавление диска очистит его.[nl] Удаление диска очистит RAID.
-oc:gui.Robot.Power=Энергия
-oc:gui.Robot.TurnOff=Выключить
-oc:gui.Robot.TurnOn=Включить
-oc:gui.Rack.Back=Сзади
-oc:gui.Rack.Bottom=Снизу
-oc:gui.Rack.Left=Слева
-oc:gui.Rack.None=Нет
-oc:gui.Rack.Right=Справа
-oc:gui.Rack.Enabled=Включено
-oc:gui.Rack.Disabled=Выключено
-oc:gui.Rack.Top=Сверху
-oc:gui.Switch.TransferRate=Цикличность
-oc:gui.Switch.PacketsPerCycle=Пакеты / цикл
-oc:gui.Switch.QueueSize=Размер очереди
-oc:gui.Terminal.InvalidKey=Неверный ключ, скорее всего, к серверу уже подключен другой терминал.
-oc:gui.Terminal.OutOfRange=Нет сигнала.
-
-# Containers
-oc:container.accesspoint=Точка доступа
-oc:container.adapter=Адаптер
-oc:container.case=Компьютер
-oc:container.charger=Зарядное устройство
-oc:container.disassembler=Разборщик
-oc:container.diskdrive=Дисковод
-oc:container.printer=Принтер
-oc:container.raid=RAID
-oc:container.relay=Ретранслятор
-oc:container.server=Сервер
-oc:container.rack=Серверная стойка
-oc:container.switch=Коммутатор
-oc:container.tabletwrapper=Планшет
-
-# Keybinds
-key.clipboardPaste=Вставить из буфера обмена
-key.materialCosts=Показать стоимость в материалах
-
-# Item / Block Tooltips
-oc:tooltip.accesspoint=Работает как коммутатор, но и с беспроводными сетями.
-oc:tooltip.abstractbuscard=Обеспечивает взаимодействие с абстрактной шиной из §fStargateTech 2§7 (отправка и приём LIP-пакетов).
-oc:tooltip.acid=Высокотоксичная псевдо-жидкость, которую обычно пьют только определённые пираты. Однако может быть полезна и при других применениях.
-oc:tooltip.adapter=Используется для контроля некомпонентных блоков, таких как обычные блоки или блоки из других модов.
-oc:tooltip.alu=Выполняет арифметические вычисления, так что вам не придётся возиться с ними.
-oc:tooltip.analyzer=Используется для отображения информации о блоках, такой как §fадрес§7 или §fимя компонента§7.[nl] Также отображает ошибку, вызвавшую сбой компьютера.
-oc:tooltip.apu=Это процессор со встроенной видеокартой, полезный, когда вам требуется освободить ещё один слот для карт.[nl] Поддерживается компонентов: §f%s§7[nl] Максимальное разрешение: §f%sx%s§7[nl] Максимальная глубина цвета: §f%s§7[nl] Операций в тик: §f%s§7
-oc:tooltip.assembler=Позволяет собирать роботов и другие устройства из ряда различных частей компьютера.
-oc:tooltip.cable=Простой и дешёвый способ соединить компоненты между собой.
-oc:tooltip.capacitor=Накапливает энергию для дальнейшего использования. Может быть очень быстро заполнен и опустошён.
-oc:tooltip.cardbase=Как видно из названия, это основа для всех карт расширения.
-oc:tooltip.case=Системный блок - основа компьютера, содержащий §fкарты расширения§7, §fОЗУ§7 и §fжёсткие диски§7.[nl] Слотов: §f%s§7
-oc:tooltip.chamelium=Базовый материал для 3D печати. Не глотать: может привести к слепоте и временным отсутствием присутствия.
-oc:tooltip.chameliumblock=Удобен для окрашенных 3D моделей или просто как цветной блок для вашей базы.
-oc:tooltip.charger=Передаёт энергию из аккумуляторов вплотную находящимся роботам и дронам. Скорость передачи зависит от §fсилы сигнала красного камня§7: отсутствие сигнала означает "не заряжать", а полный сигнал - "заряжать на полной скорости".
-oc:tooltip.circuitboard=Мы уже очень близки. Может быть вытравлена, чтобы получить печатную плату.
-oc:tooltip.controlunit=Это штука, которая... контролирует... что-то. Она необходима, чтобы создать центральный процессор. Так что, да, она очень важна.
-oc:tooltip.componentbus=Позволяет серверам взаимодействовать с большим количеством компонентов.[nl] Поддерживается компонентов: §f%s§7
-oc:tooltip.cpu=Является важным компонентом в компьютере. Тактовая частота немного нестабильна, но что вы ожидали, если он работает на карманных солнечных часах. Количество поддерживаемых компонентов: §f%s§7
-oc:tooltip.cpu.architecture=Архитектура: §f%s§7
-oc:tooltip.cuttingwire=Используется для нарезки глиняных блоков в пластины. Рвётся после использования, что делает её, пожалуй, самым неэффективным инструментом.
-oc:tooltip.datacard0=Обеспечивает поддержку нескольких продвинутых алгоритмов, таких как хеширование и сжатие.
-oc:tooltip.datacard1=Обеспечивает поддержку нескольких продвинутых алгоритмов, таких как AES-шифрование, хеширование и сжатие.
-oc:tooltip.datacard2=Обеспечивает поддержку нескольких продвинутых алгоритмов, таких как AES-шифрование, эллиптическая криптография, хеширование и сжатие.
-oc:tooltip.debugcard=Креативный предмет, позволяет манипулировать игровым миром. Используйте на свой страх и риск.
-oc:tooltip.debugger=Может быть использован для вывода отладочной информации о внутренней сети. Используйте только тогда, когда попросил разработчик.
-oc:tooltip.diamondchip=Небольшой кусочек некогда сияющего алмаза. Он больше никогда не будет таким, как прежде.
-oc:tooltip.disassembler=Разделяет предметы на исходные компоненты. §lВнимание§7: возвращённые предметы имеют шанс %s%% сломаться!
-oc:tooltip.disk=Примитивный носитель, который может быть использован для создания постоянных запоминающих устройств.
-oc:tooltip.diskdrive.cc=§aПоддерживаются§7 дискеты из ComputerCraft.
-oc:tooltip.diskdrive=Позволяет читать и записывать дискеты. Может быть установлен в роботов, что позволит затем вставлять дискеты.
-oc:tooltip.diskdrivemountable=Работает так же, как и обычный дисковод, но может быть вставлен только в серверную стойку.
-oc:tooltip.diskusage=Занято %s/%s байт
-oc:tooltip.diskmodemanaged=Режим: файловый
-oc:tooltip.diskmodeunmanaged=Режим: блочный
-oc:tooltip.drone=Дроны это легкие и быстрые устройства, но с ограниченным инвентарем.
-oc:tooltip.dronecase=Корпус, предназначенный для создания дрона в сборщике. Вмещает малое количество компонентов и предоставляет левитацию с помощью силы камня края.
-oc:tooltip.eeprom=Маленькое программируемое хранилище, которое содержит BIOS для запуска компьютеров.
-oc:tooltip.fakeendstone=Почти такой же, как и настоящий камень края, даже эмулирует его легкость!
-oc:tooltip.geolyzer=Позволяет сканировать твёрдость блоков в окрестности. Эта информация может быть полезна для создания голограммы области или для обнаружения руд.
-oc:tooltip.graphicscard=Используется для изменения того, что отображается на мониторах.[nl] Максимальное разрешение: §f%sx%s§7[nl] Максимальная глубина цвета:§f%s§7[nl] Операций/такт: §f%s§7
-oc:tooltip.hoverboots=Прыгайте выше, падайте глубже, бегайте быстрее. Это и многое другое с нашими новыми Парящими ботинками (TM).
-oc:tooltip.inkcartridge=Используется в 3D печати. По таинственным причинам ему не нужно оставаться в принтере.
-oc:tooltip.inkcartridgeempty=Этот картридж выглядит пустым. Заправьте его с помощью красителей. Или выбросьте.
-oc:tooltip.internetcard=Эта карта позволяет делать HTTP-запросы и использовать реальные TCP сокеты.
-oc:tooltip.interweb=Поздравляем, вы выиграли одну (1) интерсеть. Подключиться к ней можно с помощью Интернет-платы. Осторожно: не кормите троллей.
-oc:tooltip.ironnugget=Самородок, созданный из железа. Может, именно поэтому он и назван железным самородком? Хм...
-oc:tooltip.keyboard=Присоединяется к монитору, позволяя вводить информацию.
-oc:tooltip.hologram0=Объёмный дисплей, управляемый компьютером и использующийся для отображения произвольных воксельных структур.[nl] Разрешение: §f48x32x48§7 [nl] Максимальный масштаб: §f3x§7 [nl] Глубина цвета: §fМонохромный§7
-oc:tooltip.hologram1=Объёмный дисплей, управляемый компьютером и использующийся для отображения произвольных воксельных структур.[nl] Разрешение: §f48x32x48§7 [nl] Максимальный масштаб: §f4x§7 [nl] Глубина цвета: §fТрёхцветный§7
-oc:tooltip.linkedcard=Они изготавливаются в парах и могут общаться только с партнёром. Тем не менее, общаться они могут на любом расстоянии - даже между измерениями. Однако для отправки сообщения нужно довольно много энергии.
-oc:tooltip.linkedcard_channel=§8Канал: %s§7
-oc:tooltip.manual=Содержит всю информацию о моде OpenComputers, которая вам может когда-либо понадобиться. И даже больше. По невероятно низкой цене... §oнажмите R для продолжения§7.
-oc:tooltip.materialcosts=Удерживайте [§f%s§7] для показа материалов.
-oc:tooltip.materials=Материалы:
-oc:tooltip.memory=Необходима для запуска компьютера. Чем больше ОЗУ, тем более требовательные программы Вы можете запустить.
-oc:tooltip.microchip=Чип, ранее известный как интегральная схема. Понятия не имею почему, но он работает с красным камнем.
-oc:tooltip.microcontroller=Микроконтроллеры - это компьютеры, сведённые к самым базовым вещам. Они используются для выполнения специфических задач и выполняют программу, записанную на EEPROM.[nl] §cНе могут взаимодействовать с внешними компонентами.§7
-oc:tooltip.microcontrollercase=Базовый компонент для создания микроконтроллеров. Положите в сборщик, чтобы установить компоненты, и соберите микроконтроллер.
-oc:tooltip.motionsensor=Может обнаружить движение ближайших живых существ. Требуется прямая линия видимости.
-oc:tooltip.nanomachines=Блок управления и кучка нанороботов для приема внутрь, если вы решились.
-oc:tooltip.networkcard=Позволяет обмениваться сообщениями между соединённым друг с другом - с помощью кабеля или других блоков - компьютерами.
-oc:tooltip.poweracceptor=Скорость преобразования энергии: §f%s/t§7
-oc:tooltip.powerconverter.buildcraft=§fBuildCraft MJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.factorization=§fFactorization Charge§7: §a%s:%s§7
-oc:tooltip.powerconverter.industrialcraft2=§fIndustrialCraft² EU§7: §a%s:%s§7
-oc:tooltip.powerconverter.mekanism=§fMekanism Joules§7: §a%s:%s§7
-oc:tooltip.powerconverter.thermalexpansion=§fThermal Expansion RF§7: §a%s:%s§7
-oc:tooltip.powerconverter.resonantengine=§fResonant Engine Coulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=Преобразует энергию из других модов во внутренний тип энергии. Соотношение энергии:
-oc:tooltip.powerdistributor=Передаёт энергию между различными сетями. Полезно, если требуется запитать от одного преобразователя несколько сетей, которые должны оставаться разделёнными.
-oc:tooltip.present=Откройте этот подарок, чтобы получить немного §kчего-то§7![nl]§8Крафтите предметы OpenComputers в нужное время, чтобы получить шанс получить подарок.§7
-oc:tooltip.print.beaconbase=§8Используется в качестве основы для маяка.
-oc:tooltip.print.lightvalue=§8Сила излучаемого света: %s.
-oc:tooltip.print.redstonelevel=§8Сила выдаваемого красного сигнала: %s.
-oc:tooltip.printedcircuitboard=Основа плат, памяти и прочего.
-oc:tooltip.printer=Позволяет печатать пользовательские 3D-модели, используя хамелиум и картриджи с чернилами. Должен быть настроен с помощью компьютера. Держите подальше от детей.
-oc:tooltip.raid=Позволяет соединять три жестких диска в единую файловую систему, которую могут использовать все подключенные компьютеры.
-oc:tooltip.rawcircuitboard=Может быть закалена в печи для получения печатной платы.
-oc:tooltip.redstone=Позволяет считывать и подавать сигналы красного камня вокруг блока. Контролируется любым подключенным компьютером. Иными словами, это что-то вроде внешней платы на красном камне.
-oc:tooltip.redstonecard.projectred=Мод §fProjectRed§7 §aподдерживается§7.
-oc:tooltip.redstonecard.redlogic=Мод §fRedLogic§7 §aподдерживается§7.
-oc:tooltip.redstonecard.rednet=Мод §fRedNet§7 §aподдерживается§7.
-oc:tooltip.redstonecard.wirelesscbe=Мод §fWireless Redstone (ChickenBones)§7 §aподдерживается§7.
-oc:tooltip.redstonecard.wirelesssv=Мод §fWireless Redstone (SlimeVoid)§7 §aподдерживается§7.
-oc:tooltip.redstonecard=Позволяет считывать и подавать сигналы красного камня вокруг компьютера или робота.
-oc:tooltip.relay=Позволяет соединять различные сети между собой. Передаются только сообщения, компоненты между сетями не будут доступны. Используйте его для разделения сетей с возможностью пересылать сообщения между ними.
-oc:tooltip.robot=В отличие от компьютеров, роботы могут передвигаться и взаимодействовать с миром, как игрок.[nl] §cНе могут подключаться к внешним компонентам.§7
-# The underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fУровень§7: §a%s§7.
-oc:tooltip.robot_storedenergy=§fНакопленная энергия§7: §a%s§7.
-oc:tooltip.screen=Отображает текст, передаваемый видеокартой.[nl] Максимальное разрешение: §f%sx%s§7[nl] Максимальная глубина цвета: §f%s§7
-oc:tooltip.server=Это сервер. Есть много других, похожих на него, но только этот может быть улучшен компонентами, как системный блок. Можно включить после размещения в серверную стойку.
-oc:tooltip.server.components=Установленные компоненты:
-oc:tooltip.rack=Обеспечивает работу до четырёх серверов или других монтируемых компонентов.
-oc:tooltip.switch=Позволяет соединять различные сети между собой. Передаются только сообщения, компоненты между сетями не будут доступны. Используйте его для разделения сетей с возможностью пересылать сообщения между ними.
-oc:tooltip.tablet=Планшет, полностью готовый к работе с Lua. Может быть отключен нажатием правой кнопки мыши + Shift.
-oc:tooltip.tabletcase=Простой корпус для планшета. Поместите в сборщик, чтобы вставить компоненты, и соберите себе планшетный компьютер.
-oc:tooltip.terminal=Позволяет дистанционно управлять сервером, пока вы находитесь в радиусе его действия. Действует как портативный дисплей с клавиатурой.[nl] Shift+ПКМ по серверу терминалов в стойке для привязки.
-oc:tooltip.terminalserver=Компонент, к которому можно подключить беспроводной терминал. Имеет виртуальный экран и клавиатуру.
-oc:tooltip.texturepicker=Простой инструмент, позволяющий узнать название текстуры блока, которое можно использовать в 3D печати.
-oc:tooltip.tier=§8Уровень %s
-oc:tooltip.netsplitter=Работает как переключатель. Соединение каждой стороны переключается ключем. При подаче сигнала красного камня все соединения инвертируются.
-oc:tooltip.toolong=Удерживайте [§f%s§7], чтобы отобразить описание.
-oc:tooltip.transistor=Базовый элемент для большинства частей компьютера. Он немного деформирован, но отлично выполняет свою работу.
-oc:tooltip.transposer=Позволяет автоматизировать перемещение предметов и жидкостей между соседними инвентарями и хранилищами жидкости.
-oc:tooltip.upgradeangel=Позволяет роботам размещать блоки в воздухе без точки опоры.
-oc:tooltip.upgradebattery=Увеличивает количество энергии, которую робот может хранить, что позволяет ему работать дольше без перезарядки.
-oc:tooltip.upgradechunkloader=Если робот движется в лесу и никто его не видит, действительно ли он движется? Данное улучшение гарантирует это. Оно держит чанк, в котором находится робот, загруженным, но постоянно потребляет энергию во время работы.
-oc:tooltip.upgradecontainercard=Это улучшение-контейнер позволяет динамически устанавливать и снимать плату с собранного робота. [nl] Максимальный уровень: §f%s§7
-oc:tooltip.upgradecontainerupgrade=Это улучшение-контейнер позволяет динамически устанавливать и снимать другое улучшение с собранного робота. [nl] Максимальный уровень: §f%s§7
-oc:tooltip.upgradecrafting=Позволяет роботам использовать верхнюю левую часть инвентаря для крафта предметов. Вещи должны быть расположены в том же порядке, что и в верстаке.
-oc:tooltip.upgradedatabase=Позволяет хранить информацию о предметах для последующего использования другими компонентами.[nl] Поддерживается записей: §f%s§7
-oc:tooltip.upgradeexperience=Это улучшение позволяет роботу накапливать опыт при выполнении различных операций. Чем больше у них опыта, тем больше энергии они могут хранить, могут быстрее собирать блоки и эффективнее использовать инструменты.
-oc:tooltip.upgradegenerator=Позволяет роботам генерировать энергию из сжигаемого топлива прямо на ходу.[nl] §fЭффективность§7: §a%s%%§7
-oc:tooltip.upgradehover=Данное улучшение позволяет роботам летать выше над землей без необходимости лазать по стенам.[nl] Максимальная высота: §f%s§7
-oc:tooltip.upgradeinventory=Это улучшение даёт место в инвентаре для робота. Без него роботы не смогут хранить предметы внутри.
-oc:tooltip.upgradeinventorycontroller=Это улучшение позволяет роботу контролировать взаимодействие с внешними инвентарями и менять свой экипированный инструмент предметом из его инвентаря.
-oc:tooltip.upgradeleash=Позволяет некоторым устройствам, таким как дроны, цеплять животных на поводок. Много животных, при этом.
-oc:tooltip.upgrademf=Позволяет адаптерам взаимодействовать с блоками на удалении от них.
-oc:tooltip.upgrademf.linked=§fСоединение установлено§7
-oc:tooltip.upgrademf.unlinked=§fНет соединения§7
-oc:tooltip.upgradenavigation=Позволяет определять положение и ориентацию робота. Положение определяется относительно центра карты, использованной при крафте улучшения.
-oc:tooltip.upgradepiston=Позволяет двигать блоки, как поршни. §lНе§7 может двигать животных, однако.
-oc:tooltip.upgradesign=Позволяет читать и писать текст на табличках.
-oc:tooltip.upgradesolargenerator=Позволяет роботам генерировать энергию из солнечного света прямо на ходу. Требует прямую видимость неба над роботом. Генерирует энергию на скорости %s%% от двигателя Стирлинга.
-oc:tooltip.upgradetank=Позволяет роботам и дронам взаимодействовать с жидкостями. Без него они не смогут хранить жидкость.
-oc:tooltip.upgradetankcontroller=Позволяет роботам и дронам взамодействовать в внешними хранилищами жидкости, а также заливать и выливать жидкости в них.
-oc:tooltip.upgradetractorbeam=Даёт роботу самую невероятно продвинутую технологию под кодовым названием "Магнит для предметов". Позволяет роботу подбирать предметы в радиусе 3 блоков от своего расположения.
-oc:tooltip.waypoint=Добавляет путевую точку для устройств с навигационным улучшением.
-oc:tooltip.wirelessnetworkcard=Позволяет передавать сетевые сообщения по беспроводному каналу в дополнение к проводному. Вы можете настроить §fсилу сигнала§7, чтобы контролировать, насколько далеко должны отправляться сообщения. Более высокая сила сигнала приводит к повышенному потреблению энергии.
-oc:tooltip.worldsensorcard=Позволяет получать информацию об атмосфере и гравитации на планетах, добавляемых модом GalactiCraft. Используйте на свой страх и риск. Производитель не несет ответственности за материальный ущерб и увечья. У нас есть адвокаты. И деньги. Даже не пытайтесь.
-oc:tooltip.wrench=Гибрид отвертки и ключа.
-
-#Achievements
-achievement.oc.adapter=Мы едины
-achievement.oc.adapter.desc=Дайте поработать с другими модами!
-achievement.oc.assembler=Великолепно
-achievement.oc.assembler.desc=Время захватывать мир!
-achievement.oc.cable=Не трогай провода!
-achievement.oc.cable.desc=... они от этого ржавеют
-achievement.oc.capacitor=Батарея в комплекте
-achievement.oc.capacitor.desc=Вы не можете остановить это.
-achievement.oc.card=Мы принимаем карточки
-achievement.oc.card.desc=Для вашего удобства. Вам это понравится.
-achievement.oc.case=В случае возникновения неполадок
-achievement.oc.case.desc=Открывайте боковую крышку летом.
-achievement.oc.charger=Ладно, сделаем это
-achievement.oc.charger.desc=Пошла зарядка.. черт, опять забыл редстоун сигнал.
-achievement.oc.chip=Полезные мелочи
-achievement.oc.chip.desc=Ведь электронные лампы - прошлый век
-achievement.oc.cpu=Разогнанный
-achievement.oc.cpu.desc=Время нагрузить его по полной.
-achievement.oc.disassembler=Больше не нужно
-achievement.oc.disassembler.desc=Когда великолепные идеи оказываются не такими уж и великолепными
-achievement.oc.diskDrive=Карусель
-achievement.oc.diskDrive.desc=Небольшая емкость, зато какой звук!
-achievement.oc.drone=Вездесущее око
-achievement.oc.drone.desc=Небольшой брат следит за тобой.
-achievement.oc.eeprom=Он может быть только один
-achievement.oc.eeprom.desc=Для каждого компьютера, то есть. Для загрузки компьютера, вы знали?
-achievement.oc.floppy=Не подносить магнит
-achievement.oc.floppy.desc=Дискеты не любят магниты.
-achievement.oc.geolyzer=Назад на землю
-achievement.oc.geolyzer.desc=Он имеет необычные свойства.
-achievement.oc.graphicsCard=Последнее поколение
-achievement.oc.graphicsCard.desc=Покажи это.
-achievement.oc.hdd=Продавец хотдогов
-achievement.oc.hdd.desc=Нет, подождите, это не то, о чем вы подумали. Не роняйте его...
-achievement.oc.hologram=Гиперпространство
-achievement.oc.hologram.desc=Когда двух измерений уже не хватает
-achievement.oc.keyboard=Крошкохранитель-3000
-achievement.oc.keyboard.desc=Не рекомендуется переворачивать и трясти его
-achievement.oc.microcontroller=Маленькая сестренка
-achievement.oc.microcontroller.desc=Просто маленький компьютер
-achievement.oc.motionSensor=Оно двигается
-achievement.oc.motionSensor.desc=Как Майкл Джексон.
-achievement.oc.networkCard=Нам надо поговорить!
-achievement.oc.networkCard.desc=Оставайтесь на связи с дальними родственниками.
-achievement.oc.openOS=Поехали
-achievement.oc.openOS.desc=Неужели он включится.
-achievement.oc.powerDistributor=Поделись с ближним
-achievement.oc.powerDistributor.desc=Когда вы помогаете распределять энергию.
-achievement.oc.rack=Прямо в стойку
-achievement.oc.rack.desc=Не знаю, о чем думаете вы, я думал о серверной стойке.
-achievement.oc.raid=Чрезмерная избыточность
-achievement.oc.raid.desc=Только диски не вынимайте.
-achievement.oc.ram=Случайный доступ к памяти
-achievement.oc.ram.desc=Поздравляем, вы делаете это правильно.
-achievement.oc.redstoneCard=Есть контакт
-achievement.oc.redstoneCard.desc=Возврат к аналоговой технике.
-achievement.oc.redstoneIO=Выскочка
-achievement.oc.redstoneIO.desc=Когда все сигналы в нужных местах
-achievement.oc.robot=Бип-пип
-achievement.oc.robot.desc=УНИЧТОЖИТЬ!
-achievement.oc.screen=Вы пробовали выключить и снова включить?
-achievement.oc.screen.desc=Серьезно. Редстоун сигнал может выключать монитор.
-achievement.oc.server=Выделенный сервер
-achievement.oc.server.desc=Облачные вычисления, мы идем к вам.
-achievement.oc.switch=Сложная топология
-achievement.oc.switch.desc=Избегайте сложных связей и потери пакетов.
-achievement.oc.tablet=Несъедобно
-achievement.oc.tablet.desc=Держите подальше от маленьких детей, во избежание пропажи денег на вашей кредитной карте.
-achievement.oc.transistor=Редстоун, скажи "Привет."
-achievement.oc.transistor.desc=Создайте транзистор. Потом послушайте музыку. Не благодарите меня.
-achievement.oc.wirelessNetworkCard=Сигналы
-achievement.oc.wirelessNetworkCard.desc=Время идти туда, где никогда не появлялся сигнал.
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code.
-death.attack.oc.nanomachinesOverload.1=%s был слишком жадным.
-death.attack.oc.nanomachinesOverload.2=%s получил нервный срыв.
-death.attack.oc.nanomachinesOverload.3=Нанороботы %s вышли из под контроля.
-death.attack.oc.nanomachinesHungry.1=%s был съеден нанороботами.
-death.attack.oc.nanomachinesHungry.2=%s не кормил нанороботов.
-death.attack.oc.nanomachinesHungry.3=%s был переварен нанороботами.
-
-# NEI Integration
-nei.options.inventory.oredict=Показывать имена Ore Dictionary
-nei.options.inventory.oredict.true=Да
-nei.options.inventory.oredict.false=Нет
-nei.usage.oc.Manual=Открыть руководство
-
-# Waila Integration
-option.oc.address=Адрес
-option.oc.componentName=Название компонента
-option.oc.energy=Энергия
diff --git a/src/main/resources/assets/opencomputers/lang/ru_ru.json b/src/main/resources/assets/opencomputers/lang/ru_ru.json
new file mode 100644
index 0000000000..1cee1964b2
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/ru_ru.json
@@ -0,0 +1,457 @@
+{
+ "tile.oc.accesspoint": "§cТочка доступа§7",
+ "tile.oc.adapter": "Адаптер",
+ "tile.oc.assembler": "Сборщик",
+ "tile.oc.cable": "Кабель",
+ "tile.oc.capacitor": "Конденсатор энергии",
+ "tile.oc.case1": "Системный блок (1-ый уровень)",
+ "tile.oc.case2": "Системный блок (2-ой уровень)",
+ "tile.oc.case3": "Системный блок (3-ий уровень)",
+ "tile.oc.casecreative": "Системный блок (Творческий)",
+ "tile.oc.chameliumblock": "Блок хамелиума",
+ "tile.oc.charger": "Зарядное устройство",
+ "tile.oc.disassembler": "Разборщик",
+ "tile.oc.diskdrive": "Дисковод",
+ "tile.oc.endstone": "Камень края",
+ "tile.oc.geolyzer": "Геоанализатор",
+ "tile.oc.hologram1": "Голографический проектор (1-ый уровень)",
+ "tile.oc.hologram2": "Голографический проектор (2-ой уровень)",
+ "tile.oc.keyboard": "Клавиатура",
+ "tile.oc.microcontroller": "Микроконтроллер",
+ "tile.oc.motionsensor": "Датчик движения",
+ "tile.oc.netsplitter": "Сетевой переключатель",
+ "tile.oc.powerconverter": "Преобразователь энергии",
+ "tile.oc.powerdistributor": "Распределитель энергии",
+ "tile.oc.print": "3D модель",
+ "tile.oc.printer": "3D принтер",
+ "tile.oc.raid": "RAID",
+ "tile.oc.redstone": "Красный контроллер",
+ "tile.oc.relay": "Ретранслятор",
+ "tile.oc.robot": "Робот",
+ "tile.oc.robotafterimage": "Робот",
+ "tile.oc.screen1": "Монитор (1-ый уровень)",
+ "tile.oc.screen2": "Монитор (2-ой уровень)",
+ "tile.oc.screen3": "Монитор (3-ий уровень)",
+ "tile.oc.rack": "Серверная стойка",
+ "tile.oc.switch": "§cКоммутатор§7",
+ "tile.oc.transposer": "Транспозер",
+ "tile.oc.waypoint": "Путевая точка",
+ "item.oc.abstractbuscard": "Карта абстрактной шины",
+ "item.oc.acid": "Кислота",
+ "item.oc.alu": "Арифметико-логическое устройство (АЛУ)",
+ "item.oc.analyzer": "Анализатор",
+ "item.oc.apu0": "Процессор с видеокартой (APU) (1-ый уровень)",
+ "item.oc.apu1": "Процессор с видеокартой (APU) (2-ой уровень)",
+ "item.oc.apu2": "Процессор с видеокартой (APU) (Творческий)",
+ "item.oc.arrowkeys": "Клавиши со стрелками",
+ "item.oc.buttongroup": "Группа кнопок",
+ "item.oc.cardbase": "Основа для карт",
+ "item.oc.chamelium": "Хамелиум",
+ "item.oc.circuitboard": "Нетравленая печатная плата",
+ "item.oc.componentbus0": "Компонентная шина (1-ый уровень)",
+ "item.oc.componentbus1": "Компонентная шина (2-ой уровень)",
+ "item.oc.componentbus2": "Компонентная шина (3-ий уровень)",
+ "item.oc.controlunit": "Устройство управления (УУ)",
+ "item.oc.cpu0": "Центральный процессор (ЦП) (1-ый уровень)",
+ "item.oc.cpu1": "Центральный процессор (ЦП) (2-ой уровень)",
+ "item.oc.cpu2": "Центральный процессор (ЦП) (3-ий уровень)",
+ "item.oc.cuttingwire": "Проволока",
+ "item.oc.datacard0": "Карта данных (1-ый уровень)",
+ "item.oc.datacard1": "Карта данных (2-ой уровень)",
+ "item.oc.datacard2": "Карта данных (3-ий уровень)",
+ "item.oc.debugcard": "Отладочная карта",
+ "item.oc.debugger": "Сетевой отладчик",
+ "item.oc.diamondchip": "Алмазный обломок",
+ "item.oc.disk": "Металлический диск",
+ "item.oc.diskdrivemountable": "Дисковод (для серверной стойки)",
+ "item.oc.drone": "Дрон",
+ "item.oc.dronecase0": "Корпус дрона (1-ый уровень)",
+ "item.oc.dronecase1": "Корпус дрона (2-ой уровень)",
+ "item.oc.dronecase3": "Корпус дрона (Креатив)",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.floppydisk": "Дискета",
+ "item.oc.graphicscard0": "Видеокарта (1-ый уровень)",
+ "item.oc.graphicscard1": "Видеокарта (2-ой уровень)",
+ "item.oc.graphicscard2": "Видеокарта (3-ий уровень)",
+ "item.oc.harddiskdrive0": "Жёсткий диск (1-ый уровень)",
+ "item.oc.harddiskdrive1": "Жёсткий диск (2-ой уровень)",
+ "item.oc.harddiskdrive2": "Жёсткий диск (3-ий уровень)",
+ "item.oc.hoverboots": "Парящие ботинки",
+ "item.oc.inkcartridge": "Картридж с чернилами",
+ "item.oc.inkcartridgeempty": "Картридж с чернилами (Пустой)",
+ "item.oc.internetcard": "Интернет карта",
+ "item.oc.interweb": "Интерпаутина",
+ "item.oc.ironnugget": "Железный самородок",
+ "item.oc.linkedcard": "Соединённая карта",
+ "item.oc.manual": "Руководство OpenComputers",
+ "item.oc.memory0": "Память (1-ый уровень)",
+ "item.oc.memory1": "Память (Уровень 1.5)",
+ "item.oc.memory2": "Память (2-ой уровень)",
+ "item.oc.memory3": "Память (Уровень 2.5)",
+ "item.oc.memory4": "Память (3-ий уровень)",
+ "item.oc.memory5": "Память (Уровень 3.5)",
+ "item.oc.microchip0": "Микрочип (1-ый уровень)",
+ "item.oc.microchip1": "Микрочип (2-ой уровень)",
+ "item.oc.microchip2": "Микрочип (3-ий уровень)",
+ "item.oc.microcontrollercase0": "Корпус микроконтроллера (1-ый уровень)",
+ "item.oc.microcontrollercase1": "Корпус микроконтроллера (2-ой уровень)",
+ "item.oc.microcontrollercase3": "Корпус микроконтроллера (Креатив)",
+ "item.oc.nanomachines": "Нанороботы",
+ "item.oc.networkcard": "Сетевая карта",
+ "item.oc.numpad": "Цифровой блок клавиш",
+ "item.oc.present": "Маленькое что-то...",
+ "item.oc.printedcircuitboard": "Печатная плата",
+ "item.oc.rawcircuitboard": "Основа для печатной платы",
+ "item.oc.redstonecard0": "Плата на красном камне (1-ый уровень)",
+ "item.oc.redstonecard1": "Плата на красном камне (2-ой уровень)",
+ "item.oc.server0": "Сервер (1-ый уровень)",
+ "item.oc.server1": "Сервер (2-ой уровень)",
+ "item.oc.server2": "Сервер (3-ий уровень)",
+ "item.oc.server3": "Сервер (Творческий)",
+ "item.oc.tablet": "Планшет",
+ "item.oc.tabletcase0": "Корпус планшета (1-ый уровень)",
+ "item.oc.tabletcase1": "Корпус планшета (2-ой уровень)",
+ "item.oc.tabletcase3": "Корпус планшета (Креатив)",
+ "item.oc.terminal": "Беспроводной терминал",
+ "item.oc.terminalserver": "Терминальный сервер",
+ "item.oc.texturepicker": "Определитель текстур",
+ "item.oc.transistor": "Транзистор",
+ "item.oc.upgradeangel": "\"Ангельское\" улучшение",
+ "item.oc.upgradebattery0": "Улучшение \"Ёмкость\" (1-ый уровень)",
+ "item.oc.upgradebattery1": "Улучшение \"Ёмкость\" (2-ой уровень)",
+ "item.oc.upgradebattery2": "Улучшение \"Ёмкость\" (3-ий уровень)",
+ "item.oc.upgradechunkloader": "Улучшение \"Загрузчик чанков\"",
+ "item.oc.upgradecontainercard0": "Контейнер для карты (1-ый уровень)",
+ "item.oc.upgradecontainercard1": "Контейнер для карты (2-ой уровень)",
+ "item.oc.upgradecontainercard2": "Контейнер для карты (3-ий уровень)",
+ "item.oc.upgradecontainerupgrade0": "Контейнер для улучшения (1-ый уровень)",
+ "item.oc.upgradecontainerupgrade1": "Контейнер для улучшения (2-ой уровень)",
+ "item.oc.upgradecontainerupgrade2": "Контейнер для улучшения (3-ий уровень)",
+ "item.oc.upgradecrafting": "Улучшение \"Верстак\"",
+ "item.oc.upgradedatabase0": "Улучшение \"База данных\" (1-ый уровень)",
+ "item.oc.upgradedatabase1": "Улучшение \"База данных\" (2-ой уровень)",
+ "item.oc.upgradedatabase2": "Улучшение \"База данных\" (3-ий уровень)",
+ "item.oc.upgradeexperience": "Улучшение \"Опыт\"",
+ "item.oc.upgradegenerator": "Улучшение \"Генератор\"",
+ "item.oc.upgradehover0": "Улучшение \"Парение\" (1-ый уровень)",
+ "item.oc.upgradehover1": "Улучшение \"Парение\" (2-ый уровень)",
+ "item.oc.upgradeinventory": "Улучшение \"Инвентарь\"",
+ "item.oc.upgradeinventorycontroller": "Улучшение \"Контроллер инвентаря\"",
+ "item.oc.upgradeleash": "Улучшение \"Поводок\"",
+ "item.oc.upgrademf": "МФУ",
+ "item.oc.upgradenavigation": "Улучшение \"Навигация\"",
+ "item.oc.upgradepiston": "Улучшение \"Поршень\"",
+ "item.oc.upgradesign": "Улучшение \"Контроллер табличек\"",
+ "item.oc.upgradesolargenerator": "Улучшение \"Солнечный генератор\"",
+ "item.oc.upgradetank": "Улучшение \"Бак для жидкостей\"",
+ "item.oc.upgradetankcontroller": "Улучшение \"Контроллер бака\"",
+ "item.oc.upgradetractorbeam": "Улучшение \"Притягивающий луч\"",
+ "item.oc.upgradetrading": "Улучшение \"Торговля\"",
+ "item.oc.wirelessnetworkcard0": "Плата беспроводной сети (1-ый уровень)",
+ "item.oc.wirelessnetworkcard1": "Плата беспроводной сети (2-ой уровень)",
+ "item.oc.worldsensorcard": "Карта-мировой сенсор",
+ "item.oc.wrench": "Ключ",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "Дрон",
+ "oc:gui.Analyzer.Address": "§6Адрес§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Адрес скопирован в буфер обмена.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Скорость зарядки§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Имя компонента§f: %s",
+ "oc:gui.Analyzer.Components": "§6Количество подключенных компонентов§f: %s",
+ "oc:gui.Analyzer.CopyToClipboard": "Кликните для копирования в буфер обмена.",
+ "oc:gui.Analyzer.LastError": "§6Последняя ошибка§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Имя§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Владелец§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Опыт§f: %s (Уровень: %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6Накоплено энергии§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Всего накоплено энергии§f: %s",
+ "oc:gui.Analyzer.Users": "§6Пользователи§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Уровень сигнала§f: %s",
+ "oc:gui.Assembler.Collect": "Заберите результат сборки",
+ "oc:gui.Assembler.Complexity": "Сложность: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Вставьте системный блок",
+ "oc:gui.Assembler.InsertCPU": "Вставьте процессор",
+ "oc:gui.Assembler.InsertRAM": "Вставьте память",
+ "oc:gui.Assembler.Progress": "Прогресс: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Собрать",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Видеокарта",
+ "oc:gui.Assembler.Warning.Inventory": "Улучшение \"Инвентарь\"",
+ "oc:gui.Assembler.Warning.Keyboard": "Клавиатура",
+ "oc:gui.Assembler.Warning.OS": "Загрузочный диск",
+ "oc:gui.Assembler.Warning.Screen": "Монитор",
+ "oc:gui.Assembler.Warnings": "§eВнимание§7: Отсутствуют рекомендуемые компоненты.",
+ "oc:gui.Chat.NewVersion": "Доступна новая версия: %s",
+ "oc:gui.Chat.TextureName": "§7Имя текстуры: §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "Возникли §cошибки§f при преобразовании классов. Пожалуйста, сообщите об этом, а также приложите файл FML §alatest.log§f/§afml-server-latest.log§f!",
+ "oc:gui.Chat.WarningFingerprint": "§cВНИМАНИЕ§f - несовпадение отпечатка файла! Ожидаемый: '§a%s§f', полученный: '§e%s§f'. Если Вы не разработчик, использующий деобфусцированную версию мода, то §lкрайне§f желательно заново скачать OpenComputers, поскольку JAR-файл, возможно, был изменён.",
+ "oc:gui.Chat.WarningLink": "Невозможно открыть ссылку: %s",
+ "oc:gui.Chat.WarningLuaFallback": "Исходные библиотеки Lua не доступны, компьютеры не смогут сохранять своё состояние. Они перезагрузятся после выгрузки чанка.",
+ "oc:gui.Chat.WarningProjectRed": "Вы используете версию Project: Red, несовместимую с OpenComputers. Попробуйте обновить Project: Red.",
+ "oc:gui.Chat.WarningRecipes": "Произошла ошибка при загрузке одного или нескольких рецептов. Некоторые предметы могут не крафтиться. Проверьте логи, чобы узнать подробнее.",
+ "oc:gui.Drive.Managed": "Файловый режим",
+ "oc:gui.Drive.Unmanaged": "Блочный режим",
+ "oc:gui.Drive.Warning": "§lВнимание§r: переключение режимов очищает диск!",
+ "oc:gui.Error.ComponentOverflow": "Слишком много компонентов подключено к компьютеру.",
+ "oc:gui.Error.InternalError": "Возникла внутренняя ошибка, пожалуйста, посмотрите лог-файл. Возможно, это баг.",
+ "oc:gui.Error.NoCPU": "Не установлен процессор.",
+ "oc:gui.Error.NoEnergy": "Недостаточно энергии.",
+ "oc:gui.Error.NoRAM": "Не установлена память.",
+ "oc:gui.Error.OutOfMemory": "Недостаточно памяти.",
+ "oc:gui.Manual.Blocks": "Блоки OpenComputers",
+ "oc:gui.Manual.Home": "Главная страница",
+ "oc:gui.Manual.Items": "Предметы OpenComputers",
+ "oc:gui.Manual.Warning.BlockMissing": "Блок недоступен.",
+ "oc:gui.Manual.Warning.ImageMissing": "Изображение не найдено.",
+ "oc:gui.Manual.Warning.ItemMissing": "Предмет недоступен.",
+ "oc:gui.Manual.Warning.OreDictMissing": "Запись Ore Dictionary недоступна.",
+ "oc:gui.Raid.Warning": "§4Добавление диска очистит его.\nУдаление диска очистит RAID.",
+ "oc:gui.Robot.Power": "Энергия",
+ "oc:gui.Robot.TurnOff": "Выключить",
+ "oc:gui.Robot.TurnOn": "Включить",
+ "oc:gui.Rack.Back": "Сзади",
+ "oc:gui.Rack.Bottom": "Снизу",
+ "oc:gui.Rack.Left": "Слева",
+ "oc:gui.Rack.None": "Нет",
+ "oc:gui.Rack.Right": "Справа",
+ "oc:gui.Rack.Enabled": "Включено",
+ "oc:gui.Rack.Disabled": "Выключено",
+ "oc:gui.Rack.Top": "Сверху",
+ "oc:gui.Switch.TransferRate": "Цикличность",
+ "oc:gui.Switch.PacketsPerCycle": "Пакеты / цикл",
+ "oc:gui.Switch.QueueSize": "Размер очереди",
+ "oc:gui.Terminal.InvalidKey": "Неверный ключ, скорее всего, к серверу уже подключен другой терминал.",
+ "oc:gui.Terminal.OutOfRange": "Нет сигнала.",
+ "oc:container.accesspoint": "Точка доступа",
+ "oc:container.adapter": "Адаптер",
+ "oc:container.case": "Компьютер",
+ "oc:container.charger": "Зарядное устройство",
+ "oc:container.disassembler": "Разборщик",
+ "oc:container.diskdrive": "Дисковод",
+ "oc:container.printer": "Принтер",
+ "oc:container.raid": "RAID",
+ "oc:container.relay": "Ретранслятор",
+ "oc:container.server": "Сервер",
+ "oc:container.rack": "Серверная стойка",
+ "oc:container.switch": "Коммутатор",
+ "oc:container.tabletwrapper": "Планшет",
+ "key.opencomputers.clipboardPaste": "Вставить из буфера обмена",
+ "key.opencomputers.materialCosts": "Показать стоимость в материалах",
+ "oc:tooltip.accesspoint": "Работает как коммутатор, но и с беспроводными сетями.",
+ "oc:tooltip.abstractbuscard": "Обеспечивает взаимодействие с абстрактной шиной из §fStargateTech 2§7 (отправка и приём LIP-пакетов).",
+ "oc:tooltip.acid": "Высокотоксичная псевдо-жидкость, которую обычно пьют только определённые пираты. Однако может быть полезна и при других применениях.",
+ "oc:tooltip.adapter": "Используется для контроля некомпонентных блоков, таких как обычные блоки или блоки из других модов.",
+ "oc:tooltip.alu": "Выполняет арифметические вычисления, так что вам не придётся возиться с ними.",
+ "oc:tooltip.analyzer": "Используется для отображения информации о блоках, такой как §fадрес§7 или §fимя компонента§7.\nТакже отображает ошибку, вызвавшую сбой компьютера.",
+ "oc:tooltip.apu": "Это процессор со встроенной видеокартой, полезный, когда вам требуется освободить ещё один слот для карт.\nПоддерживается компонентов: §f%s§7\nМаксимальное разрешение: §f%sx%s§7\nМаксимальная глубина цвета: §f%s§7\nОпераций в тик: §f%s§7",
+ "oc:tooltip.assembler": "Позволяет собирать роботов и другие устройства из ряда различных частей компьютера.",
+ "oc:tooltip.cable": "Простой и дешёвый способ соединить компоненты между собой.",
+ "oc:tooltip.capacitor": "Накапливает энергию для дальнейшего использования. Может быть очень быстро заполнен и опустошён.",
+ "oc:tooltip.cardbase": "Как видно из названия, это основа для всех карт расширения.",
+ "oc:tooltip.case": "Системный блок - основа компьютера, содержащий §fкарты расширения§7, §fОЗУ§7 и §fжёсткие диски§7.\nСлотов: §f%s§7",
+ "oc:tooltip.chamelium": "Базовый материал для 3D печати. Не глотать: может привести к слепоте и временным отсутствием присутствия.",
+ "oc:tooltip.chameliumblock": "Удобен для окрашенных 3D моделей или просто как цветной блок для вашей базы.",
+ "oc:tooltip.charger": "Передаёт энергию из аккумуляторов вплотную находящимся роботам и дронам. Скорость передачи зависит от §fсилы сигнала красного камня§7: отсутствие сигнала означает \"не заряжать\", а полный сигнал - \"заряжать на полной скорости\".",
+ "oc:tooltip.circuitboard": "Мы уже очень близки. Может быть вытравлена, чтобы получить печатную плату.",
+ "oc:tooltip.controlunit": "Это штука, которая... контролирует... что-то. Она необходима, чтобы создать центральный процессор. Так что, да, она очень важна.",
+ "oc:tooltip.componentbus": "Позволяет серверам взаимодействовать с большим количеством компонентов.\nПоддерживается компонентов: §f%s§7",
+ "oc:tooltip.cpu": "Является важным компонентом в компьютере. Тактовая частота немного нестабильна, но что вы ожидали, если он работает на карманных солнечных часах. Количество поддерживаемых компонентов: §f%s§7",
+ "oc:tooltip.cpu.architecture": "Архитектура: §f%s§7",
+ "oc:tooltip.cuttingwire": "Используется для нарезки глиняных блоков в пластины. Рвётся после использования, что делает её, пожалуй, самым неэффективным инструментом.",
+ "oc:tooltip.datacard0": "Обеспечивает поддержку нескольких продвинутых алгоритмов, таких как хеширование и сжатие.",
+ "oc:tooltip.datacard1": "Обеспечивает поддержку нескольких продвинутых алгоритмов, таких как AES-шифрование, хеширование и сжатие.",
+ "oc:tooltip.datacard2": "Обеспечивает поддержку нескольких продвинутых алгоритмов, таких как AES-шифрование, эллиптическая криптография, хеширование и сжатие.",
+ "oc:tooltip.debugcard": "Креативный предмет, позволяет манипулировать игровым миром. Используйте на свой страх и риск.",
+ "oc:tooltip.debugger": "Может быть использован для вывода отладочной информации о внутренней сети. Используйте только тогда, когда попросил разработчик.",
+ "oc:tooltip.diamondchip": "Небольшой кусочек некогда сияющего алмаза. Он больше никогда не будет таким, как прежде.",
+ "oc:tooltip.disassembler": "Разделяет предметы на исходные компоненты. §lВнимание§7: возвращённые предметы имеют шанс %s%% сломаться!",
+ "oc:tooltip.disk": "Примитивный носитель, который может быть использован для создания постоянных запоминающих устройств.",
+ "oc:tooltip.diskdrive.cc": "§aПоддерживаются§7 дискеты из ComputerCraft.",
+ "oc:tooltip.diskdrive": "Позволяет читать и записывать дискеты. Может быть установлен в роботов, что позволит затем вставлять дискеты.",
+ "oc:tooltip.diskdrivemountable": "Работает так же, как и обычный дисковод, но может быть вставлен только в серверную стойку.",
+ "oc:tooltip.diskusage": "Занято %s/%s байт",
+ "oc:tooltip.diskmodemanaged": "Режим: файловый",
+ "oc:tooltip.diskmodeunmanaged": "Режим: блочный",
+ "oc:tooltip.drone": "Дроны это легкие и быстрые устройства, но с ограниченным инвентарем.",
+ "oc:tooltip.dronecase": "Корпус, предназначенный для создания дрона в сборщике. Вмещает малое количество компонентов и предоставляет левитацию с помощью силы камня края.",
+ "oc:tooltip.eeprom": "Маленькое программируемое хранилище, которое содержит BIOS для запуска компьютеров.",
+ "oc:tooltip.fakeendstone": "Почти такой же, как и настоящий камень края, даже эмулирует его легкость!",
+ "oc:tooltip.geolyzer": "Позволяет сканировать твёрдость блоков в окрестности. Эта информация может быть полезна для создания голограммы области или для обнаружения руд.",
+ "oc:tooltip.graphicscard": "Используется для изменения того, что отображается на мониторах.\nМаксимальное разрешение: §f%sx%s§7\nМаксимальная глубина цвета:§f%s§7\nОпераций/такт: §f%s§7",
+ "oc:tooltip.hoverboots": "Прыгайте выше, падайте глубже, бегайте быстрее. Это и многое другое с нашими новыми Парящими ботинками (TM).",
+ "oc:tooltip.inkcartridge": "Используется в 3D печати. По таинственным причинам ему не нужно оставаться в принтере.",
+ "oc:tooltip.inkcartridgeempty": "Этот картридж выглядит пустым. Заправьте его с помощью красителей. Или выбросьте.",
+ "oc:tooltip.internetcard": "Эта карта позволяет делать HTTP-запросы и использовать реальные TCP сокеты.",
+ "oc:tooltip.interweb": "Поздравляем, вы выиграли одну (1) интерсеть. Подключиться к ней можно с помощью Интернет-платы. Осторожно: не кормите троллей.",
+ "oc:tooltip.ironnugget": "Самородок, созданный из железа. Может, именно поэтому он и назван железным самородком? Хм...",
+ "oc:tooltip.keyboard": "Присоединяется к монитору, позволяя вводить информацию.",
+ "oc:tooltip.hologram0": "Объёмный дисплей, управляемый компьютером и использующийся для отображения произвольных воксельных структур.\nРазрешение: §f48x32x48§7\nМаксимальный масштаб: §f3x§7\nГлубина цвета: §fМонохромный§7",
+ "oc:tooltip.hologram1": "Объёмный дисплей, управляемый компьютером и использующийся для отображения произвольных воксельных структур.\nРазрешение: §f48x32x48§7\nМаксимальный масштаб: §f4x§7\nГлубина цвета: §fТрёхцветный§7",
+ "oc:tooltip.linkedcard": "Они изготавливаются в парах и могут общаться только с партнёром. Тем не менее, общаться они могут на любом расстоянии - даже между измерениями. Однако для отправки сообщения нужно довольно много энергии.",
+ "oc:tooltip.linkedcard_channel": "§8Канал: %s§7",
+ "oc:tooltip.manual": "Содержит всю информацию о моде OpenComputers, которая вам может когда-либо понадобиться. И даже больше. По невероятно низкой цене... §oнажмите R для продолжения§7.",
+ "oc:tooltip.materialcosts": "Удерживайте [§f%s§7] для показа материалов.",
+ "oc:tooltip.materials": "Материалы:",
+ "oc:tooltip.memory": "Необходима для запуска компьютера. Чем больше ОЗУ, тем более требовательные программы Вы можете запустить.",
+ "oc:tooltip.microchip": "Чип, ранее известный как интегральная схема. Понятия не имею почему, но он работает с красным камнем.",
+ "oc:tooltip.microcontroller": "Микроконтроллеры - это компьютеры, сведённые к самым базовым вещам. Они используются для выполнения специфических задач и выполняют программу, записанную на EEPROM.\n§cНе могут взаимодействовать с внешними компонентами.§7",
+ "oc:tooltip.microcontrollercase": "Базовый компонент для создания микроконтроллеров. Положите в сборщик, чтобы установить компоненты, и соберите микроконтроллер.",
+ "oc:tooltip.motionsensor": "Может обнаружить движение ближайших живых существ. Требуется прямая линия видимости.",
+ "oc:tooltip.nanomachines": "Блок управления и кучка нанороботов для приема внутрь, если вы решились.",
+ "oc:tooltip.networkcard": "Позволяет обмениваться сообщениями между соединённым друг с другом - с помощью кабеля или других блоков - компьютерами.",
+ "oc:tooltip.poweracceptor": "Скорость преобразования энергии: §f%s/t§7",
+ "oc:tooltip.powerconverter.buildcraft": "§fBuildCraft MJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.factorization": "§fFactorization Charge§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.industrialcraft2": "§fIndustrialCraft² EU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.mekanism": "§fMekanism Joules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.thermalexpansion": "§fThermal Expansion RF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.resonantengine": "§fResonant Engine Coulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Преобразует энергию из других модов во внутренний тип энергии. Соотношение энергии:",
+ "oc:tooltip.powerdistributor": "Передаёт энергию между различными сетями. Полезно, если требуется запитать от одного преобразователя несколько сетей, которые должны оставаться разделёнными.",
+ "oc:tooltip.present": "Откройте этот подарок, чтобы получить немного §kчего-то§7!\n§8Крафтите предметы OpenComputers в нужное время, чтобы получить шанс получить подарок.§7",
+ "oc:tooltip.print.beaconbase": "§8Используется в качестве основы для маяка.",
+ "oc:tooltip.print.lightvalue": "§8Сила излучаемого света: %s.",
+ "oc:tooltip.print.redstonelevel": "§8Сила выдаваемого красного сигнала: %s.",
+ "oc:tooltip.printedcircuitboard": "Основа плат, памяти и прочего.",
+ "oc:tooltip.printer": "Позволяет печатать пользовательские 3D-модели, используя хамелиум и картриджи с чернилами. Должен быть настроен с помощью компьютера. Держите подальше от детей.",
+ "oc:tooltip.raid": "Позволяет соединять три жестких диска в единую файловую систему, которую могут использовать все подключенные компьютеры.",
+ "oc:tooltip.rawcircuitboard": "Может быть закалена в печи для получения печатной платы.",
+ "oc:tooltip.redstone": "Позволяет считывать и подавать сигналы красного камня вокруг блока. Контролируется любым подключенным компьютером. Иными словами, это что-то вроде внешней платы на красном камне.",
+ "oc:tooltip.redstonecard.projectred": "Мод §fProjectRed§7 §aподдерживается§7.",
+ "oc:tooltip.redstonecard.redlogic": "Мод §fRedLogic§7 §aподдерживается§7.",
+ "oc:tooltip.redstonecard.rednet": "Мод §fRedNet§7 §aподдерживается§7.",
+ "oc:tooltip.redstonecard.wirelesscbe": "Мод §fWireless Redstone (ChickenBones)§7 §aподдерживается§7.",
+ "oc:tooltip.redstonecard.wirelesssv": "Мод §fWireless Redstone (SlimeVoid)§7 §aподдерживается§7.",
+ "oc:tooltip.redstonecard": "Позволяет считывать и подавать сигналы красного камня вокруг компьютера или робота.",
+ "oc:tooltip.relay": "Позволяет соединять различные сети между собой. Передаются только сообщения, компоненты между сетями не будут доступны. Используйте его для разделения сетей с возможностью пересылать сообщения между ними.",
+ "oc:tooltip.robot": "В отличие от компьютеров, роботы могут передвигаться и взаимодействовать с миром, как игрок.\n§cНе могут подключаться к внешним компонентам.§7",
+ "oc:tooltip.robot_level": "§fУровень§7: §a%s§7.",
+ "oc:tooltip.robot_storedenergy": "§fНакопленная энергия§7: §a%s§7.",
+ "oc:tooltip.screen": "Отображает текст, передаваемый видеокартой.\nМаксимальное разрешение: §f%sx%s§7\nМаксимальная глубина цвета: §f%s§7",
+ "oc:tooltip.server": "Это сервер. Есть много других, похожих на него, но только этот может быть улучшен компонентами, как системный блок. Можно включить после размещения в серверную стойку.",
+ "oc:tooltip.server.components": "Установленные компоненты:",
+ "oc:tooltip.rack": "Обеспечивает работу до четырёх серверов или других монтируемых компонентов.",
+ "oc:tooltip.switch": "Позволяет соединять различные сети между собой. Передаются только сообщения, компоненты между сетями не будут доступны. Используйте его для разделения сетей с возможностью пересылать сообщения между ними.",
+ "oc:tooltip.tablet": "Планшет, полностью готовый к работе с Lua. Может быть отключен нажатием правой кнопки мыши + Shift.",
+ "oc:tooltip.tabletcase": "Простой корпус для планшета. Поместите в сборщик, чтобы вставить компоненты, и соберите себе планшетный компьютер.",
+ "oc:tooltip.terminal": "Позволяет дистанционно управлять сервером, пока вы находитесь в радиусе его действия. Действует как портативный дисплей с клавиатурой.\nShift+ПКМ по серверу терминалов в стойке для привязки.",
+ "oc:tooltip.terminalserver": "Компонент, к которому можно подключить беспроводной терминал. Имеет виртуальный экран и клавиатуру.",
+ "oc:tooltip.texturepicker": "Простой инструмент, позволяющий узнать название текстуры блока, которое можно использовать в 3D печати.",
+ "oc:tooltip.tier": "§8Уровень %s",
+ "oc:tooltip.netsplitter": "Работает как переключатель. Соединение каждой стороны переключается ключем. При подаче сигнала красного камня все соединения инвертируются.",
+ "oc:tooltip.toolong": "Удерживайте [§f%s§7], чтобы отобразить описание.",
+ "oc:tooltip.transistor": "Базовый элемент для большинства частей компьютера. Он немного деформирован, но отлично выполняет свою работу.",
+ "oc:tooltip.transposer": "Позволяет автоматизировать перемещение предметов и жидкостей между соседними инвентарями и хранилищами жидкости.",
+ "oc:tooltip.upgradeangel": "Позволяет роботам размещать блоки в воздухе без точки опоры.",
+ "oc:tooltip.upgradebattery": "Увеличивает количество энергии, которую робот может хранить, что позволяет ему работать дольше без перезарядки.",
+ "oc:tooltip.upgradechunkloader": "Если робот движется в лесу и никто его не видит, действительно ли он движется? Данное улучшение гарантирует это. Оно держит чанк, в котором находится робот, загруженным, но постоянно потребляет энергию во время работы.",
+ "oc:tooltip.upgradecontainercard": "Это улучшение-контейнер позволяет динамически устанавливать и снимать плату с собранного робота.\nМаксимальный уровень: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "Это улучшение-контейнер позволяет динамически устанавливать и снимать другое улучшение с собранного робота.\nМаксимальный уровень: §f%s§7",
+ "oc:tooltip.upgradecrafting": "Позволяет роботам использовать верхнюю левую часть инвентаря для крафта предметов. Вещи должны быть расположены в том же порядке, что и в верстаке.",
+ "oc:tooltip.upgradedatabase": "Позволяет хранить информацию о предметах для последующего использования другими компонентами.\nПоддерживается записей: §f%s§7",
+ "oc:tooltip.upgradeexperience": "Это улучшение позволяет роботу накапливать опыт при выполнении различных операций. Чем больше у них опыта, тем больше энергии они могут хранить, могут быстрее собирать блоки и эффективнее использовать инструменты.",
+ "oc:tooltip.upgradegenerator": "Позволяет роботам генерировать энергию из сжигаемого топлива прямо на ходу.\n§fЭффективность§7: §a%s%%§7",
+ "oc:tooltip.upgradehover": "Данное улучшение позволяет роботам летать выше над землей без необходимости лазать по стенам.\nМаксимальная высота: §f%s§7",
+ "oc:tooltip.upgradeinventory": "Это улучшение даёт место в инвентаре для робота. Без него роботы не смогут хранить предметы внутри.",
+ "oc:tooltip.upgradeinventorycontroller": "Это улучшение позволяет роботу контролировать взаимодействие с внешними инвентарями и менять свой экипированный инструмент предметом из его инвентаря.",
+ "oc:tooltip.upgradeleash": "Позволяет некоторым устройствам, таким как дроны, цеплять животных на поводок. Много животных, при этом.",
+ "oc:tooltip.upgrademf": "Позволяет адаптерам взаимодействовать с блоками на удалении от них.",
+ "oc:tooltip.upgrademf.linked": "§fСоединение установлено§7",
+ "oc:tooltip.upgrademf.unlinked": "§fНет соединения§7",
+ "oc:tooltip.upgradenavigation": "Позволяет определять положение и ориентацию робота. Положение определяется относительно центра карты, использованной при крафте улучшения.",
+ "oc:tooltip.upgradepiston": "Позволяет двигать блоки, как поршни. §lНе§7 может двигать животных, однако.",
+ "oc:tooltip.upgradesign": "Позволяет читать и писать текст на табличках.",
+ "oc:tooltip.upgradesolargenerator": "Позволяет роботам генерировать энергию из солнечного света прямо на ходу. Требует прямую видимость неба над роботом. Генерирует энергию на скорости %s%% от двигателя Стирлинга.",
+ "oc:tooltip.upgradetank": "Позволяет роботам и дронам взаимодействовать с жидкостями. Без него они не смогут хранить жидкость.",
+ "oc:tooltip.upgradetankcontroller": "Позволяет роботам и дронам взамодействовать в внешними хранилищами жидкости, а также заливать и выливать жидкости в них.",
+ "oc:tooltip.upgradetractorbeam": "Даёт роботу самую невероятно продвинутую технологию под кодовым названием \"Магнит для предметов\". Позволяет роботу подбирать предметы в радиусе 3 блоков от своего расположения.",
+ "oc:tooltip.waypoint": "Добавляет путевую точку для устройств с навигационным улучшением.",
+ "oc:tooltip.wirelessnetworkcard": "Позволяет передавать сетевые сообщения по беспроводному каналу в дополнение к проводному. Вы можете настроить §fсилу сигнала§7, чтобы контролировать, насколько далеко должны отправляться сообщения. Более высокая сила сигнала приводит к повышенному потреблению энергии.",
+ "oc:tooltip.worldsensorcard": "Позволяет получать информацию об атмосфере и гравитации на планетах, добавляемых модом GalactiCraft. Используйте на свой страх и риск. Производитель не несет ответственности за материальный ущерб и увечья. У нас есть адвокаты. И деньги. Даже не пытайтесь.",
+ "oc:tooltip.wrench": "Гибрид отвертки и ключа.",
+ "achievement.oc.adapter": "Мы едины",
+ "achievement.oc.adapter.desc": "Дайте поработать с другими модами!",
+ "achievement.oc.assembler": "Великолепно",
+ "achievement.oc.assembler.desc": "Время захватывать мир!",
+ "achievement.oc.cable": "Не трогай провода!",
+ "achievement.oc.cable.desc": "... они от этого ржавеют",
+ "achievement.oc.capacitor": "Батарея в комплекте",
+ "achievement.oc.capacitor.desc": "Вы не можете остановить это.",
+ "achievement.oc.card": "Мы принимаем карточки",
+ "achievement.oc.card.desc": "Для вашего удобства. Вам это понравится.",
+ "achievement.oc.case": "В случае возникновения неполадок",
+ "achievement.oc.case.desc": "Открывайте боковую крышку летом.",
+ "achievement.oc.charger": "Ладно, сделаем это",
+ "achievement.oc.charger.desc": "Пошла зарядка.. черт, опять забыл редстоун сигнал.",
+ "achievement.oc.chip": "Полезные мелочи",
+ "achievement.oc.chip.desc": "Ведь электронные лампы - прошлый век",
+ "achievement.oc.cpu": "Разогнанный",
+ "achievement.oc.cpu.desc": "Время нагрузить его по полной.",
+ "achievement.oc.disassembler": "Больше не нужно",
+ "achievement.oc.disassembler.desc": "Когда великолепные идеи оказываются не такими уж и великолепными",
+ "achievement.oc.diskDrive": "Карусель",
+ "achievement.oc.diskDrive.desc": "Небольшая емкость, зато какой звук!",
+ "achievement.oc.drone": "Вездесущее око",
+ "achievement.oc.drone.desc": "Небольшой брат следит за тобой.",
+ "achievement.oc.eeprom": "Он может быть только один",
+ "achievement.oc.eeprom.desc": "Для каждого компьютера, то есть. Для загрузки компьютера, вы знали?",
+ "achievement.oc.floppy": "Не подносить магнит",
+ "achievement.oc.floppy.desc": "Дискеты не любят магниты.",
+ "achievement.oc.geolyzer": "Назад на землю",
+ "achievement.oc.geolyzer.desc": "Он имеет необычные свойства.",
+ "achievement.oc.graphicsCard": "Последнее поколение",
+ "achievement.oc.graphicsCard.desc": "Покажи это.",
+ "achievement.oc.hdd": "Продавец хотдогов",
+ "achievement.oc.hdd.desc": "Нет, подождите, это не то, о чем вы подумали. Не роняйте его...",
+ "achievement.oc.hologram": "Гиперпространство",
+ "achievement.oc.hologram.desc": "Когда двух измерений уже не хватает",
+ "achievement.oc.keyboard": "Крошкохранитель-3000",
+ "achievement.oc.keyboard.desc": "Не рекомендуется переворачивать и трясти его",
+ "achievement.oc.microcontroller": "Маленькая сестренка",
+ "achievement.oc.microcontroller.desc": "Просто маленький компьютер",
+ "achievement.oc.motionSensor": "Оно двигается",
+ "achievement.oc.motionSensor.desc": "Как Майкл Джексон.",
+ "achievement.oc.networkCard": "Нам надо поговорить!",
+ "achievement.oc.networkCard.desc": "Оставайтесь на связи с дальними родственниками.",
+ "achievement.oc.openOS": "Поехали",
+ "achievement.oc.openOS.desc": "Неужели он включится.",
+ "achievement.oc.powerDistributor": "Поделись с ближним",
+ "achievement.oc.powerDistributor.desc": "Когда вы помогаете распределять энергию.",
+ "achievement.oc.rack": "Прямо в стойку",
+ "achievement.oc.rack.desc": "Не знаю, о чем думаете вы, я думал о серверной стойке.",
+ "achievement.oc.raid": "Чрезмерная избыточность",
+ "achievement.oc.raid.desc": "Только диски не вынимайте.",
+ "achievement.oc.ram": "Случайный доступ к памяти",
+ "achievement.oc.ram.desc": "Поздравляем, вы делаете это правильно.",
+ "achievement.oc.redstoneCard": "Есть контакт",
+ "achievement.oc.redstoneCard.desc": "Возврат к аналоговой технике.",
+ "achievement.oc.redstoneIO": "Выскочка",
+ "achievement.oc.redstoneIO.desc": "Когда все сигналы в нужных местах",
+ "achievement.oc.robot": "Бип-пип",
+ "achievement.oc.robot.desc": "УНИЧТОЖИТЬ!",
+ "achievement.oc.screen": "Вы пробовали выключить и снова включить?",
+ "achievement.oc.screen.desc": "Серьезно. Редстоун сигнал может выключать монитор.",
+ "achievement.oc.server": "Выделенный сервер",
+ "achievement.oc.server.desc": "Облачные вычисления, мы идем к вам.",
+ "achievement.oc.switch": "Сложная топология",
+ "achievement.oc.switch.desc": "Избегайте сложных связей и потери пакетов.",
+ "achievement.oc.tablet": "Несъедобно",
+ "achievement.oc.tablet.desc": "Держите подальше от маленьких детей, во избежание пропажи денег на вашей кредитной карте.",
+ "achievement.oc.transistor": "Редстоун, скажи \"Привет.\"",
+ "achievement.oc.transistor.desc": "Создайте транзистор. Потом послушайте музыку. Не благодарите меня.",
+ "achievement.oc.wirelessNetworkCard": "Сигналы",
+ "achievement.oc.wirelessNetworkCard.desc": "Время идти туда, где никогда не появлялся сигнал.",
+ "death.attack.oc.nanomachinesOverload.1": "%s был слишком жадным.",
+ "death.attack.oc.nanomachinesOverload.2": "%s получил нервный срыв.",
+ "death.attack.oc.nanomachinesOverload.3": "Нанороботы %s вышли из под контроля.",
+ "death.attack.oc.nanomachinesHungry.1": "%s был съеден нанороботами.",
+ "death.attack.oc.nanomachinesHungry.2": "%s не кормил нанороботов.",
+ "death.attack.oc.nanomachinesHungry.3": "%s был переварен нанороботами.",
+ "nei.options.inventory.oredict": "Показывать имена Ore Dictionary",
+ "nei.options.inventory.oredict.true": "Да",
+ "nei.options.inventory.oredict.false": "Нет",
+ "nei.usage.oc.Manual": "Открыть руководство",
+ "option.oc.address": "Адрес",
+ "option.oc.componentName": "Название компонента",
+ "option.oc.energy": "Энергия"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/tr_TR.lang b/src/main/resources/assets/opencomputers/lang/tr_TR.lang
deleted file mode 100644
index c5f2217a52..0000000000
--- a/src/main/resources/assets/opencomputers/lang/tr_TR.lang
+++ /dev/null
@@ -1,496 +0,0 @@
-# Based off /src/main/resources/assets/opencomputers/lang/en_US.lang
-# Initial localization by H. Utku Maden (Other authors should append their names in the list.)
-# ------
-# Some translational loses may have been introduced. (Language translations may not be 100% correct)
-# Please comment awkward translational situations.
-
-# Blocks
-#=====
-
-tile.oc.adapter.name=Dönüştürücü
-tile.oc.assembler.name=Elektronik Birleştirici
-tile.oc.cable.name=Kablo
-
-# This translation is prefered. Do not change to 'kapasitör' or 'kondansatör'.
-tile.oc.capacitor.name=Sığaç
-# Sounds wierd, but was made with 'halı' to keep consistancy with minecraft's own localization.
-tile.oc.carpetedcapacitor.name=Halılı Sığaç
-
-# Direct translation of tier does not exist, nearest is 'sınıf', but higher numbers are a worse object; so 'seviye' (level) was used
-tile.oc.case1.name=Bilgisayar Kasası (1. Seviye)
-tile.oc.case2.name=Bilgisayar Kasası (2. Seviye)
-tile.oc.case3.name=Bilgisayar Kasası (3. Seviye)
-tile.oc.casecreative.name=Bilgisayar Kasası (Yaratıcı)
-
-# Fictional things get fictional names
-tile.oc.chameliumblock.name=Şamelyum Küpü
-tile.oc.charger.name=Şarj Cihazı
-tile.oc.disassembler.name=Ayrıştırıcı
-tile.oc.diskdrive.name=Disket Sürücüsü
-tile.oc.endstone.name=End Taşı
-tile.oc.geolyzer.name=Jeolizer
-tile.oc.hologram1.name=Hologram Projektörü (1. Seviye)
-tile.oc.hologram2.name=Hologram Projektörü (2. Seviye)
-tile.oc.keyboard.name=Klavye
-tile.oc.microcontroller.name=Mikroişlemci
-tile.oc.motionsensor.name=Hareket Algılayıcı
-tile.oc.netsplitter.name=Ağ Bölücü
-tile.oc.powerconverter.name=Güç Dönüştürücü
-tile.oc.powerdistributor.name=Güç Dağıtıcı
-tile.oc.print.name=3B Çıktı
-tile.oc.printer.name=3B Yazıcı
-tile.oc.raid.name=RAID
-tile.oc.redstone.name=Kızıltaş G/Ç Küpü
-tile.oc.relay.name=Ağ Tamponu
-tile.oc.robot.name=Robot
-tile.oc.robotafterimage.name=Robot
-tile.oc.screen1.name=Ekran (1. Seviye)
-tile.oc.screen2.name=Ekran (2. Seviye)
-tile.oc.screen3.name=Ekran (3. Seviye)
-tile.oc.rack.name=Sunucu Rafı
-tile.oc.transposer.name=İletici
-tile.oc.waypoint.name=Yer İşareti
-
-# Items
-item.oc.abstractbuscard.name=Soyut Veriyolu Kartı
-item.oc.acid.name=İspirto?
-item.oc.alu.name=Aritmetik Mantık Birimi (ALU)
-item.oc.analyzer.name=Analiz Aleti
-item.oc.apu0.name=Eklentili İşlemci (APU) (1. Seviye)
-item.oc.apu1.name=Eklentili İşlemci (APU) (2. Seviye)
-item.oc.apu2.name=Eklentili İşlemci (APU) (Yaratıcı)
-item.oc.arrowkeys.name=Ok Tuşları
-item.oc.buttongroup.name=Harf Takımı
-item.oc.cardbase.name=Ham Bilgisayar Kartı
-item.oc.chamelium.name=Şamelyum
-item.oc.circuitboard.name=Devre Kartı
-item.oc.componentbus0.name=Cihaz Veriyolu (1. Seviye)
-item.oc.componentbus1.name=Cihaz Veriyolu (2. Seviye)
-item.oc.componentbus2.name=Cihaz Veriyolu (3. Seviye)
-item.oc.componentbus3.name=Cihaz Veriyolu (Yaratıcı)
-item.oc.controlunit.name=Yönetim Birimi (CU)
-item.oc.cpu0.name=İşlemci (CPU) (1. Seviye)
-item.oc.cpu1.name=İşlemci (CPU) (2. Seviye)
-item.oc.cpu2.name=İşlemci (CPU) (3. Seviye)
-item.oc.cuttingwire.name=Kesme Teli
-item.oc.datacard0.name=Veri Kartı (1. Seviye)
-item.oc.datacard1.name=Veri Kartı (2. Seviye)
-item.oc.datacard2.name=Veri Kartı (3. Seviye)
-item.oc.debugcard.name=Hata Ayıklama Kartı
-item.oc.debugger.name=Ağ Hata Ayıklama Aleti
-item.oc.diamondchip.name=Elmas Kesiti
-item.oc.disk.name=Disk Bileşeni
-item.oc.diskdrivemountable.name=Disk
-item.oc.drone.name=Drone
-item.oc.dronecase0.name=Drone Kasası (1. Seviye)
-item.oc.dronecase1.name=Drone Kasası (2. Seviye)
-item.oc.dronecase3.name=Drone Kasası (3. Seviye)
-item.oc.eeprom.name=EEPROM
-item.oc.floppydisk.name=Disket
-item.oc.graphicscard0.name=Ekran Kartı (1. Seviye)
-item.oc.graphicscard1.name=Ekran Kartı (2. Seviye)
-item.oc.graphicscard2.name=Ekran Kartı (3. Seviye)
-item.oc.harddiskdrive0.name=Hard Disk (1. Seviye)
-item.oc.harddiskdrive1.name=Hard Disk (2. Seviye)
-item.oc.harddiskdrive2.name=Hard Disk (3. Seviye)
-item.oc.hoverboots.name=Uçma Botu
-item.oc.inkcartridge.name=Mürekkep Kartuşu
-item.oc.inkcartridgeempty.name=Mürekkep Kartuşu (Boş)
-item.oc.internetcard.name=İnternet Kartı
-item.oc.interweb.name=Ağ?
-item.oc.ironnugget.name=Demir Parçası
-item.oc.linkedcard.name=Bağlantılı Kart
-item.oc.manual.name=OpenComputers Kullanma Kılavuzu
-item.oc.memory0.name=Bellek (1. Seviye)
-item.oc.memory1.name=Bellek (1,5. Seviye)
-item.oc.memory2.name=Bellek (2. Seviye)
-item.oc.memory3.name=Bellek (2,5. Seviye)
-item.oc.memory4.name=Bellek (3. Seviye)
-item.oc.memory5.name=Bellek (3,5. Seviye)
-item.oc.microchip0.name=Entegre Devre (1. Seviye)
-item.oc.microchip1.name=Entegre Devre (2. Seviye)
-item.oc.microchip2.name=Entegre Devre (3. Seviye)
-item.oc.microcontrollercase0.name=Mikroişlemci Kasası (1. Seviye)
-item.oc.microcontrollercase1.name=Mikroişlemci Kasası (2. Seviye)
-item.oc.microcontrollercase3.name=Mikroişlemci Kasası (Yaratıcı)
-item.oc.nanomachines.name=Nanomakine
-item.oc.networkcard.name=Ağ Kartı
-item.oc.numpad.name=Tuş Takımı
-item.oc.present.name=Çam Sakızı...
-item.oc.printedcircuitboard.name=Devre Kartı (PCB)
-item.oc.rawcircuitboard.name=Ham Devre Kartı
-item.oc.redstonecard0.name=Kızıltaş Kartı (1. Seviye)
-item.oc.redstonecard1.name=Kızıltaş Kartı (2. Seviye)
-item.oc.server0.name=Sunucu (1. Seviye)
-item.oc.server1.name=Sunucu (2. Seviye)
-item.oc.server2.name=Sunucu (3. Seviye)
-item.oc.server3.name=Sunucu (Yaratıcı)
-item.oc.tablet.name=Tablet
-item.oc.tabletcase0.name=Tablet Kasası (1. Seviye)
-item.oc.tabletcase1.name=Tablet Kasası 500640(2. Seviye)
-item.oc.tabletcase3.name=Tablet Kasası (Yaratıcı)
-item.oc.terminal.name=Uzaktan Uçbirim
-item.oc.terminalserver.name=Uçbirim Sunucusu
-item.oc.texturepicker.name=Doku Seçici
-item.oc.transistor.name=Transistör
-item.oc.upgradeangel.name=Melek Eklentisi
-item.oc.upgradebattery0.name=Batarya Eklentisi (1. Seviye)
-item.oc.upgradebattery1.name=Batarya Eklentisi (2. Seviye)
-item.oc.upgradebattery2.name=Batarya Eklentisi (3. Seviye)
-item.oc.upgradechunkloader.name=Kesiti-yüklü-tut Eklentisi
-item.oc.upgradecontainercard0.name=Kart Yuvası (1. Seviye)
-item.oc.upgradecontainercard1.name=Kart Yuvası (2. Seviye)
-item.oc.upgradecontainercard2.name=Kart Yuvası (3. Seviye)
-item.oc.upgradecontainerupgrade0.name=Eklenti Yuvası (1. Seviye)
-item.oc.upgradecontainerupgrade1.name=Eklenti Yuvası (2. Seviye)
-item.oc.upgradecontainerupgrade2.name=Eklenti Yuvası (3. Seviye)
-item.oc.upgradecrafting.name=Üretim Eklentisi
-item.oc.upgradedatabase0.name=Veritabanı Eklentisi (1. Seviye)
-item.oc.upgradedatabase1.name=Veritabanı Eklentisi (2. Seviye)
-item.oc.upgradedatabase2.name=Veritabanı Eklentisi (3. Seviye)
-item.oc.upgradeexperience.name=Deneyim Eklentisi
-item.oc.upgradegenerator.name=Jeneratör Eklentisi
-item.oc.upgradehover0.name=Uçma Eklentisi (1. Seviye)
-item.oc.upgradehover1.name=Uçma Eklentisi (2. Seviye)
-item.oc.upgradeinventory.name=Envanter Eklentisi
-item.oc.upgradeinventorycontroller.name=Envanter Yönetimi Eklentisi
-item.oc.upgradeleash.name=Kayış Eklentisi
-item.oc.upgrademf.name=MFU
-item.oc.upgradenavigation.name=Yönbulma Eklentisi
-item.oc.upgradepiston.name=Piston Eklentisi
-item.oc.upgradesign.name=Tabela G/Ç Eklentisi
-item.oc.upgradesolargenerator.name=Güneş Enerjisi Eklentisi
-item.oc.upgradetank.name=Tank Eklentisi
-item.oc.upgradetankcontroller.name=Tank Yönetimi Eklentisi
-item.oc.upgradetractorbeam.name=Çekme Işını Eklentisi
-item.oc.upgradetrading.name=Ticaret Eklentisi
-item.oc.wirelessnetworkcard0.name=Kablosuz Ağ Kartı (1. Seviye)
-item.oc.wirelessnetworkcard1.name=Kablosuz Ağ Kartı (2. Seviye)
-item.oc.worldsensorcard.name=Dünya Algılayıcı Kartı
-item.oc.wrench.name=Tornanahtar
-
-# Entities
-entity.oc.Drone.name=Drone
-
-# GUI
-oc:gui.Analyzer.Address=§6Adres§f: %s
-oc:gui.Analyzer.AddressCopied=Adres panoya kopyalandı
-oc:gui.Analyzer.ChargerSpeed=§6Şarj hızı§f: %s
-oc:gui.Analyzer.ComponentName=§6Parça adı§f: %s
-oc:gui.Analyzer.Components=§6Bağlı parça sayısı§f: %s
-oc:gui.Analyzer.CopyToClipboard=Panoya kopyalamak için tıklayın.
-oc:gui.Analyzer.LastError=§6Son hata§f: %s
-oc:gui.Analyzer.RobotName=§6Adı§f: %s
-oc:gui.Analyzer.RobotOwner=§6Sahibi§f: %s
-oc:gui.Analyzer.RobotXp=§6Deneyimi§f: %s (Seviye %s)
-oc:gui.Analyzer.StoredEnergy=§6Depoladığı enerji§f: %s
-oc:gui.Analyzer.TotalEnergy=§6Maksimum enerji miktarı§f: %s
-oc:gui.Analyzer.Users=§6Kullanıcılar§f: %s
-oc:gui.Analyzer.WirelessStrength=§6Sinyal gücü§f: %s
-oc:gui.Assembler.Collect=Çıktıyı al
-oc:gui.Assembler.Complexity=Karmaşıklık: %s/%s
-oc:gui.Assembler.InsertCase=Kasa koyun
-oc:gui.Assembler.InsertCPU=İşlemci koyun
-oc:gui.Assembler.InsertRAM=Bellek koyun
-oc:gui.Assembler.Progress=İlerleme: %s%% (%s)
-oc:gui.Assembler.Run=Birleştir
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=Ekran Kartı
-oc:gui.Assembler.Warning.Inventory=Envanter Eklentisi
-oc:gui.Assembler.Warning.Keyboard=Klavye
-oc:gui.Assembler.Warning.OS=Başlangıç Bölümü
-oc:gui.Assembler.Warning.Screen=Ekran
-oc:gui.Assembler.Warnings=§eUyarı§7: Önerilen parçalar eksik.
-oc:gui.Chat.NewVersion=Yeni bir sürüm çıktı: %s
-oc:gui.Chat.TextureName=§7Doku adı §a%s§f.
-oc:gui.Chat.WarningClassTransformer=Sınıf dönüştürücü çalışırken §chatalar§f oluştu. Lütfen bunu mod yazarlarına (bütün!) FML §alatest.log§f/§afml-server-latest.log§f kayıt dosyasıyla birlikte gönderiniz. Şimdiden teşekkür ederiz.
-#There were §cerrors§f running the class transformer. Please report this, together with your (full!) FML §alatest.log§f/§afml-server-latest.log§f logfile, thank you!
-oc:gui.Chat.WarningFingerprint=§cUYARI§f - Parmakizi uyuşmazlığı! '§a%s§f' beklerken '§e%s§f' bulduk. Eğer karılmamış sürümünü kullanan bir mode yazarı değilseniz OpenComputers modunu yeniden indirmeniz §lşiddetle§f tavsiye edilir; çünkü elinizdeki JAR dosyası ile oynanmış olabilir.
-# §cWARNING§f - fingerprint mismatch! Expected '§a%s§f' but got '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.
-oc:gui.Chat.WarningLink=Bağlantı açılamadı: %s
-oc:gui.Chat.WarningLuaFallback=Orijinal Lua kütüphaneleri bulunamadı ve bilgisayarlar durumlarını koruyamayacak. Bölümler yeniden yüklenince bilgisayarlar yeniden başlayacak. (Yedek kütüphaneler kullanılıyor)
-# Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads.
-oc:gui.Chat.WarningProjectRed=OpenComputers'ı desteklemeyen bir Project: Red sürümünü kullanıyorsunuz. Project: Red'i güncellemeyi deneyin.
-# You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.
-oc:gui.Chat.WarningRecipes=Bir veya birden fazla tarifi yüklerken hata oluştu. Bazı nesneler üretilemeyebilir. Daha fazla bilgi için kayıt defteri dosyanızı bakın.
-# There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.
-oc:gui.Chat.WarningSimpleComponent= §aSimpleComponent§f arayüzünü kullanan bir mod eklentisi (acep sizin mi?) §eyanlış bir şeyler§f yaptı. Parça mantığı enjekte edilemedi. Daha fazla bilgi için kayıt defteri dosyanıza bakın.
-# An addon (yours?) using the §aSimpleComponent§f interface did §esomething wrong§f. Component logic could not be injected. Please check your log file for more information.
-oc:gui.Drive.Managed=Denetimli
-oc:gui.Drive.Unmanaged=Denetimsiz
-oc:gui.Drive.Warning=§lUyarı§r: kip değiştirmek disk üzerindeki bütün verinin kaybına sebep olur.
-oc:gui.Error.ComponentOverflow=Bilgisayara çok parça takılı.
-oc:gui.Error.InternalError=İçsel bir hata, lütfen kayıt defterine bakın. Bu büyük ihtimalle bir yazılım sorunu.
-oc:gui.Error.NoCPU=Bilgisayarın işlemcisi yok.
-oc:gui.Error.NoEnergy=Güç yeterli değil.
-oc:gui.Error.NoRAM=Bilgisayarda bellek yok.
-oc:gui.Error.OutOfMemory=Bellek taştı.
-oc:gui.Manual.Blocks=OpenComputers Küpler
-oc:gui.Manual.Home=Ev
-oc:gui.Manual.Items=OpenComputers Nesneler
-oc:gui.Manual.Warning.BlockMissing=Küp yok.
-oc:gui.Manual.Warning.ImageMissing=Resim bulunamadı.
-oc:gui.Manual.Warning.ItemMissing=Nesne yok.
-oc:gui.Manual.Warning.OreDictMissing=Cevher Muadilleri Sözlüğü yok.
-oc:gui.Raid.Warning=§4Disk eklemek onu siler.[nl] Disk çıkarmak RAID'i siler.
-oc:gui.Robot.Power=Güç
-oc:gui.Robot.TurnOff=Kapat
-oc:gui.Robot.TurnOn=Aç[nl]§7Hata çözmek için analiz aletini kullanın.§r
-oc:gui.Rack.Back=Arka
-oc:gui.Rack.Bottom=Alt
-oc:gui.Rack.Left=Sol
-oc:gui.Rack.None=Hiç
-oc:gui.Rack.Right=Sağ
-oc:gui.Rack.Enabled=Aktif
-oc:gui.Rack.Disabled=İnaktif
-oc:gui.Rack.Top=Üst
-oc:gui.Switch.PacketsPerCycle=Paket / devir
-oc:gui.Switch.QueueSize=Sıra Uzunluğu
-oc:gui.Switch.TransferRate=Devir hızı
-oc:gui.Terminal.InvalidKey=Geçersiz anahtar. Büyük ihtimalle başka bir uçbirim sunuzuya bağlandı.
-oc:gui.Terminal.OutOfRange=Sinyal yok.
-
-# Containers
-oc:container.adapter=Dönüştürücü
-oc:container.case=Bilgisayar
-oc:container.charger=Şarj Aleti
-oc:container.disassembler=Ayrıştırıcı
-oc:container.diskdrive=Disket Sürücüsü
-oc:container.printer=Yazıcı
-oc:container.raid=RAID
-oc:container.relay=Ağ Tamponu
-oc:container.server=Sunucu
-oc:container.rack=Sunucu Rafı
-oc:container.tabletwrapper=Tablet
-
-# Keybinds
-key.clipboardPaste=Panodan Yapıştır
-
-# Item / Block Tooltips
-oc:tooltip.abstractbuscard=LIP paketleri alıp ileterek §fStargateTech 2§7'in soyut veriyolu ile iletişim kurmanızı sağlar.
-oc:tooltip.acid=Zehirli, alkol kokan sıvımtırak bir şey. Belki askerde bazı manyak herifler kafayı bulmak için içer. Başka kullanım alanları da olabilir.
-oc:tooltip.adapter=Parça olmayan blokları (örneğin "vanilla" bloklar veya diğer modların bloklarını) kumanda etmek için kullanılır.
-oc:tooltip.alu=Siz yorulmayın diye sizin için işlem yapar. Belki böylesi daha iyidir.
-oc:tooltip.analyzer=Blokların §fadresi§7 ve §fparça ismi§7 gibi özelliklerini gösterir.[nl] Ayrıca bilgisayarın beklenmedik bir şekilde kapanmasına sebep olan hatayı da gösterir.
-# Used to display information about blocks, such as their §faddress§7 and §fcomponent name§7.[nl] Also displays the error that caused a computer to crash if it did not shut down normally.
-oc:tooltip.apu= Ekran kartı olan bir işlemci, bir kart yuvasına daha ihtiyacınız olursa diye.[nl] Desteklenen parçalar: §f%s§7[nl] Maksimum çözünürlük: §f%sx%s§7[nl] Maksimum renk derinliği: §f%s§7[nl] İşlem/tick: §f%s§7
-# This is a CPU with an integrated GPU (or IGP), when you just need that extra card slot.[nl] Supported components: §f%s§7[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7[nl] Operations/tick: §f%s§7
-oc:tooltip.assembler=Bilgisayar parçalarından robot ve başka cihazları üretmenize yarar.
-oc:tooltip.cable=Blokları bağlamanın ucuz bir yolu.
-oc:tooltip.capacitor=Daha sonra kullanılmak üzere enerji depolar. Çok hızlı şarj ve desarj olabilir.
-oc:tooltip.carpetedcapacitor=Daha sonra kullanılmak üzere enerji depolar. Çok hızlı şarj ve desarj olabilir. Bir Oselo veya Koyun üstünde yürürse şarj olur.
-oc:tooltip.cardbase=Adı üstünde, tüm bilgisayar kartlarının en basit yapıtaşı.
-oc:tooltip.case=Bilgisayar kasası bilgisayarın yapıtaşıdır ve bilgisayarın §fkartlarını§7, §fbelleğini§7 ve §fsürücülerimi§7 bünyesimde barındırır.[nl] Yuvalar: §f%s§7
-# The Computer Case is the basic building block for computers and houses the computer's §fextension cards§7, §fRAM§7 and §fhard disks§7.[nl] Slots: §f%s§7
-oc:tooltip.chamelium=3B çıktılar için hammaddedir. Yutmayınız, körlük ve geçici bilinç kaybına sebep olabilir.
-oc:tooltip.chameliumblock=Hoş ve temiz. 3B çıktılarda renkli şekiller yaratmak veya üssünüzü temiz ve renkli bir blokla dekore etmek için kullanılabilir.
-oc:tooltip.charger=Sığaçlardan takındaki robotlara ve dronlara enerji aktarır. Aktarım hızı gelen §fkızıltaş sinyaline§7 bağlıdır; tam güç tam hızla şarj olması, hiç sinyal olmaması ise şarj olmaması demektir. Tabletleri de şarj etmek, hatta sürücülerine erişmek için kullanılabilir.
-oc:tooltip.circuitboard=İşte şimdi yol alıyoruz. İşleme tabi tutularak devre kartı elde edilebilir.
-oc:tooltip.controlunit=Bu birim... yönetiyor işte. İşlemciye ihtiyacın var o yüzden önemli, değil mi?
-oc:tooltip.componentbus=Bu eklenti sunucuların aynı anda daha çok parça ile bağlantı kurmasını sağlar, işlemciler gibi.[nl] Desteklenen parçalar §f%s§7
-oc:tooltip.cpu=Her bilgisayara lazım. Saati biraz istikrarsız ama cep saatinden o kadar oluyor. Çok sarsma.[nl]Desteklenen parçalar: §f%s§7
-oc:tooltip.cpu.Architecture=Mimari: §f%s§7
-oc:tooltip.cuttingwire=Kil blokları devre kartı şekline sokmak için kullanılır. Tek kullanımda kopar. Ne iğrenç bir alet bu.
-oc:tooltip.datacard0="hashing", "deflate"/"inflate" gibi birkaç gelişmiş algoritma sunar.
-oc:tooltip.datacard1="hashing", "deflate"/"inflate", AES şifreleme gibi birkaç gelişmiş algoritma sunar.
-oc:tooltip.datacard2="hashing", "deflate"/"inflate", AES şifreleme, eliptik eğri kriptografisi gibi birkaç gelişmiş algoritma sunar.
-oc:tooltip.debugcard=Test etmeyi kolaylaştıran, dünyayı manüpile eden Yaratıcı mod aracı. Yetişkin denetimi altında kullanın.
-oc:tooltip.debugger=OpenComputers'ın iç ağının hata ayıklama bilgisini toplamak için kullanılır. Sadece bir geliştirici isterse kullanınız.
-oc:tooltip.diamondchip=Parıltılı bir elmasın naçiz bir parçası. Asla eskisi gibi olamayacak.
-oc:tooltip.disassembler=Nesneleri ihtiva ettiği parçalarına ayrıştırır. §lUyarı§7: ayrışan parçaların ayrışma sürecinde %%%s bozulma olasılığı vardır.
-oc:tooltip.disk=Daimi veri depolama cihazları yapılabilen ilkel veri saklama dairesi.
-oc:tooltip.diskdrive.CC=ComputerCraft disketler §açalışır§7.
-oc:tooltip.diskdrive=Disket okuma ve yazmaya yarar. Daha sonra disket takmak için robotlara da takılabilir.
-oc:tooltip.diskdrivemountable=Normal bir sürücüyle aynı işlevi görür fakat bir sunucu rafına takılmalıdır.
-oc:tooltip.diskusage=Disk kullanımı: %s/%s Byte
-oc:tooltip.diskmodemanaged=Kip: Denetimli
-oc:tooltip.diskmodeunmanaged=Kip: Denetimsiz
-oc:tooltip.drone=Dronlar hafif, hızlı, az yük kapasiteli uçan cihazlardır.
-oc:tooltip.dronecase=Bu kasa birleştirici ile Drone yapmak için kullanılır. Sınırlı parça için alanı var ve end taşı ile güçlendirilmiş uçma kabiliyeti var.
-oc:tooltip.eeprom=Elektrikle silinebilir, programlanabilir salt okunur hafıza. Bilgisayarların çalışması için gerekli BIOS kodunu içerir.
-oc:tooltip.fakeendstone=Neredeyse aynısı, bu da havalanmaya meyilli.
-oc:tooltip.geolyzer=Yakındaki blokların sertliğini ölçmeye yarar. Bu bilgi cevher bulmak için bölgenin holgramını yapmaya yarayabilir.
-oc:tooltip.graphicscard=Ekranları güzel bilgilerle doldurur.[nl] Azami Çözünürlük: §f%sx%s§7[nl] Azami renk derinliği: §f%s§7[nl] İşlem/tick: §f%s§7
-oc:tooltip.hoverboots=Daha yükseğe sıçra, daha derine in, daha iyi yürü. Hepsi Uçan Bot (TM) sayesinde.
-oc:tooltip.inkcartridge=3B yazıcılara mürekkep koymak için kullanılır. Nedense makineye takılı kalmıyor.
-oc:tooltip.inkcartridgeempty=Yazıcının kartuşu yine birmiş. Mürekkebi doldurabilirsin. Ya da at gitsin. Nasıl olsa bir daha aynı yazmaz.
-oc:tooltip.internetcard=Bu kart ile gerçekten internete bağlanıp, TCP üzerinden HTTP istemlerinde bulunabilirsiniz.
-oc:tooltip.interweb=Tebrikler, bir ağ (?) kazandınız. Internete bununla bağlanabilirsiniz. Trollerin seviyesine inmmeyin.
-oc:tooltip.ironnugget=Demirden kopan bir parça, başka nasıl açıklayayım.
-oc:tooltip.keyboard=Yazı yazmak için ekranlara takılabilir.
-oc:tooltip.hologram0=Bilgisayarla kumanda edilen, voksel tabanlı yapıları göstermek için kullanılan hacimsel ekran.[nl] Çözünürlük: §f48x32x48§7 [nl] Azami Ölçek: §f3x§7 [nl] Renk derinliği: §fMonokrom§7
-oc:tooltip.hologram1=Bilgisayarla kumanda edilen, voksel tabanlı yapıları göstermek için kullanılan hacimsel ekran.[nl] Çözünürlük: §f48x32x48§7 [nl] Azami Ölçek: §f3x§7 [nl] Renk derinliği: §f3 Renkli§7
-oc:tooltip.linkedcard=Bunlar çiftler halinde üretilir ve sadece partneriyle iletişim kurarlar. İletişimleri mesafeyi ve boyutları engel tanımaz fakat çok güç ister.
-oc:tooltip.linkedcard_channel=§8Kanal: %s§7
-oc:tooltip.manual=OpenComputers hakkında ihtiyaç duyabileceğiniz her bilgi ve daha fazlası. Hem de sadece ... §ofiyatı öğrenmek için R'ye basın§7.
-oc:tooltip.memory=Bilgisayarların çalışması için gerekli. Ne kadar çok belleğiniz varsa o kadar karmaşık programlar çalıştırabilirsiniz.
-oc:tooltip.microchip=Siyah elektrikle çalışan zımbırtılar. Neden kızıltaşla çalıştıkları beni aşıyor.
-oc:tooltip.microcontroller=Mikroişlemciler bilgisayarların en asgari biçimi. Görev odaklıdırlar ve EEPROM'larında gelen tek bir programla çalışırlar.[nl] §cHarici parçalarla bağlantı kuramazlar.§7
-oc:tooltip.microcontrollercase=Mikroişlemcilerin temel bileşeni. Mikroişlemci yapmak için bir birleştirici kullanın ve başka parçalar ekleyin.
-oc:tooltip.motionsensor=Yakındaki canlıların hareketini algılar. Çalışması için canlılar görüş açısında olmalıdır.
-oc:tooltip.nanomachines=Kumanda birimi ve tüketilmek üzere bir sürü nanomakine, tabi sende o mide varse.
-oc:tooltip.networkcard=Uzaktaki, birbirine başka bloklarla bağlı (örneğin kablolarla) bilgisayarların birbirlerine mesajlar göndererek iletişim kurmasını sağlar.
-oc:tooltip.poweracceptor=Enerji dönüşüm hızı: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fBuildCraft MJ'si§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fFactorization Yükü§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fIndustrialCraft² EU'su§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fMekanism Joule'ü§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fThermal Expansion RF'i§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fResonant Engine Coulomb'u§7: §a%s:%s§7
-oc:tooltip.powerconverter=Başka modların enerjilerini OpenComputers'ın kendi enerji birimine dönüştürür. Dönüşüm oranları:
-oc:tooltip.powerdistributor=Farklı ağlara enerji dağıtır. Ayrı kalması gereken alt-ağlara dönüştürücüden gelen enerjiyi dağıtmak için bire bir.
-oc:tooltip.present=... çoban armağanı. Verdiğimiz rahatsızlıktan dolayı. Hediyeyi açarak §kganimetlere§7 sahip olabilirsiniz.[nl]§8Doğru zamanda OpenComputers parçaları üreterek hediye kazanabilirsiniz.§7
-oc:tooltip.print.BeaconBase=§8Fener tabanı olarak işlev görür.
-oc:tooltip.print.LightValue=§8Işınan ışık: %s.
-oc:tooltip.print.RedstoneLevel=§8Kızıltaş çıktısı: %s.
-oc:tooltip.printedcircuitboard=Bellek, bilgisayar kartları vb.nin yapı taşı.
-oc:tooltip.printer=Kullanıcı tanımlı nesnelerin şamelyum ve mürekkep kullanılarak basılmasını sağlar. Bir bilgisayar tarafından yönetilmelidir. Bazı sebeplerden dolayı, çocuklardan uzak tutun.
-oc:tooltip.raid=Birden fazla diskin tek bir dosya sistemi altında birleştirilip bağlı tüm bilgisayarlar tarafından kullanılmasını sağlar.
-oc:tooltip.rawcircuitboard=Herhangi bir fırında kurutulabilir.
-oc:tooltip.redstone=Bloğun çevresinde kızıltaş iletimi ve çevresinden kızıltaş alıgalma yapabilir. Bağlı herhangi bir bilgisayar kumanda edebilir. Harici bir kızıltaş kartı gibi davranır.
-oc:tooltip.redstonecard.ProjectRed=§fProject: Red§7 §adestekli§7.
-oc:tooltip.redstonecard.RedLogic=§fRedLogic§7 §adestekli§7.
-oc:tooltip.redstonecard.RedNet=§fRedNet§7 §adestekli§7.
-oc:tooltip.redstonecard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 §adestekli§7.
-oc:tooltip.redstonecard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 §adestekli§7.
-oc:tooltip.redstonecard=Bilgisayarın veya robotun çevresine kızltaş sinyali iletimesini ve çevresinden kızıltaş sinyalı algılamasını sağlar.
-oc:tooltip.relay=Farklı ağları birbirine bağlamaya yarar. Sadece ağ mesajları iletilir, parçalar görünmez. Bunu Ağ kartlarını kullanırken bilgisayarları birbirinden izole etmek için kullanabilirsiniz.
-oc:tooltip.robot=Bilgisayarların aksine robotlar oyuncular gibi dünyada hareket edebilir ve ona değişiklikler yapabilir.[nl] §cHarici parçalara bağlanamaz.§7
-# the underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§fSeviye§7: §a%s§7
-oc:tooltip.robot_storedenergy=§fDepolu enerji§7: §a%s§7
-oc:tooltip.screen=Yazı göster, kasadaki bir ekran kartı aracılığıyla. [nl] Azami çözünürlük: §f%sx%s§7[nl] Azami renk derinliği: §f%s§7
-oc:tooltip.server=Bu bir sunucu. Bundan çokça olabilir fakat bu (bir bilgisayar gibi) başka parçalarla geliştirilebilir. Sunucu rafına takılarak çalıştırılabilir.
-oc:tooltip.server.Components=Takılı Parçalar:
-oc:tooltip.rack=4 sunucunun veya rafa konulabilen parçaların takılmasını sağlar.
-oc:tooltip.tablet=Lua ile eğlence için bir tablet bilgisayar. Çömelirken aktifleştirirseniz kapanmaya sorlarsınız.
-oc:tooltip.tabletcase=Basit bir tablet kasası. Bir birleştirici ve başka parçalar ile bir tablet yapabilirsiniz..
-oc:tooltip.terminal=Menzili içinde bir sunucuyu uzaktan kumanda etmenize yarar. Taşınabilir ekran ve klavye gibi davranır. Shift+Sağ-Tık ile raftaki bir sunucuya bağlayabilirsiniz.
-oc:tooltip.terminalserver=Uzaktan Uçbirimin yöneticisi. Sanal bir ekranı ve klavyesi var.
-oc:tooltip.texturepicker= Bu alet, 3B yazıcıda şekil tanımlamak üzere bir bloğun yüzeyini ifade eden bir metin gösterir. Kesinlikle dokunun ismi değil. Sana yalan borcum mu var?
-oc:tooltip.tier=§8%s. Seviye
-oc:tooltip.netsplitter=Ayarlanabilir bir bağlantı noktası gibi davranır. Her yüzün bağlantısı bir İngiliz anahtarı ile değiştirilebilir. Her yüzün bağlantısı bir kızıltaş sinyali ile tersine dönüştürülebilr.
-oc:tooltip.toolong=Şuna basılı tutarak daha detaylı bilgi alabilirsiniz: [§f%s§7]
-oc:tooltip.transistor=Çoğu bilgisayar parçasının basit bir bileşeni. Biraz yamulmuş ama iş görür.
-oc:tooltip.transposer=Bitişiğindeki envanterler arasında katı ve sıvı değişimini sağlar.
-oc:tooltip.upgradeangel=Robotlara boşlukta (tutunacak yer yokken) blok koyma yetisi sağlar.
-oc:tooltip.upgradebattery=Cihazın depolayabileceği enerji miktarını arttırır. Böylece cihaz şarj olmadan daha uzun süre çalışabilir. [nl] Kapasite: §f%s§7
-oc:tooltip.upgradechunkloader=Robot tek başına ormana giderse ve onu kimse görmezse hareket eder mi? Bu eklenti çalıştığından emin olur. Bir bölümü(16x16x256) sürekli yüklü tutar fakat sürekli enerji harcar.
-oc:tooltip.upgradecontainercard=Bu yuva birleştirilmiş cihazda kartların rahatlıkla takılıp çıkarılmasını sağlar. [nl] Azami Seviye: §f%s§7
-oc:tooltip.upgradecontainerupgrade=Bu yuva birleştirilmiş cihazda eklentilerin rahatlıkla takılıp çıkarılmasını sağlar. [nl] Azami Seviye: §f%s§7
-oc:tooltip.upgradecrafting=Robotun envanterinin sol üst köşesini çalışma masası gibi kullanmasını sağlar. Nesnelerin tarife göre yerleşmesi şarttır.
-oc:tooltip.upgradedatabase=Bu eklenti deste bilgisinin başka parçalar tarafından kullanılmak üzere saklanmasını sağlar.[nl] Desteklenen satır sayısı: §f%s§7
-oc:tooltip.upgradeexperience=Bu eklenti çeşitli eylemler aracalığıyla robotların deneyim kazanmasını sağlar. Robotlar ne kadar deneyimliyse o kadar enerji depolayabilir, o kadar hızlı blok toplayabilir ve aletleri o kadar etkili kullanabilir.
-oc:tooltip.upgradegenerator=Yolda yakıttan enerji üretimini sağlar. Yakıtları enerji değerlerine göre enerji üretmek için kullanır.[nl] §fVerimlilik§7: §a%s%%§7
-oc:tooltip.upgradehover=Bu eklenti robotun duvar tırmanmak zorunda kalmadan daha yükseğe çıkmasını sağlar.[nl] Azami irtifa: §f%s§7
-oc:tooltip.upgradeinventory=Bu eklenti bir robota veya drona envanter sağlar. Bu olmadan nesne tutamazlar.
-oc:tooltip.upgradeinventorycontroller=Bu eklenti robotların ve dronların harici envanterlerle iletişim kurmasını ve onlardaki aletlerle kendi aletini değişmesini sağlar.
-oc:tooltip.upgrademf=Dönüştürücülerin bitişiğinde olmadığı nesnelerle iletişim kurmasını sağlar.
-oc:tooltip.upgrademf.Linked=§fBağlantı kuruldu§7
-oc:tooltip.upgrademf.Unlinked=§fBağlantı yok§7
-oc:tooltip.upgradeleash=Drone gibi bazı cihazların belediye görevlilerine sataş...-özür dilerim. Bu cihaz aslında canlı(lar)ı bağlamak için kullanılıyormuş. İlğinç.
-oc:tooltip.upgradenavigation=Cihazın yönünü ve yerini tespit etmek için kullanılır. Yer bilgisi eklentiyi üretirken kullanılan haritanın merkez noktasına göredir.
-oc:tooltip.upgradepiston=Bu eklenti çok itici. Piston gibi blokları hareket ettirmeye yarar. Canlıları ve partikülleri hareket ettir§lmez§7.
-oc:tooltip.upgradesign=Tabelalardan yazı okumayı ve onlara yazı yazmayı sağlar.
-oc:tooltip.upgradesolargenerator=Güneşten enerji üretimini sağlar. Gökyüzü görüş açısında olmalıdır. Bir Stirling motorunun %%%s katı hızı kadar hızlı enerji üretebilir.
-oc:tooltip.upgradetank=Robotlara ve dronlara sıvı depolama alanı sağlar. Bu olmadan sıvı depolayamazlar.
-oc:tooltip.upgradetankcontroller=Bu eklenti robotlara ve dronlara harici sıvı depoları ile iletişim yeteneği sağlar. Harici depodan dahiliye, dahiliden hariciye sıvı iletimi sağlar.
-oc:tooltip.upgradetractorbeam=Nesne mıknatısı adı verilen çok gelişmiş bir teknolojiti edinin. Cihazın 3 block menzilinden nesneleri almasını sağlar.
-oc:tooltip.waypoint=Yönbulma eklentisi olan cihazlar için referans noktası oluşturur.
-oc:tooltip.wirelessnetworkcard=Normal ağ mesajlarının yanı sıra kablosuz ağ mesajlarının iletimini sağlar. §fSinyal gücünü§7 ayarlayarak mesajların ne kadar uzağa iletildiğini kontrol edebilirsiniz. Yüksek sinyal gücü daha çok enerji tüketir.
-oc:tooltip.worldsensorcard=Dünya hakkında yerçekimi ve nefes alınabilir bir atmosferi olup olmadığı gibi bilgileri toplar. Bilgiler kesin değildir. Üretici firma karttan edilen bilgilere göre verilen kararlar sonucu oluşan maddi ve manevi hiçbir hasardan sorumlu değildir. Avukatlarımız var. Paramız da. Denemeyi aklınızdan bile geçirmeyin.
-oc:tooltip.Wrench=İngiliz anahtarı tornavida karışımı bir şey. Öğrenmesi basit, ustalaşması zor.
-
-#Achievements
-achievement.oc.adapter=Tak-Çalıştır
-achievement.oc.adapter.desc=Diğer modların ve elbette vanilla Minecraft blokları ile iletişim kur.
-achievement.oc.assembler=Harika
-achievement.oc.assembler.desc=Dünyayı ele geçirme vakti.
-achievement.oc.cable=Temiz Kablo
-achievement.oc.cable.desc=Patentli dolanma önleyici teknolojisi ile.
-achievement.oc.capacitor=Piller Ürüne Dahildir.
-achievement.oc.capacitor.desc=Durduramazsın.
-achievement.oc.card=Kredi Kartı Geçerlidir.
-achievement.oc.card.desc=Sizin için. Kesinlikle bir art niyetimiz yok.
-achievement.oc.case=Yangın Durumunda ...
-achievement.oc.case.desc=Çünkü küp kasalar en iyisi.
-achievement.oc.charger=Haydi şu işi bitirelim.
-achievement.oc.charger.desc=Şarj etsene seni... Kızıltaş sinyalini unutmuşum.
-achievement.oc.chip=En Küçüğünden Lütfen
-achievement.oc.chip.desc=Çünkü tüpler eskide kaldı.
-achievement.oc.cpu=Modifiye
-achievement.oc.cpu.desc=Haydi bu makineyi biraz zorlayalım.
-achievement.oc.disassembler=Ali Yazar, Veli Bozar
-achievement.oc.disassembler.desc=Nasıl olsa Sarı Çizmeli Mehmet Ağa bir gün öder hesabı.
-achievement.oc.diskDrive=Dönmedolap
-achievement.oc.diskDrive.desc=Az alan, güzel ses.
-achievement.oc.drone=Su gibi git...
-achievement.oc.drone.desc=... su gibi gel. Pahalısın lazımsın bize.
-achievement.oc.eeprom=Ya ben, ya hiç!
-achievement.oc.eeprom.desc=Bilgisayar için, önemli bir parça.
-achievement.oc.floppy=Güneş Tutulması
-achievement.oc.floppy.desc=Hepsini bozduk 1999'da.
-achievement.oc.geolyzer=Zonguldak
-achievement.oc.geolyzer.desc=Toprak ne ki, yeri bir metre kaz kömür çıkıyor.
-achievement.oc.graphicsCard=Yeni Nesil
-achievement.oc.graphicsCard.desc=Döviz kuru düşseydi fakir kalmazdım.
-achievement.oc.hdd=Hıyar Domates Dirhem
-achievement.oc.hdd.desc=Yanlış oldu, bekle dilimin ucunda.
-achievement.oc.hologram=Gelecek Boyut
-achievement.oc.hologram.desc=2B'tan sıkıldın mı?
-achievement.oc.keyboard=TozMıknatısı3000
-achievement.oc.keyboard.desc=Odanıza alın, odanız tertemiz olsun*. *TozMıknatısı300 dışında.
-achievement.oc.microcontroller=Kardeş
-achievement.oc.microcontroller.desc=Bilgisayarın küçük kardeşi.
-achievement.oc.motionSensor=Tuvalet Kabusu
-achievement.oc.motionSensor.desc=İşerken ışık söner mi acaba?
-achievement.oc.networkCard=Feysbuk
-achievement.oc.networkCard.desc=Hep birlikte kimsenin takmadığı şeyleri paylaşıp sosyal olduğumuzu sanıyoruz.
-achievement.oc.openOS=iŞlEtİm SiStEmİ NeY?
-achievement.oc.openOS.desc=Bilgisayarcıya git format atsın ablacım.
-achievement.oc.powerDistributor=Hayat Paylaşınca Güzel
-achievement.oc.powerDistributor.desc=Reklam yapmıyoruz. Güzel sözün telif hakkı mı olur?
-achievement.oc.rack="Bizim salondaki raf olur mu?"
-achievement.oc.rack.desc=Tartmaz bir kere.
-achievement.oc.raid=Yerim Kalmadı.
-achievement.oc.raid.desc=Ne kadar çok "aile fotoğrafı"n varsa artık.
-achievement.oc.ram=Seçici Hatıra
-achievement.oc.ram.desc=Nedense sevdiklerimi daha çok hatırlıyorum.
-achievement.oc.redstoneCard=Regülatörü Tak.
-achievement.oc.redstoneCard.desc=Daha tüpler ısınacak.
-achievement.oc.redstoneIO=TRT
-achievement.oc.redstoneIO.desc=İlk yayın birazdan başlayacak.
-achievement.oc.robot="Gerginlik yaratma robot o robot."
-achievement.oc.robot.desc="Robot musun sen?" "Evet."
-achievement.oc.screen=Aç Kapa Çalışır.
-achievement.oc.screen.desc=Gerçekten, kızıltaş sinyalleri etkiliyor.
-achievement.oc.server=e-Devlet Kapısı
-achievement.oc.server.desc=Ne varsa orada, bu bilgileri kim saklayacak.
-achievement.oc.switch=Birini düzelt, diğerini boz.
-achievement.oc.switch.desc=Telekomcular niye işlerini yapamıyor.
-achievement.oc.tablet=Bu bir ilaç değildir.
-achievement.oc.tablet.desc=Çocuklardan uzak tutun. İstenmeyen harcamalara neden olabilir.
-achievement.oc.transistor=Düğmemtırak
-achievement.oc.transistor.desc=Bizim radyodada vardı bunlardan.
-achievement.oc.wirelessNetworkCard="Işınla bizi Scotty"
-achievement.oc.wirelessNetworkCard.desc="Barış içinde size bir ileti getirdik."
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code.
-death.attack.oc.nanomachinesOverload.1=%s elini çok sıkı tuttu.
-death.attack.oc.nanomachinesOverload.2=%s kafayı yedi.
-death.attack.oc.nanomachinesOverload.3=%s öldü. Nanomakine varmış diyorlar.
-death.attack.oc.nanomachinesHungry.1=%s sizlere ömür. Nanomakineler diri diri yemiş.
-death.attack.oc.nanomachinesHungry.2=%s nanomakinelerine bakmadı.
-death.attack.oc.nanomachinesHungry.3=%s sindirildi.
-
-# NEI Integration
-nei.options.inventory.oredict=Cevher Muadilleri Sözlüğü Adlarını Göster
-nei.options.inventory.oredict.true=Evet
-nei.options.inventory.oredict.false=Hayır
-nei.usage.oc.Manual=Kılavuzu Aç
-
-# Waila Integration
-option.oc.address=Adres
-option.oc.componentName=Parça Adı
-option.oc.energy=Enerji
diff --git a/src/main/resources/assets/opencomputers/lang/tr_tr.json b/src/main/resources/assets/opencomputers/lang/tr_tr.json
new file mode 100644
index 0000000000..095f2270a7
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/tr_tr.json
@@ -0,0 +1,451 @@
+{
+ "tile.oc.adapter": "Dönüştürücü",
+ "tile.oc.assembler": "Elektronik Birleştirici",
+ "tile.oc.cable": "Kablo",
+ "tile.oc.capacitor": "Sığaç",
+ "tile.oc.carpetedcapacitor": "Halılı Sığaç",
+ "tile.oc.case1": "Bilgisayar Kasası (1. Seviye)",
+ "tile.oc.case2": "Bilgisayar Kasası (2. Seviye)",
+ "tile.oc.case3": "Bilgisayar Kasası (3. Seviye)",
+ "tile.oc.casecreative": "Bilgisayar Kasası (Yaratıcı)",
+ "tile.oc.chameliumblock": "Şamelyum Küpü",
+ "tile.oc.charger": "Şarj Cihazı",
+ "tile.oc.disassembler": "Ayrıştırıcı",
+ "tile.oc.diskdrive": "Disket Sürücüsü",
+ "tile.oc.endstone": "End Taşı",
+ "tile.oc.geolyzer": "Jeolizer",
+ "tile.oc.hologram1": "Hologram Projektörü (1. Seviye)",
+ "tile.oc.hologram2": "Hologram Projektörü (2. Seviye)",
+ "tile.oc.keyboard": "Klavye",
+ "tile.oc.microcontroller": "Mikroişlemci",
+ "tile.oc.motionsensor": "Hareket Algılayıcı",
+ "tile.oc.netsplitter": "Ağ Bölücü",
+ "tile.oc.powerconverter": "Güç Dönüştürücü",
+ "tile.oc.powerdistributor": "Güç Dağıtıcı",
+ "tile.oc.print": "3B Çıktı",
+ "tile.oc.printer": "3B Yazıcı",
+ "tile.oc.raid": "RAID",
+ "tile.oc.redstone": "Kızıltaş G/Ç Küpü",
+ "tile.oc.relay": "Ağ Tamponu",
+ "tile.oc.robot": "Robot",
+ "tile.oc.robotafterimage": "Robot",
+ "tile.oc.screen1": "Ekran (1. Seviye)",
+ "tile.oc.screen2": "Ekran (2. Seviye)",
+ "tile.oc.screen3": "Ekran (3. Seviye)",
+ "tile.oc.rack": "Sunucu Rafı",
+ "tile.oc.transposer": "İletici",
+ "tile.oc.waypoint": "Yer İşareti",
+ "item.oc.abstractbuscard": "Soyut Veriyolu Kartı",
+ "item.oc.acid": "İspirto?",
+ "item.oc.alu": "Aritmetik Mantık Birimi (ALU)",
+ "item.oc.analyzer": "Analiz Aleti",
+ "item.oc.apu0": "Eklentili İşlemci (APU) (1. Seviye)",
+ "item.oc.apu1": "Eklentili İşlemci (APU) (2. Seviye)",
+ "item.oc.apu2": "Eklentili İşlemci (APU) (Yaratıcı)",
+ "item.oc.arrowkeys": "Ok Tuşları",
+ "item.oc.buttongroup": "Harf Takımı",
+ "item.oc.cardbase": "Ham Bilgisayar Kartı",
+ "item.oc.chamelium": "Şamelyum",
+ "item.oc.circuitboard": "Devre Kartı",
+ "item.oc.componentbus0": "Cihaz Veriyolu (1. Seviye)",
+ "item.oc.componentbus1": "Cihaz Veriyolu (2. Seviye)",
+ "item.oc.componentbus2": "Cihaz Veriyolu (3. Seviye)",
+ "item.oc.componentbus3": "Cihaz Veriyolu (Yaratıcı)",
+ "item.oc.controlunit": "Yönetim Birimi (CU)",
+ "item.oc.cpu0": "İşlemci (CPU) (1. Seviye)",
+ "item.oc.cpu1": "İşlemci (CPU) (2. Seviye)",
+ "item.oc.cpu2": "İşlemci (CPU) (3. Seviye)",
+ "item.oc.cuttingwire": "Kesme Teli",
+ "item.oc.datacard0": "Veri Kartı (1. Seviye)",
+ "item.oc.datacard1": "Veri Kartı (2. Seviye)",
+ "item.oc.datacard2": "Veri Kartı (3. Seviye)",
+ "item.oc.debugcard": "Hata Ayıklama Kartı",
+ "item.oc.debugger": "Ağ Hata Ayıklama Aleti",
+ "item.oc.diamondchip": "Elmas Kesiti",
+ "item.oc.disk": "Disk Bileşeni",
+ "item.oc.diskdrivemountable": "Disk",
+ "item.oc.drone": "Drone",
+ "item.oc.dronecase0": "Drone Kasası (1. Seviye)",
+ "item.oc.dronecase1": "Drone Kasası (2. Seviye)",
+ "item.oc.dronecase3": "Drone Kasası (3. Seviye)",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.floppydisk": "Disket",
+ "item.oc.graphicscard0": "Ekran Kartı (1. Seviye)",
+ "item.oc.graphicscard1": "Ekran Kartı (2. Seviye)",
+ "item.oc.graphicscard2": "Ekran Kartı (3. Seviye)",
+ "item.oc.harddiskdrive0": "Hard Disk (1. Seviye)",
+ "item.oc.harddiskdrive1": "Hard Disk (2. Seviye)",
+ "item.oc.harddiskdrive2": "Hard Disk (3. Seviye)",
+ "item.oc.hoverboots": "Uçma Botu",
+ "item.oc.inkcartridge": "Mürekkep Kartuşu",
+ "item.oc.inkcartridgeempty": "Mürekkep Kartuşu (Boş)",
+ "item.oc.internetcard": "İnternet Kartı",
+ "item.oc.interweb": "Ağ?",
+ "item.oc.ironnugget": "Demir Parçası",
+ "item.oc.linkedcard": "Bağlantılı Kart",
+ "item.oc.manual": "OpenComputers Kullanma Kılavuzu",
+ "item.oc.memory0": "Bellek (1. Seviye)",
+ "item.oc.memory1": "Bellek (1,5. Seviye)",
+ "item.oc.memory2": "Bellek (2. Seviye)",
+ "item.oc.memory3": "Bellek (2,5. Seviye)",
+ "item.oc.memory4": "Bellek (3. Seviye)",
+ "item.oc.memory5": "Bellek (3,5. Seviye)",
+ "item.oc.microchip0": "Entegre Devre (1. Seviye)",
+ "item.oc.microchip1": "Entegre Devre (2. Seviye)",
+ "item.oc.microchip2": "Entegre Devre (3. Seviye)",
+ "item.oc.microcontrollercase0": "Mikroişlemci Kasası (1. Seviye)",
+ "item.oc.microcontrollercase1": "Mikroişlemci Kasası (2. Seviye)",
+ "item.oc.microcontrollercase3": "Mikroişlemci Kasası (Yaratıcı)",
+ "item.oc.nanomachines": "Nanomakine",
+ "item.oc.networkcard": "Ağ Kartı",
+ "item.oc.numpad": "Tuş Takımı",
+ "item.oc.present": "Çam Sakızı...",
+ "item.oc.printedcircuitboard": "Devre Kartı (PCB)",
+ "item.oc.rawcircuitboard": "Ham Devre Kartı",
+ "item.oc.redstonecard0": "Kızıltaş Kartı (1. Seviye)",
+ "item.oc.redstonecard1": "Kızıltaş Kartı (2. Seviye)",
+ "item.oc.server0": "Sunucu (1. Seviye)",
+ "item.oc.server1": "Sunucu (2. Seviye)",
+ "item.oc.server2": "Sunucu (3. Seviye)",
+ "item.oc.server3": "Sunucu (Yaratıcı)",
+ "item.oc.tablet": "Tablet",
+ "item.oc.tabletcase0": "Tablet Kasası (1. Seviye)",
+ "item.oc.tabletcase1": "Tablet Kasası 500640(2. Seviye)",
+ "item.oc.tabletcase3": "Tablet Kasası (Yaratıcı)",
+ "item.oc.terminal": "Uzaktan Uçbirim",
+ "item.oc.terminalserver": "Uçbirim Sunucusu",
+ "item.oc.texturepicker": "Doku Seçici",
+ "item.oc.transistor": "Transistör",
+ "item.oc.upgradeangel": "Melek Eklentisi",
+ "item.oc.upgradebattery0": "Batarya Eklentisi (1. Seviye)",
+ "item.oc.upgradebattery1": "Batarya Eklentisi (2. Seviye)",
+ "item.oc.upgradebattery2": "Batarya Eklentisi (3. Seviye)",
+ "item.oc.upgradechunkloader": "Kesiti-yüklü-tut Eklentisi",
+ "item.oc.upgradecontainercard0": "Kart Yuvası (1. Seviye)",
+ "item.oc.upgradecontainercard1": "Kart Yuvası (2. Seviye)",
+ "item.oc.upgradecontainercard2": "Kart Yuvası (3. Seviye)",
+ "item.oc.upgradecontainerupgrade0": "Eklenti Yuvası (1. Seviye)",
+ "item.oc.upgradecontainerupgrade1": "Eklenti Yuvası (2. Seviye)",
+ "item.oc.upgradecontainerupgrade2": "Eklenti Yuvası (3. Seviye)",
+ "item.oc.upgradecrafting": "Üretim Eklentisi",
+ "item.oc.upgradedatabase0": "Veritabanı Eklentisi (1. Seviye)",
+ "item.oc.upgradedatabase1": "Veritabanı Eklentisi (2. Seviye)",
+ "item.oc.upgradedatabase2": "Veritabanı Eklentisi (3. Seviye)",
+ "item.oc.upgradeexperience": "Deneyim Eklentisi",
+ "item.oc.upgradegenerator": "Jeneratör Eklentisi",
+ "item.oc.upgradehover0": "Uçma Eklentisi (1. Seviye)",
+ "item.oc.upgradehover1": "Uçma Eklentisi (2. Seviye)",
+ "item.oc.upgradeinventory": "Envanter Eklentisi",
+ "item.oc.upgradeinventorycontroller": "Envanter Yönetimi Eklentisi",
+ "item.oc.upgradeleash": "Kayış Eklentisi",
+ "item.oc.upgrademf": "MFU",
+ "item.oc.upgradenavigation": "Yönbulma Eklentisi",
+ "item.oc.upgradepiston": "Piston Eklentisi",
+ "item.oc.upgradesign": "Tabela G/Ç Eklentisi",
+ "item.oc.upgradesolargenerator": "Güneş Enerjisi Eklentisi",
+ "item.oc.upgradetank": "Tank Eklentisi",
+ "item.oc.upgradetankcontroller": "Tank Yönetimi Eklentisi",
+ "item.oc.upgradetractorbeam": "Çekme Işını Eklentisi",
+ "item.oc.upgradetrading": "Ticaret Eklentisi",
+ "item.oc.wirelessnetworkcard0": "Kablosuz Ağ Kartı (1. Seviye)",
+ "item.oc.wirelessnetworkcard1": "Kablosuz Ağ Kartı (2. Seviye)",
+ "item.oc.worldsensorcard": "Dünya Algılayıcı Kartı",
+ "item.oc.wrench": "Tornanahtar",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "Drone",
+ "oc:gui.Analyzer.Address": "§6Adres§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "Adres panoya kopyalandı",
+ "oc:gui.Analyzer.ChargerSpeed": "§6Şarj hızı§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6Parça adı§f: %s",
+ "oc:gui.Analyzer.Components": "§6Bağlı parça sayısı§f: %s",
+ "oc:gui.Analyzer.CopyToClipboard": "Panoya kopyalamak için tıklayın.",
+ "oc:gui.Analyzer.LastError": "§6Son hata§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6Adı§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6Sahibi§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6Deneyimi§f: %s (Seviye %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6Depoladığı enerji§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6Maksimum enerji miktarı§f: %s",
+ "oc:gui.Analyzer.Users": "§6Kullanıcılar§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6Sinyal gücü§f: %s",
+ "oc:gui.Assembler.Collect": "Çıktıyı al",
+ "oc:gui.Assembler.Complexity": "Karmaşıklık: %s/%s",
+ "oc:gui.Assembler.InsertCase": "Kasa koyun",
+ "oc:gui.Assembler.InsertCPU": "İşlemci koyun",
+ "oc:gui.Assembler.InsertRAM": "Bellek koyun",
+ "oc:gui.Assembler.Progress": "İlerleme: %s%% (%s)",
+ "oc:gui.Assembler.Run": "Birleştir",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "Ekran Kartı",
+ "oc:gui.Assembler.Warning.Inventory": "Envanter Eklentisi",
+ "oc:gui.Assembler.Warning.Keyboard": "Klavye",
+ "oc:gui.Assembler.Warning.OS": "Başlangıç Bölümü",
+ "oc:gui.Assembler.Warning.Screen": "Ekran",
+ "oc:gui.Assembler.Warnings": "§eUyarı§7: Önerilen parçalar eksik.",
+ "oc:gui.Chat.NewVersion": "Yeni bir sürüm çıktı: %s",
+ "oc:gui.Chat.TextureName": "§7Doku adı §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "Sınıf dönüştürücü çalışırken §chatalar§f oluştu. Lütfen bunu mod yazarlarına (bütün!) FML §alatest.log§f/§afml-server-latest.log§f kayıt dosyasıyla birlikte gönderiniz. Şimdiden teşekkür ederiz.",
+ "oc:gui.Chat.WarningFingerprint": "§cUYARI§f - Parmakizi uyuşmazlığı! '§a%s§f' beklerken '§e%s§f' bulduk. Eğer karılmamış sürümünü kullanan bir mode yazarı değilseniz OpenComputers modunu yeniden indirmeniz §lşiddetle§f tavsiye edilir; çünkü elinizdeki JAR dosyası ile oynanmış olabilir.",
+ "oc:gui.Chat.WarningLink": "Bağlantı açılamadı: %s",
+ "oc:gui.Chat.WarningLuaFallback": "Orijinal Lua kütüphaneleri bulunamadı ve bilgisayarlar durumlarını koruyamayacak. Bölümler yeniden yüklenince bilgisayarlar yeniden başlayacak. (Yedek kütüphaneler kullanılıyor)",
+ "oc:gui.Chat.WarningProjectRed": "OpenComputers'ı desteklemeyen bir Project: Red sürümünü kullanıyorsunuz. Project: Red'i güncellemeyi deneyin.",
+ "oc:gui.Chat.WarningRecipes": "Bir veya birden fazla tarifi yüklerken hata oluştu. Bazı nesneler üretilemeyebilir. Daha fazla bilgi için kayıt defteri dosyanızı bakın.",
+ "oc:gui.Drive.Managed": "Denetimli",
+ "oc:gui.Drive.Unmanaged": "Denetimsiz",
+ "oc:gui.Drive.Warning": "§lUyarı§r: kip değiştirmek disk üzerindeki bütün verinin kaybına sebep olur.",
+ "oc:gui.Error.ComponentOverflow": "Bilgisayara çok parça takılı.",
+ "oc:gui.Error.InternalError": "İçsel bir hata, lütfen kayıt defterine bakın. Bu büyük ihtimalle bir yazılım sorunu.",
+ "oc:gui.Error.NoCPU": "Bilgisayarın işlemcisi yok.",
+ "oc:gui.Error.NoEnergy": "Güç yeterli değil.",
+ "oc:gui.Error.NoRAM": "Bilgisayarda bellek yok.",
+ "oc:gui.Error.OutOfMemory": "Bellek taştı.",
+ "oc:gui.Manual.Blocks": "OpenComputers Küpler",
+ "oc:gui.Manual.Home": "Ev",
+ "oc:gui.Manual.Items": "OpenComputers Nesneler",
+ "oc:gui.Manual.Warning.BlockMissing": "Küp yok.",
+ "oc:gui.Manual.Warning.ImageMissing": "Resim bulunamadı.",
+ "oc:gui.Manual.Warning.ItemMissing": "Nesne yok.",
+ "oc:gui.Manual.Warning.OreDictMissing": "Cevher Muadilleri Sözlüğü yok.",
+ "oc:gui.Raid.Warning": "§4Disk eklemek onu siler.\nDisk çıkarmak RAID'i siler.",
+ "oc:gui.Robot.Power": "Güç",
+ "oc:gui.Robot.TurnOff": "Kapat",
+ "oc:gui.Robot.TurnOn": "Aç\n§7Hata çözmek için analiz aletini kullanın.§r",
+ "oc:gui.Rack.Back": "Arka",
+ "oc:gui.Rack.Bottom": "Alt",
+ "oc:gui.Rack.Left": "Sol",
+ "oc:gui.Rack.None": "Hiç",
+ "oc:gui.Rack.Right": "Sağ",
+ "oc:gui.Rack.Enabled": "Aktif",
+ "oc:gui.Rack.Disabled": "İnaktif",
+ "oc:gui.Rack.Top": "Üst",
+ "oc:gui.Switch.PacketsPerCycle": "Paket / devir",
+ "oc:gui.Switch.QueueSize": "Sıra Uzunluğu",
+ "oc:gui.Switch.TransferRate": "Devir hızı",
+ "oc:gui.Terminal.InvalidKey": "Geçersiz anahtar. Büyük ihtimalle başka bir uçbirim sunuzuya bağlandı.",
+ "oc:gui.Terminal.OutOfRange": "Sinyal yok.",
+ "oc:container.adapter": "Dönüştürücü",
+ "oc:container.case": "Bilgisayar",
+ "oc:container.charger": "Şarj Aleti",
+ "oc:container.disassembler": "Ayrıştırıcı",
+ "oc:container.diskdrive": "Disket Sürücüsü",
+ "oc:container.printer": "Yazıcı",
+ "oc:container.raid": "RAID",
+ "oc:container.relay": "Ağ Tamponu",
+ "oc:container.server": "Sunucu",
+ "oc:container.rack": "Sunucu Rafı",
+ "oc:container.tabletwrapper": "Tablet",
+ "key.opencomputers.clipboardPaste": "Panodan Yapıştır",
+ "oc:tooltip.abstractbuscard": "LIP paketleri alıp ileterek §fStargateTech 2§7'in soyut veriyolu ile iletişim kurmanızı sağlar.",
+ "oc:tooltip.acid": "Zehirli, alkol kokan sıvımtırak bir şey. Belki askerde bazı manyak herifler kafayı bulmak için içer. Başka kullanım alanları da olabilir.",
+ "oc:tooltip.adapter": "Parça olmayan blokları (örneğin \"vanilla\" bloklar veya diğer modların bloklarını) kumanda etmek için kullanılır.",
+ "oc:tooltip.alu": "Siz yorulmayın diye sizin için işlem yapar. Belki böylesi daha iyidir.",
+ "oc:tooltip.analyzer": "Blokların §fadresi§7 ve §fparça ismi§7 gibi özelliklerini gösterir.\nAyrıca bilgisayarın beklenmedik bir şekilde kapanmasına sebep olan hatayı da gösterir.",
+ "oc:tooltip.apu": " Ekran kartı olan bir işlemci, bir kart yuvasına daha ihtiyacınız olursa diye.\nDesteklenen parçalar: §f%s§7\nMaksimum çözünürlük: §f%sx%s§7\nMaksimum renk derinliği: §f%s§7\nİşlem/tick: §f%s§7",
+ "oc:tooltip.assembler": "Bilgisayar parçalarından robot ve başka cihazları üretmenize yarar.",
+ "oc:tooltip.cable": "Blokları bağlamanın ucuz bir yolu.",
+ "oc:tooltip.capacitor": "Daha sonra kullanılmak üzere enerji depolar. Çok hızlı şarj ve desarj olabilir.",
+ "oc:tooltip.carpetedcapacitor": "Daha sonra kullanılmak üzere enerji depolar. Çok hızlı şarj ve desarj olabilir. Bir Oselo veya Koyun üstünde yürürse şarj olur.",
+ "oc:tooltip.cardbase": "Adı üstünde, tüm bilgisayar kartlarının en basit yapıtaşı.",
+ "oc:tooltip.case": "Bilgisayar kasası bilgisayarın yapıtaşıdır ve bilgisayarın §fkartlarını§7, §fbelleğini§7 ve §fsürücülerimi§7 bünyesimde barındırır.\nYuvalar: §f%s§7",
+ "oc:tooltip.chamelium": "3B çıktılar için hammaddedir. Yutmayınız, körlük ve geçici bilinç kaybına sebep olabilir.",
+ "oc:tooltip.chameliumblock": "Hoş ve temiz. 3B çıktılarda renkli şekiller yaratmak veya üssünüzü temiz ve renkli bir blokla dekore etmek için kullanılabilir.",
+ "oc:tooltip.charger": "Sığaçlardan takındaki robotlara ve dronlara enerji aktarır. Aktarım hızı gelen §fkızıltaş sinyaline§7 bağlıdır; tam güç tam hızla şarj olması, hiç sinyal olmaması ise şarj olmaması demektir. Tabletleri de şarj etmek, hatta sürücülerine erişmek için kullanılabilir.",
+ "oc:tooltip.circuitboard": "İşte şimdi yol alıyoruz. İşleme tabi tutularak devre kartı elde edilebilir.",
+ "oc:tooltip.controlunit": "Bu birim... yönetiyor işte. İşlemciye ihtiyacın var o yüzden önemli, değil mi?",
+ "oc:tooltip.componentbus": "Bu eklenti sunucuların aynı anda daha çok parça ile bağlantı kurmasını sağlar, işlemciler gibi.\nDesteklenen parçalar §f%s§7",
+ "oc:tooltip.cpu": "Her bilgisayara lazım. Saati biraz istikrarsız ama cep saatinden o kadar oluyor. Çok sarsma.\nDesteklenen parçalar: §f%s§7",
+ "oc:tooltip.cpu.Architecture": "Mimari: §f%s§7",
+ "oc:tooltip.cuttingwire": "Kil blokları devre kartı şekline sokmak için kullanılır. Tek kullanımda kopar. Ne iğrenç bir alet bu.",
+ "oc:tooltip.datacard0": "\"hashing\", \"deflate\"/\"inflate\" gibi birkaç gelişmiş algoritma sunar.",
+ "oc:tooltip.datacard1": "\"hashing\", \"deflate\"/\"inflate\", AES şifreleme gibi birkaç gelişmiş algoritma sunar.",
+ "oc:tooltip.datacard2": "\"hashing\", \"deflate\"/\"inflate\", AES şifreleme, eliptik eğri kriptografisi gibi birkaç gelişmiş algoritma sunar.",
+ "oc:tooltip.debugcard": "Test etmeyi kolaylaştıran, dünyayı manüpile eden Yaratıcı mod aracı. Yetişkin denetimi altında kullanın.",
+ "oc:tooltip.debugger": "OpenComputers'ın iç ağının hata ayıklama bilgisini toplamak için kullanılır. Sadece bir geliştirici isterse kullanınız.",
+ "oc:tooltip.diamondchip": "Parıltılı bir elmasın naçiz bir parçası. Asla eskisi gibi olamayacak.",
+ "oc:tooltip.disassembler": "Nesneleri ihtiva ettiği parçalarına ayrıştırır. §lUyarı§7: ayrışan parçaların ayrışma sürecinde %%%s bozulma olasılığı vardır.",
+ "oc:tooltip.disk": "Daimi veri depolama cihazları yapılabilen ilkel veri saklama dairesi.",
+ "oc:tooltip.diskdrive.CC": "ComputerCraft disketler §açalışır§7.",
+ "oc:tooltip.diskdrive": "Disket okuma ve yazmaya yarar. Daha sonra disket takmak için robotlara da takılabilir.",
+ "oc:tooltip.diskdrivemountable": "Normal bir sürücüyle aynı işlevi görür fakat bir sunucu rafına takılmalıdır.",
+ "oc:tooltip.diskusage": "Disk kullanımı: %s/%s Byte",
+ "oc:tooltip.diskmodemanaged": "Kip: Denetimli",
+ "oc:tooltip.diskmodeunmanaged": "Kip: Denetimsiz",
+ "oc:tooltip.drone": "Dronlar hafif, hızlı, az yük kapasiteli uçan cihazlardır.",
+ "oc:tooltip.dronecase": "Bu kasa birleştirici ile Drone yapmak için kullanılır. Sınırlı parça için alanı var ve end taşı ile güçlendirilmiş uçma kabiliyeti var.",
+ "oc:tooltip.eeprom": "Elektrikle silinebilir, programlanabilir salt okunur hafıza. Bilgisayarların çalışması için gerekli BIOS kodunu içerir.",
+ "oc:tooltip.fakeendstone": "Neredeyse aynısı, bu da havalanmaya meyilli.",
+ "oc:tooltip.geolyzer": "Yakındaki blokların sertliğini ölçmeye yarar. Bu bilgi cevher bulmak için bölgenin holgramını yapmaya yarayabilir.",
+ "oc:tooltip.graphicscard": "Ekranları güzel bilgilerle doldurur.\nAzami Çözünürlük: §f%sx%s§7\nAzami renk derinliği: §f%s§7\nİşlem/tick: §f%s§7",
+ "oc:tooltip.hoverboots": "Daha yükseğe sıçra, daha derine in, daha iyi yürü. Hepsi Uçan Bot (TM) sayesinde.",
+ "oc:tooltip.inkcartridge": "3B yazıcılara mürekkep koymak için kullanılır. Nedense makineye takılı kalmıyor.",
+ "oc:tooltip.inkcartridgeempty": "Yazıcının kartuşu yine birmiş. Mürekkebi doldurabilirsin. Ya da at gitsin. Nasıl olsa bir daha aynı yazmaz.",
+ "oc:tooltip.internetcard": "Bu kart ile gerçekten internete bağlanıp, TCP üzerinden HTTP istemlerinde bulunabilirsiniz.",
+ "oc:tooltip.interweb": "Tebrikler, bir ağ (?) kazandınız. Internete bununla bağlanabilirsiniz. Trollerin seviyesine inmmeyin.",
+ "oc:tooltip.ironnugget": "Demirden kopan bir parça, başka nasıl açıklayayım.",
+ "oc:tooltip.keyboard": "Yazı yazmak için ekranlara takılabilir.",
+ "oc:tooltip.hologram0": "Bilgisayarla kumanda edilen, voksel tabanlı yapıları göstermek için kullanılan hacimsel ekran.\nÇözünürlük: §f48x32x48§7\nAzami Ölçek: §f3x§7\nRenk derinliği: §fMonokrom§7",
+ "oc:tooltip.hologram1": "Bilgisayarla kumanda edilen, voksel tabanlı yapıları göstermek için kullanılan hacimsel ekran.\nÇözünürlük: §f48x32x48§7\nAzami Ölçek: §f3x§7\nRenk derinliği: §f3 Renkli§7",
+ "oc:tooltip.linkedcard": "Bunlar çiftler halinde üretilir ve sadece partneriyle iletişim kurarlar. İletişimleri mesafeyi ve boyutları engel tanımaz fakat çok güç ister.",
+ "oc:tooltip.linkedcard_channel": "§8Kanal: %s§7",
+ "oc:tooltip.manual": "OpenComputers hakkında ihtiyaç duyabileceğiniz her bilgi ve daha fazlası. Hem de sadece ... §ofiyatı öğrenmek için R'ye basın§7.",
+ "oc:tooltip.memory": "Bilgisayarların çalışması için gerekli. Ne kadar çok belleğiniz varsa o kadar karmaşık programlar çalıştırabilirsiniz.",
+ "oc:tooltip.microchip": "Siyah elektrikle çalışan zımbırtılar. Neden kızıltaşla çalıştıkları beni aşıyor.",
+ "oc:tooltip.microcontroller": "Mikroişlemciler bilgisayarların en asgari biçimi. Görev odaklıdırlar ve EEPROM'larında gelen tek bir programla çalışırlar.\n§cHarici parçalarla bağlantı kuramazlar.§7",
+ "oc:tooltip.microcontrollercase": "Mikroişlemcilerin temel bileşeni. Mikroişlemci yapmak için bir birleştirici kullanın ve başka parçalar ekleyin.",
+ "oc:tooltip.motionsensor": "Yakındaki canlıların hareketini algılar. Çalışması için canlılar görüş açısında olmalıdır.",
+ "oc:tooltip.nanomachines": "Kumanda birimi ve tüketilmek üzere bir sürü nanomakine, tabi sende o mide varse.",
+ "oc:tooltip.networkcard": "Uzaktaki, birbirine başka bloklarla bağlı (örneğin kablolarla) bilgisayarların birbirlerine mesajlar göndererek iletişim kurmasını sağlar.",
+ "oc:tooltip.poweracceptor": "Enerji dönüşüm hızı: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fBuildCraft MJ'si§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fFactorization Yükü§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fIndustrialCraft² EU'su§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fMekanism Joule'ü§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fThermal Expansion RF'i§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fResonant Engine Coulomb'u§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "Başka modların enerjilerini OpenComputers'ın kendi enerji birimine dönüştürür. Dönüşüm oranları:",
+ "oc:tooltip.powerdistributor": "Farklı ağlara enerji dağıtır. Ayrı kalması gereken alt-ağlara dönüştürücüden gelen enerjiyi dağıtmak için bire bir.",
+ "oc:tooltip.present": "... çoban armağanı. Verdiğimiz rahatsızlıktan dolayı. Hediyeyi açarak §kganimetlere§7 sahip olabilirsiniz.\n§8Doğru zamanda OpenComputers parçaları üreterek hediye kazanabilirsiniz.§7",
+ "oc:tooltip.print.BeaconBase": "§8Fener tabanı olarak işlev görür.",
+ "oc:tooltip.print.LightValue": "§8Işınan ışık: %s.",
+ "oc:tooltip.print.RedstoneLevel": "§8Kızıltaş çıktısı: %s.",
+ "oc:tooltip.printedcircuitboard": "Bellek, bilgisayar kartları vb.nin yapı taşı.",
+ "oc:tooltip.printer": "Kullanıcı tanımlı nesnelerin şamelyum ve mürekkep kullanılarak basılmasını sağlar. Bir bilgisayar tarafından yönetilmelidir. Bazı sebeplerden dolayı, çocuklardan uzak tutun.",
+ "oc:tooltip.raid": "Birden fazla diskin tek bir dosya sistemi altında birleştirilip bağlı tüm bilgisayarlar tarafından kullanılmasını sağlar.",
+ "oc:tooltip.rawcircuitboard": "Herhangi bir fırında kurutulabilir.",
+ "oc:tooltip.redstone": "Bloğun çevresinde kızıltaş iletimi ve çevresinden kızıltaş alıgalma yapabilir. Bağlı herhangi bir bilgisayar kumanda edebilir. Harici bir kızıltaş kartı gibi davranır.",
+ "oc:tooltip.redstonecard.ProjectRed": "§fProject: Red§7 §adestekli§7.",
+ "oc:tooltip.redstonecard.RedLogic": "§fRedLogic§7 §adestekli§7.",
+ "oc:tooltip.redstonecard.RedNet": "§fRedNet§7 §adestekli§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "§fWireless Redstone (ChickenBones)§7 §adestekli§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "§fWireless Redstone (SlimeVoid)§7 §adestekli§7.",
+ "oc:tooltip.redstonecard": "Bilgisayarın veya robotun çevresine kızltaş sinyali iletimesini ve çevresinden kızıltaş sinyalı algılamasını sağlar.",
+ "oc:tooltip.relay": "Farklı ağları birbirine bağlamaya yarar. Sadece ağ mesajları iletilir, parçalar görünmez. Bunu Ağ kartlarını kullanırken bilgisayarları birbirinden izole etmek için kullanabilirsiniz.",
+ "oc:tooltip.robot": "Bilgisayarların aksine robotlar oyuncular gibi dünyada hareket edebilir ve ona değişiklikler yapabilir.\n§cHarici parçalara bağlanamaz.§7",
+ "oc:tooltip.robot_level": "§fSeviye§7: §a%s§7",
+ "oc:tooltip.robot_storedenergy": "§fDepolu enerji§7: §a%s§7",
+ "oc:tooltip.screen": "Yazı göster, kasadaki bir ekran kartı aracılığıyla.\nAzami çözünürlük: §f%sx%s§7\nAzami renk derinliği: §f%s§7",
+ "oc:tooltip.server": "Bu bir sunucu. Bundan çokça olabilir fakat bu (bir bilgisayar gibi) başka parçalarla geliştirilebilir. Sunucu rafına takılarak çalıştırılabilir.",
+ "oc:tooltip.server.Components": "Takılı Parçalar:",
+ "oc:tooltip.rack": "4 sunucunun veya rafa konulabilen parçaların takılmasını sağlar.",
+ "oc:tooltip.tablet": "Lua ile eğlence için bir tablet bilgisayar. Çömelirken aktifleştirirseniz kapanmaya sorlarsınız.",
+ "oc:tooltip.tabletcase": "Basit bir tablet kasası. Bir birleştirici ve başka parçalar ile bir tablet yapabilirsiniz..",
+ "oc:tooltip.terminal": "Menzili içinde bir sunucuyu uzaktan kumanda etmenize yarar. Taşınabilir ekran ve klavye gibi davranır. Shift+Sağ-Tık ile raftaki bir sunucuya bağlayabilirsiniz.",
+ "oc:tooltip.terminalserver": "Uzaktan Uçbirimin yöneticisi. Sanal bir ekranı ve klavyesi var.",
+ "oc:tooltip.texturepicker": " Bu alet, 3B yazıcıda şekil tanımlamak üzere bir bloğun yüzeyini ifade eden bir metin gösterir. Kesinlikle dokunun ismi değil. Sana yalan borcum mu var?",
+ "oc:tooltip.tier": "§8%s. Seviye",
+ "oc:tooltip.netsplitter": "Ayarlanabilir bir bağlantı noktası gibi davranır. Her yüzün bağlantısı bir İngiliz anahtarı ile değiştirilebilir. Her yüzün bağlantısı bir kızıltaş sinyali ile tersine dönüştürülebilr.",
+ "oc:tooltip.toolong": "Şuna basılı tutarak daha detaylı bilgi alabilirsiniz: [§f%s§7]",
+ "oc:tooltip.transistor": "Çoğu bilgisayar parçasının basit bir bileşeni. Biraz yamulmuş ama iş görür.",
+ "oc:tooltip.transposer": "Bitişiğindeki envanterler arasında katı ve sıvı değişimini sağlar.",
+ "oc:tooltip.upgradeangel": "Robotlara boşlukta (tutunacak yer yokken) blok koyma yetisi sağlar.",
+ "oc:tooltip.upgradebattery": "Cihazın depolayabileceği enerji miktarını arttırır. Böylece cihaz şarj olmadan daha uzun süre çalışabilir.\nKapasite: §f%s§7",
+ "oc:tooltip.upgradechunkloader": "Robot tek başına ormana giderse ve onu kimse görmezse hareket eder mi? Bu eklenti çalıştığından emin olur. Bir bölümü(16x16x256) sürekli yüklü tutar fakat sürekli enerji harcar.",
+ "oc:tooltip.upgradecontainercard": "Bu yuva birleştirilmiş cihazda kartların rahatlıkla takılıp çıkarılmasını sağlar.\nAzami Seviye: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "Bu yuva birleştirilmiş cihazda eklentilerin rahatlıkla takılıp çıkarılmasını sağlar.\nAzami Seviye: §f%s§7",
+ "oc:tooltip.upgradecrafting": "Robotun envanterinin sol üst köşesini çalışma masası gibi kullanmasını sağlar. Nesnelerin tarife göre yerleşmesi şarttır.",
+ "oc:tooltip.upgradedatabase": "Bu eklenti deste bilgisinin başka parçalar tarafından kullanılmak üzere saklanmasını sağlar.\nDesteklenen satır sayısı: §f%s§7",
+ "oc:tooltip.upgradeexperience": "Bu eklenti çeşitli eylemler aracalığıyla robotların deneyim kazanmasını sağlar. Robotlar ne kadar deneyimliyse o kadar enerji depolayabilir, o kadar hızlı blok toplayabilir ve aletleri o kadar etkili kullanabilir.",
+ "oc:tooltip.upgradegenerator": "Yolda yakıttan enerji üretimini sağlar. Yakıtları enerji değerlerine göre enerji üretmek için kullanır.\n§fVerimlilik§7: §a%s%%§7",
+ "oc:tooltip.upgradehover": "Bu eklenti robotun duvar tırmanmak zorunda kalmadan daha yükseğe çıkmasını sağlar.\nAzami irtifa: §f%s§7",
+ "oc:tooltip.upgradeinventory": "Bu eklenti bir robota veya drona envanter sağlar. Bu olmadan nesne tutamazlar.",
+ "oc:tooltip.upgradeinventorycontroller": "Bu eklenti robotların ve dronların harici envanterlerle iletişim kurmasını ve onlardaki aletlerle kendi aletini değişmesini sağlar.",
+ "oc:tooltip.upgrademf": "Dönüştürücülerin bitişiğinde olmadığı nesnelerle iletişim kurmasını sağlar.",
+ "oc:tooltip.upgrademf.Linked": "§fBağlantı kuruldu§7",
+ "oc:tooltip.upgrademf.Unlinked": "§fBağlantı yok§7",
+ "oc:tooltip.upgradeleash": "Drone gibi bazı cihazların belediye görevlilerine sataş...-özür dilerim. Bu cihaz aslında canlı(lar)ı bağlamak için kullanılıyormuş. İlğinç.",
+ "oc:tooltip.upgradenavigation": "Cihazın yönünü ve yerini tespit etmek için kullanılır. Yer bilgisi eklentiyi üretirken kullanılan haritanın merkez noktasına göredir.",
+ "oc:tooltip.upgradepiston": "Bu eklenti çok itici. Piston gibi blokları hareket ettirmeye yarar. Canlıları ve partikülleri hareket ettir§lmez§7.",
+ "oc:tooltip.upgradesign": "Tabelalardan yazı okumayı ve onlara yazı yazmayı sağlar.",
+ "oc:tooltip.upgradesolargenerator": "Güneşten enerji üretimini sağlar. Gökyüzü görüş açısında olmalıdır. Bir Stirling motorunun %%%s katı hızı kadar hızlı enerji üretebilir.",
+ "oc:tooltip.upgradetank": "Robotlara ve dronlara sıvı depolama alanı sağlar. Bu olmadan sıvı depolayamazlar.",
+ "oc:tooltip.upgradetankcontroller": "Bu eklenti robotlara ve dronlara harici sıvı depoları ile iletişim yeteneği sağlar. Harici depodan dahiliye, dahiliden hariciye sıvı iletimi sağlar.",
+ "oc:tooltip.upgradetractorbeam": "Nesne mıknatısı adı verilen çok gelişmiş bir teknolojiti edinin. Cihazın 3 block menzilinden nesneleri almasını sağlar.",
+ "oc:tooltip.waypoint": "Yönbulma eklentisi olan cihazlar için referans noktası oluşturur.",
+ "oc:tooltip.wirelessnetworkcard": "Normal ağ mesajlarının yanı sıra kablosuz ağ mesajlarının iletimini sağlar. §fSinyal gücünü§7 ayarlayarak mesajların ne kadar uzağa iletildiğini kontrol edebilirsiniz. Yüksek sinyal gücü daha çok enerji tüketir.",
+ "oc:tooltip.worldsensorcard": "Dünya hakkında yerçekimi ve nefes alınabilir bir atmosferi olup olmadığı gibi bilgileri toplar. Bilgiler kesin değildir. Üretici firma karttan edilen bilgilere göre verilen kararlar sonucu oluşan maddi ve manevi hiçbir hasardan sorumlu değildir. Avukatlarımız var. Paramız da. Denemeyi aklınızdan bile geçirmeyin.",
+ "oc:tooltip.Wrench": "İngiliz anahtarı tornavida karışımı bir şey. Öğrenmesi basit, ustalaşması zor.",
+ "achievement.oc.adapter": "Tak-Çalıştır",
+ "achievement.oc.adapter.desc": "Diğer modların ve elbette vanilla Minecraft blokları ile iletişim kur.",
+ "achievement.oc.assembler": "Harika",
+ "achievement.oc.assembler.desc": "Dünyayı ele geçirme vakti.",
+ "achievement.oc.cable": "Temiz Kablo",
+ "achievement.oc.cable.desc": "Patentli dolanma önleyici teknolojisi ile.",
+ "achievement.oc.capacitor": "Piller Ürüne Dahildir.",
+ "achievement.oc.capacitor.desc": "Durduramazsın.",
+ "achievement.oc.card": "Kredi Kartı Geçerlidir.",
+ "achievement.oc.card.desc": "Sizin için. Kesinlikle bir art niyetimiz yok.",
+ "achievement.oc.case": "Yangın Durumunda ...",
+ "achievement.oc.case.desc": "Çünkü küp kasalar en iyisi.",
+ "achievement.oc.charger": "Haydi şu işi bitirelim.",
+ "achievement.oc.charger.desc": "Şarj etsene seni... Kızıltaş sinyalini unutmuşum.",
+ "achievement.oc.chip": "En Küçüğünden Lütfen",
+ "achievement.oc.chip.desc": "Çünkü tüpler eskide kaldı.",
+ "achievement.oc.cpu": "Modifiye",
+ "achievement.oc.cpu.desc": "Haydi bu makineyi biraz zorlayalım.",
+ "achievement.oc.disassembler": "Ali Yazar, Veli Bozar",
+ "achievement.oc.disassembler.desc": "Nasıl olsa Sarı Çizmeli Mehmet Ağa bir gün öder hesabı.",
+ "achievement.oc.diskDrive": "Dönmedolap",
+ "achievement.oc.diskDrive.desc": "Az alan, güzel ses.",
+ "achievement.oc.drone": "Su gibi git...",
+ "achievement.oc.drone.desc": "... su gibi gel. Pahalısın lazımsın bize.",
+ "achievement.oc.eeprom": "Ya ben, ya hiç!",
+ "achievement.oc.eeprom.desc": "Bilgisayar için, önemli bir parça.",
+ "achievement.oc.floppy": "Güneş Tutulması",
+ "achievement.oc.floppy.desc": "Hepsini bozduk 1999'da.",
+ "achievement.oc.geolyzer": "Zonguldak",
+ "achievement.oc.geolyzer.desc": "Toprak ne ki, yeri bir metre kaz kömür çıkıyor.",
+ "achievement.oc.graphicsCard": "Yeni Nesil",
+ "achievement.oc.graphicsCard.desc": "Döviz kuru düşseydi fakir kalmazdım.",
+ "achievement.oc.hdd": "Hıyar Domates Dirhem",
+ "achievement.oc.hdd.desc": "Yanlış oldu, bekle dilimin ucunda.",
+ "achievement.oc.hologram": "Gelecek Boyut",
+ "achievement.oc.hologram.desc": "2B'tan sıkıldın mı?",
+ "achievement.oc.keyboard": "TozMıknatısı3000",
+ "achievement.oc.keyboard.desc": "Odanıza alın, odanız tertemiz olsun*. *TozMıknatısı300 dışında.",
+ "achievement.oc.microcontroller": "Kardeş",
+ "achievement.oc.microcontroller.desc": "Bilgisayarın küçük kardeşi.",
+ "achievement.oc.motionSensor": "Tuvalet Kabusu",
+ "achievement.oc.motionSensor.desc": "İşerken ışık söner mi acaba?",
+ "achievement.oc.networkCard": "Feysbuk",
+ "achievement.oc.networkCard.desc": "Hep birlikte kimsenin takmadığı şeyleri paylaşıp sosyal olduğumuzu sanıyoruz.",
+ "achievement.oc.openOS": "iŞlEtİm SiStEmİ NeY?",
+ "achievement.oc.openOS.desc": "Bilgisayarcıya git format atsın ablacım.",
+ "achievement.oc.powerDistributor": "Hayat Paylaşınca Güzel",
+ "achievement.oc.powerDistributor.desc": "Reklam yapmıyoruz. Güzel sözün telif hakkı mı olur?",
+ "achievement.oc.rack": "\"Bizim salondaki raf olur mu?\"",
+ "achievement.oc.rack.desc": "Tartmaz bir kere.",
+ "achievement.oc.raid": "Yerim Kalmadı.",
+ "achievement.oc.raid.desc": "Ne kadar çok \"aile fotoğrafı\"n varsa artık.",
+ "achievement.oc.ram": "Seçici Hatıra",
+ "achievement.oc.ram.desc": "Nedense sevdiklerimi daha çok hatırlıyorum.",
+ "achievement.oc.redstoneCard": "Regülatörü Tak.",
+ "achievement.oc.redstoneCard.desc": "Daha tüpler ısınacak.",
+ "achievement.oc.redstoneIO": "TRT",
+ "achievement.oc.redstoneIO.desc": "İlk yayın birazdan başlayacak.",
+ "achievement.oc.robot": "\"Gerginlik yaratma robot o robot.\"",
+ "achievement.oc.robot.desc": "\"Robot musun sen?\" \"Evet.\"",
+ "achievement.oc.screen": "Aç Kapa Çalışır.",
+ "achievement.oc.screen.desc": "Gerçekten, kızıltaş sinyalleri etkiliyor.",
+ "achievement.oc.server": "e-Devlet Kapısı",
+ "achievement.oc.server.desc": "Ne varsa orada, bu bilgileri kim saklayacak.",
+ "achievement.oc.switch": "Birini düzelt, diğerini boz.",
+ "achievement.oc.switch.desc": "Telekomcular niye işlerini yapamıyor.",
+ "achievement.oc.tablet": "Bu bir ilaç değildir.",
+ "achievement.oc.tablet.desc": "Çocuklardan uzak tutun. İstenmeyen harcamalara neden olabilir.",
+ "achievement.oc.transistor": "Düğmemtırak",
+ "achievement.oc.transistor.desc": "Bizim radyodada vardı bunlardan.",
+ "achievement.oc.wirelessNetworkCard": "\"Işınla bizi Scotty\"",
+ "achievement.oc.wirelessNetworkCard.desc": "\"Barış içinde size bir ileti getirdik.\"",
+ "death.attack.oc.nanomachinesOverload.1": "%s elini çok sıkı tuttu.",
+ "death.attack.oc.nanomachinesOverload.2": "%s kafayı yedi.",
+ "death.attack.oc.nanomachinesOverload.3": "%s öldü. Nanomakine varmış diyorlar.",
+ "death.attack.oc.nanomachinesHungry.1": "%s sizlere ömür. Nanomakineler diri diri yemiş.",
+ "death.attack.oc.nanomachinesHungry.2": "%s nanomakinelerine bakmadı.",
+ "death.attack.oc.nanomachinesHungry.3": "%s sindirildi.",
+ "nei.options.inventory.oredict": "Cevher Muadilleri Sözlüğü Adlarını Göster",
+ "nei.options.inventory.oredict.true": "Evet",
+ "nei.options.inventory.oredict.false": "Hayır",
+ "nei.usage.oc.Manual": "Kılavuzu Aç",
+ "option.oc.address": "Adres",
+ "option.oc.componentName": "Parça Adı",
+ "option.oc.energy": "Enerji"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/zh_CN.lang b/src/main/resources/assets/opencomputers/lang/zh_CN.lang
deleted file mode 100644
index de254f0db7..0000000000
--- a/src/main/resources/assets/opencomputers/lang/zh_CN.lang
+++ /dev/null
@@ -1,479 +0,0 @@
-# OpenComputer
-# This is the Simplified Chinese file for localizations.
-# Use [nl] to for a line break. 使用[nl]换行。
-
-# Blocks
-tile.oc.adapter.name=适配器
-tile.oc.assembler.name=装配器
-tile.oc.cable.name=线缆
-tile.oc.capacitor.name=电容
-tile.oc.carpetedcapacitor.name=踩踏发电电容
-tile.oc.case1.name=基础机箱
-tile.oc.case2.name=高级机箱
-tile.oc.case3.name=超级机箱
-tile.oc.casecreative.name=创造模式机箱
-tile.oc.chameliumblock.name=变色块
-tile.oc.charger.name=充电器
-tile.oc.disassembler.name=拆解器
-tile.oc.diskdrive.name=软盘驱动器
-tile.oc.endstone.name=末地石
-tile.oc.geolyzer.name=地质分析仪
-tile.oc.hologram1.name=基础全息地图投影仪
-tile.oc.hologram2.name=高级全息地图投影仪
-tile.oc.keyboard.name=键盘
-tile.oc.microcontroller.name=单片机
-tile.oc.motionsensor.name=运动传感器
-tile.oc.netsplitter.name=网络分配器
-tile.oc.powerconverter.name=能量转换器
-tile.oc.powerdistributor.name=能量分配器
-tile.oc.print.name=3D 打印
-tile.oc.printer.name=3D 打印机
-tile.oc.raid.name=Raid磁盘阵列
-tile.oc.redstone.name=红石 I/O 端口
-tile.oc.relay.name=中继器
-tile.oc.robot.name=机器人
-tile.oc.robotafterimage.name=机器人
-tile.oc.screen1.name=基础显示屏
-tile.oc.screen2.name=高级显示屏
-tile.oc.screen3.name=超级显示屏
-tile.oc.rack.name=机架
-tile.oc.transposer.name=转运器
-tile.oc.waypoint.name=路径点
-
-# Items
-item.oc.abstractbuscard.name=抽象类总线卡
-item.oc.acid.name=酸液
-item.oc.alu.name=算术逻辑单元(ALU)
-item.oc.analyzer.name=分析器
-item.oc.apu0.name=高级加速运算单元(APU)
-item.oc.apu1.name=超级加速运算单元(APU)
-item.oc.apu2.name=创造加速运算单元(APU)
-item.oc.arrowkeys.name=方向键
-item.oc.buttongroup.name=按钮组
-item.oc.cardbase.name=基板
-item.oc.chamelium.name=变色材料
-item.oc.circuitboard.name=电路板
-item.oc.componentbus0.name=基础组件总线
-item.oc.componentbus1.name=高级组件总线
-item.oc.componentbus2.name=超级组件总线
-item.oc.componentbus3.name=创造模式组件总线
-item.oc.controlunit.name=控制单元(CU)
-item.oc.cpu0.name=基础中央处理器(CPU)
-item.oc.cpu1.name=高级中央处理器(CPU)
-item.oc.cpu2.name=超级中央处理器(CPU)
-item.oc.cuttingwire.name=切割线
-item.oc.datacard0.name=基础数据卡
-item.oc.datacard1.name=高级数据卡
-item.oc.datacard2.name=超级数据卡
-item.oc.debugcard.name=调试卡
-item.oc.debugger.name=网络调试器
-item.oc.diamondchip.name=钻石芯片
-item.oc.disk.name=磁碟
-item.oc.diskdrivemountable.name=可挂载软盘驱动器
-item.oc.drone.name=无人机
-item.oc.dronecase0.name=基础无人机外壳
-item.oc.dronecase1.name=高级无人机外壳
-item.oc.dronecase3.name=创造无人机外壳
-item.oc.eeprom.name=EEPROM
-item.oc.floppydisk.name=软盘
-item.oc.GraphicsCard0.name=基础显卡
-item.oc.GraphicsCard1.name=高级显卡
-item.oc.GraphicsCard2.name=超级显卡
-item.oc.HardDiskDrive0.name=基础磁盘驱动器
-item.oc.HardDiskDrive1.name=高级磁盘驱动器
-item.oc.HardDiskDrive2.name=超级磁盘驱动器
-item.oc.hoverBoots.name=悬浮靴
-item.oc.inkcartridge.name=墨盒
-item.oc.inkcartridgeempty.name=空墨盒
-item.oc.internetcard.name=因特网卡
-item.oc.Interweb.name=因特网
-item.oc.ironnugget.name=铁粒
-item.oc.linkedcard.name=连接卡
-item.oc.manual.name=开放式电脑使用手册
-item.oc.memory0.name=内存条-T1
-item.oc.memory1.name=内存条-T1.5
-item.oc.memory2.name=内存条-T2
-item.oc.memory3.name=内存条-T2.5
-item.oc.memory4.name=内存条-T3
-item.oc.memory5.name=内存条-T3.5
-item.oc.microchip0.name=简易微芯片
-item.oc.microchip1.name=高级微芯片
-item.oc.microchip2.name=超级微芯片
-item.oc.microcontrollercase0.name=基础单片机外壳
-item.oc.microcontrollercase1.name=高级单片机外壳
-item.oc.microcontrollercase3.name=创造单片机外壳
-item.oc.nanomachines.name=纳米机器
-item.oc.networkcard.name=网卡
-item.oc.numpad.name=数字键盘
-item.oc.present.name=一点小礼物……
-item.oc.printedcircuitboard.name=印刷电路板(PCB)
-item.oc.rawcircuitboard.name=未加工电路板
-item.oc.redstonecard0.name=基础红石卡
-item.oc.redstonecard1.name=高级红石卡
-item.oc.server0.name=基础服务器
-item.oc.server1.name=高级服务器
-item.oc.server2.name=超级服务器
-item.oc.server3.name=创造模式服务器
-item.oc.tablet.name=平板电脑
-item.oc.tabletcase0.name=基础平板电脑外壳
-item.oc.tabletcase1.name=高级平板电脑外壳
-item.oc.tabletcase3.name=创造模式平板电脑外壳
-item.oc.terminal.name=终端
-item.oc.terminalserver.name=终端服务器
-item.oc.texturepicker.name=纹理选择器
-item.oc.transistor.name=晶体管
-item.oc.upgradeangel.name=天使方块升级
-item.oc.upgradebattery0.name=基础电池升级
-item.oc.upgradebattery1.name=高级电池升级
-item.oc.upgradebattery2.name=超级电池升级
-item.oc.upgradechunkloader.name=区块载入升级
-item.oc.upgradecontainercard0.name=基础卡槽
-item.oc.upgradecontainercard1.name=高级卡槽
-item.oc.upgradecontainercard2.name=超级卡槽
-item.oc.upgradecontainerupgrade0.name=基础升级组件容器
-item.oc.upgradecontainerupgrade1.name=高级升级组件容器
-item.oc.upgradecontainerupgrade2.name=超级升级组件容器
-item.oc.upgradecrafting.name=合成升级
-item.oc.upgradedatabase0.name=基础数据库升级
-item.oc.upgradedatabase1.name=高级数据库升级
-item.oc.upgradedatabase2.name=超级数据库升级
-item.oc.upgradeexperience.name=经验升级
-item.oc.upgradegenerator.name=发电机升级
-item.oc.upgradehover0.name=基础悬浮升级
-item.oc.upgradehover1.name=高级悬浮升级
-item.oc.upgradeinventory.name=物品栏升级
-item.oc.upgradeinventorycontroller.name=物品栏控制器升级
-item.oc.upgradeleash.name=缰绳升级
-item.oc.upgrademf.name=MFU
-item.oc.upgradenavigation.name=导航升级
-item.oc.upgradepiston.name=活塞升级
-item.oc.upgradesign.name=告示牌读写升级
-item.oc.upgradesolargenerator.name=太阳能发电机升级
-item.oc.upgradetank.name=水箱升级
-item.oc.upgradetankcontroller.name=储罐升级
-item.oc.upgradetractorbeam.name=牵引光束升级
-item.oc.upgradetrading.name=交易升级
-item.oc.wirelessnetworkcard0.name=基础无线网卡
-item.oc.wirelessnetworkcard1.name=高级无线网卡
-item.oc.worldsensorcard.name=世界传感器卡
-item.oc.wrench.name=螺丝刀扳手
-
-# Entities
-entity.oc.Drone.name=无人机
-
-# GUI
-oc:gui.Analyzer.Address=§6地址§f:%s
-oc:gui.Analyzer.AddressCopied=地址已复制到剪贴板。
-oc:gui.Analyzer.ChargerSpeed=§6充电速度§f:%s
-oc:gui.Analyzer.ComponentName=§6组件名§f:%s
-oc:gui.Analyzer.Components=§6已连接组件的数量§f:%s
-oc:gui.Analyzer.CopyToClipboard=点击以复制到剪贴板。
-oc:gui.Analyzer.LastError=§6上一个错误§f:%s
-oc:gui.Analyzer.RobotName=§6名称§f:%s
-oc:gui.Analyzer.RobotOwner=§6主人§f:%s
-oc:gui.Analyzer.RobotXp=§6经验§f:%s(等级 %s)
-oc:gui.Analyzer.StoredEnergy=§6存储能量§f:%s
-oc:gui.Analyzer.TotalEnergy=§6存储能量上限§f:%s
-oc:gui.Analyzer.Users=§6用户§f:%s
-oc:gui.Analyzer.WirelessStrength=§6信号强度§f:%s
-oc:gui.Assembler.Collect=收集输出
-oc:gui.Assembler.Complexity=复杂度:%s/%s
-oc:gui.Assembler.InsertCase=插入一个机箱
-oc:gui.Assembler.InsertCPU=插入一个CPU
-oc:gui.Assembler.InsertRAM=插入一些存储器
-oc:gui.Assembler.Progress=进度:%s%%(%s)
-oc:gui.Assembler.Run=组装
-oc:gui.Assembler.Warning.BIOS=BIOS
-oc:gui.Assembler.Warning.GraphicsCard=显卡
-oc:gui.Assembler.Warning.Inventory=物品栏升级
-oc:gui.Assembler.Warning.Keyboard=键盘
-oc:gui.Assembler.Warning.OS=运行环境
-oc:gui.Assembler.Warning.Screen=显示屏
-oc:gui.Assembler.Warnings=§e警告§7:推荐的组件丢失。
-oc:gui.Chat.NewVersion=有新版本可用:%s
-oc:gui.Chat.TextureName=§7材质名为§a%s§f。
-oc:gui.Chat.WarningClassTransformer=执行类转换器时发生§c错误§f。请务必反馈此问题,反馈时一并附上 FML 的日志文件 §alatest.log/fml-server-latest.log§f,谢谢!
-oc:gui.Chat.WarningFingerprint=§c警告§f——指纹校验不匹配!应为 '§a%s§f',实为 '§e%s§f'。如果你不是在反混淆环境下运行游戏的模组开发者,我们§l强烈§f建议你重新下载开放式电脑模组,因为你现在使用的 JAR 文件已被修改。
-oc:gui.Chat.WarningLink=无法打开链接:%s
-oc:gui.Chat.WarningLuaFallback=无法使用原生 Lua 库,电脑无法持久化当前状态。它们会在区块载入时重启。
-oc:gui.Chat.WarningProjectRed=你目前使用的 Project:Red 版本不兼容 OpenComputers,请更新 Project:Red。
-oc:gui.Chat.WarningRecipes=加载合成表时遇到一个或多个错误。部分物品或因此无法合成。查阅日志文件以获取详细信息。
-oc:gui.Chat.WarningSimpleComponent=某个扩展 Mod 使用了 §aSimpleComponent§f 接口但§e做错了一些事情§f,导致组件逻辑无法注入。查阅日志文件以获取详细信息。
-oc:gui.Drive.Managed=受管理
-oc:gui.Drive.Unmanaged=不受管理
-oc:gui.Drive.ReadOnlyLock=只读锁定
-oc:gui.Drive.ReadOnlyLockWarning=§l只读§r锁定.除非抹掉该磁盘,否则无法关闭.
-oc:gui.Drive.Warning=§l警告§r:切换模式将会导致当前磁盘上所有数据丢失!
-oc:gui.Error.ComponentOverflow=过多的组件连接了计算机。
-oc:gui.Error.InternalError=内部错误,请检查日志文件。这可能是个Bug。
-oc:gui.Error.NoCPU=这台计算机上没有安装CPU。
-oc:gui.Error.NoEnergy=能量不足。
-oc:gui.Error.NoRAM=这台计算机上没有安装内存。
-oc:gui.Error.OutOfMemory=内存溢出。
-oc:gui.Manual.Blocks=开放式电脑-方块
-oc:gui.Manual.Home=主页
-oc:gui.Manual.Items=开放式电脑-物品
-oc:gui.Manual.Warning.BlockMissing=该方块不可用。
-oc:gui.Manual.Warning.ImageMissing=未找到图片。
-oc:gui.Manual.Warning.ItemMissing=该物品不可用。
-oc:gui.Manual.Warning.OreDictMissing=该矿物词典条目不可用。
-oc:gui.Raid.Warning=§4添加磁盘会抹掉该磁盘。[nl]移除磁盘会使Raid无法使用。
-oc:gui.Robot.Power=能量
-oc:gui.Robot.TurnOff=关闭
-oc:gui.Robot.TurnOn=开启[nl]§7使用分析器来追踪错误。§r
-oc:gui.ServerRack.Back=后
-oc:gui.ServerRack.Bottom=底部
-oc:gui.ServerRack.Left=左
-oc:gui.ServerRack.None=无
-oc:gui.ServerRack.Right=右
-oc:gui.Rack.Enabled=启用
-oc:gui.Rack.Disabled=禁用
-oc:gui.ServerRack.Top=上
-oc:gui.Switch.PacketsPerCycle=数据包 / 周期
-oc:gui.Switch.QueueSize=队列长度
-oc:gui.Switch.TransferRate=传输速率
-oc:gui.Terminal.InvalidKey=无效键,看上去另一个终端已绑定到这台服务器。
-oc:gui.Terminal.OutOfRange=无信号。
-
-# Containers
-oc:container.adapter=适配器
-oc:container.case=计算机
-oc:container.charger=充电器
-oc:container.disassembler=分解器
-oc:container.diskdrive=磁盘驱动器
-oc:container.printer=打印机
-oc:container.raid=Raid磁盘阵列
-oc:container.relay=中继器
-oc:container.server=服务器
-oc:container.rack=机架
-oc:container.tabletwrapper=平板电脑
-
-# Keybinds
-key.clipboardPaste=粘贴到剪贴板
-
-# Item / Block Tooltips
-oc:tooltip.abstractbuscard=允许计算机向§f星门科技2§7的抽象类总线发送或接收 LIP 数据包。
-oc:tooltip.acid=一种有毒的虚构液体,通常只有某些海盗会使用它们。然而它应该有别的用途。
-oc:tooltip.adapter=用于控制非电脑组件的方块,比如原版或者来自其它模组的方块。
-oc:tooltip.alu=用来做算术及逻辑运算而不用你亲自代劳,它更能胜任这份差事。
-oc:tooltip.analyzer=用于显示方块信息,比如它们的§f地址§7和§f组件名称§7。如果计算机未能正常关闭它也会显示使计算机崩溃的报错。
-oc:tooltip.apu=如果你只是需要一个额外的卡槽,这就是你需要的自带 GPU(或者集成图形处理器 IGP)的 CPU。[nl] 支持的组件:§f%s§7[nl] 最大分辨率:§f%sx%s§7[nl] 最高色深:§f%s§7[nl] 运算/tick:§f%s§7
-oc:tooltip.assembler=允许使用若干不同的电脑组件来组装机器人。
-oc:tooltip.cable=连接方块的廉价选择。
-oc:tooltip.capacitor=储能以备不时之需。能够非常快速地充电或放电。
-oc:tooltip.carpetedcapacitor=储能以备不时之需。能够非常快速地充电或放电。有羊或豹猫踩上去的时候就能充电。
-oc:tooltip.cardbase=正如其名,它是用来安装其它扩展卡的基本卡板。
-oc:tooltip.case=计算机机箱是构建计算机的基本方块,也是各种§f扩展卡§7,§f存储器§7以及§f硬盘§7的外壳。[nl] 格子:§f%s§7
-oc:tooltip.chamelium=3D打印的基本原材料。不要误吸:或造成失明和暂时失去意识。
-oc:tooltip.chameliumblock=整洁干净的玩意。对于彩色 3D 打印相当实用,或者只是拿它的整洁干净的色彩来装饰你的华丽的基地。
-oc:tooltip.charger=将电容器的能量传输给相邻机器人。传输效率取决于输入的§f红石信号§7强度,无信号意味着不给机器人充电,而最强信号则意味着全速给机器人充电。
-oc:tooltip.circuitboard=现在我们已经取得一些进展。可以通过蚀刻来得到印制电路板。
-oc:tooltip.controlunit=用来控制……控制东西……的单元。你需要这玩意儿来做 CPU。所以反正啦,这个非常重要。
-oc:tooltip.componentbus=这个扩展能让服务器同时与更多组件通讯,工作原理类似 CPU。[nl] 支持的组件:§f%s§7
-oc:tooltip.cpu=所有计算机最核心的组件,它的时钟频率有点不可靠,但是你考虑到它是靠便携日晷来运行的,还能指望什么呢?[nl] 支持组件:§f%s§7
-oc:tooltip.cpu.Architecture=架构:§f%s§7
-oc:tooltip.cuttingwire=用于将粘土块切割成电路板的形状。使用一次就会坏掉,这可能使得成为历来最低效的工具。
-oc:tooltip.datacard0=提供数种高级算法,例如散列、压缩和解压缩算法。
-oc:tooltip.datacard1=提供数种高级算法,例如散列、AES 加密、压缩和解压缩算法。
-oc:tooltip.datacard2=提供数种高级算法,例如散列、AES 加密、椭圆曲线加密、压缩和解压缩算法。
-oc:tooltip.debugcard=创造模式物品,它能让你更简易的操控世界来进行测试。请自己承担它带来的危险。
-oc:tooltip.debugger=用于在 OpenComputer 的内部网络格栅中输出调试信息。请在开发者指导下使用。
-oc:tooltip.diamondchip=一小粒正在发光的钻石。永远不会破镜重圆。
-oc:tooltip.disassembler=将物品分解成基础组件。§l警告§7:分解得到的物品会有 %s%% 的几率在分解过程中损坏!
-oc:tooltip.disk=用于制造持久存储设备的原始媒介材料。
-oc:tooltip.diskdrive.CC=§a支持§7 ComputerCraft 的软盘。
-oc:tooltip.diskdrive=用来读写软盘。可以给机器人安装使其可以插入软盘。
-oc:tooltip.diskdrivemountable=和普通软驱用途一样,但必须装载在机架里。
-oc:tooltip.diskusage=磁盘使用:%s/%s 字节
-oc:tooltip.diskmodemanaged=模式:管理
-oc:tooltip.diskmodeunmanaged=模式:不受管理
-oc:tooltip.drone=无人机是一种轻量而快速的侦查单位,自身拥有有限的载物空间。
-oc:tooltip.dronecase=这个外壳将会在组装机中组装出无人机。这个外壳可容纳少量组件,并内建末地石驱动的悬浮系统。
-oc:tooltip.eeporm=小型的可编程存储器,可存储电脑启动所用的BIOS。
-oc:tooltip.fakeendstone=几乎可以以假乱真,甚至更加轻盈!
-oc:tooltip.geolyzer=可以检测周围方块的硬度。这些信息对编写全息地图程序或检测矿物都有很大的帮助。
-oc:tooltip.graphicscard=用来改变屏幕上的显示内容。最高分辨率:§f%sx%s§7[nl] 最高色深:§f%s§7[nl] 运算/tick:§f%s§7
-oc:tooltip.hoverboots=跳得更高,摔得更深,走得更快。一切尽在 Hover Boots™,已获顶级认证。
-oc:tooltip.inkcartridge=用于重新填装3D打印机的墨水。因为某些原因这些墨水不必保留在打印机里。
-oc:tooltip.inkcartridgeempty=此墨盒经过深度干燥处理。用颜料重新装填,抑或弃置。看我脸色行事。
-oc:tooltip.internetcard=因特网卡可以让你发送HTTP请求以及使用货真价实的TCP套接字。
-oc:tooltip.interweb=恭喜,你赢得了一个因特网。你可以使用因特网卡来连接它。注意:不要水贴钓鱼
-oc:tooltip.ironnugget=颗粒状的铁,所以叫铁粒啦,蠢蠢的感觉……
-oc:tooltip.keyboard=可以连接屏幕来输入显示文本。
-oc:tooltip.hologram0=一个能通过电脑控制来投射出任何三维结构的全息投影仪.[nl] 分辨率:§f48x32x48§7 [nl] 最大显示规模:§f3x§7 [nl] 最高色深:§f黑白§7
-oc:tooltip.hologram1=使用电脑控制的高级全息投影仪。[nl] 分辨率:§f48x32x48§7 [nl] 最大显示规模:§f4x§7 [nl] 最高色深:§f三原色§7
-oc:tooltip.linkedcard=连接卡可以成对合成,并且它们只能与各自对应的连接卡交互。然而,它们之间的交互没有距离限制,甚至可以跨越不同的世界。但它们传递信息所需要的能量消耗不多不少。
-oc:tooltip.linkedcard_channel=§8频道:%s§7
-oc:tooltip.manual=包含你需要的关于 OpenComputer 的一切信息。还有更多。为此你只需要……§o请按R键继续§7。
-oc:tooltip.memory=电脑运行必备。内存越大,你就可以运行越复杂的程序。
-oc:tooltip.microchip=通常也管这种芯片叫集成电路。我也不知道为什么能和红石一起运行,但事实如此。
-oc:tooltip.microcontroller=单片机是被压缩到不能再压缩的电脑。它们更多是用于执行特殊任务,并只运行一个内建于EEPROM中的简单程序。[nl] §c不能和外置组件相连接。§7
-oc:tooltip.microcontrollercase=单片机基础组件。在组装机中为其添加各种组件并组装单片机。
-oc:tooltip.motionsensor=可以检测附近生物的动向。检测需要无遮挡物的环境。
-oc:tooltip.nanomachines=控制单元,同时还是一堆可以吸入的纳米机器(如果你愿意的话)。
-oc:tooltip.networkcard=允许通过其他方块(比如线缆)相连的远程计算机能够向彼此发送信息进行交互。
-oc:tooltip.poweracceptor=能量转换速度:§f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§fMJ§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§fCharge§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§fEU§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§fJoules§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§fRF§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§fCoulombs§7: §a%s:%s§7
-oc:tooltip.powerconverter=将其它模组的能量转化为本模组的内部能源形式。转换比:
-oc:tooltip.powerdistributor=在不同网络中分配能量。很实用于通过包含多个理论上独立子网络的转换器在系统中共享能量。
-oc:tooltip.present=……它随时为你的麻烦待命。打开此礼物将有机会获得 §kphat lewt§7![nl]§8在时机合适时,合成 OpenComputers 的物品。§7
-oc:tooltip.print.BeaconBase=§8可用作信标底座。
-oc:tooltip.print.LightValue=§8光强:%s。
-oc:tooltip.print.RedstoneLevel=§8红石信号强度:%s。
-oc:tooltip.printedcircuitboard=扩展卡、内存等组件的基础板。
-oc:tooltip.printer=利用变色物质和墨盒打印出用户自定义的形状。需要用电脑进行配置。不要让幼童接触。就是这样。
-oc:tooltip.raid=允许将三块硬盘组成一个大文件系统供所有与其连接的电脑使用。
-oc:tooltip.rawcircuitboard=能在支持原版熔炉配方的炉子中加工强化。
-oc:tooltip.redstone=能够在方块周围接收或发送红石信号。可以被与之相连的计算机控制。基本上就像一个外置红石卡。
-oc:tooltip.redstonecard.Charset=§a兼容§7 §fSimpleLogic§7。
-oc:tooltip.redstonecard.ProjectRed=§a兼容§7 §fProject Red§7。
-oc:tooltip.redstonecard.RedLogic=§a兼容§7 §fRedLogic§7。
-oc:tooltip.redstonecard.RedNet=§a兼容§7 §fRedNet§7。
-oc:tooltip.redstonecard.WirelessCBE=§a兼容§7 §f无线红石(ChickenBones)§7。
-oc:tooltip.redstonecard.WirelessSV=§a兼容§7 §f无线红石(SlimeVoid)§7。
-oc:tooltip.redstonecard=允许在计算机和机器人四周接收或发送红石信号。
-oc:tooltip.relay=可将不同网络连接在一起。仅信息可通过此设备传递,其它元件仍不可见。用法举例:可用于保持多个独立网络的通信。
-oc:tooltip.robot=和计算机不同,机器人能够移动并且像玩家那样与世界中的东西交互。然而,它们§o不能§r§7直接与外设进行交互!
-# The underscore makes sure this isn't hidden with the rest of the tooltip。
-oc:tooltip.robot_level=§f等级§7:§a%s§7。
-oc:tooltip.robot_storedenergy=§f存储能量§7:§a%s§7。
-oc:tooltip.screen=显示文本,运作需要机箱中的显卡。[nl] 最高分辨率:§f%sx%s§7[nl] 最高色深:§f%s§7
-oc:tooltip.server=这就是服务器,它与许多其它的服务器拥有相似功能,但这台服务器可以使用组件进行升级,就像升级机箱一样。它也可以放入服务器机架中运行。
-oc:tooltip.server.Components=已安装的组件:
-oc:tooltip.rack=它能装下四台服务器或者别的设备。
-oc:tooltip.tablet=一台平板电脑,为 Lua 新人准备。潜行时右击可强制关机。
-oc:tooltip.tabletcase=平板电脑的基础外壳。在组装机中添加组件以制造平板电脑。
-oc:tooltip.terminal=可以远程控制服务器,不过前提是你处于信号范围内。使用方法相同于显示屏与键盘. Shift 右击机架中的服务器可以绑定对应的终端。
-oc:tooltip.terminalserver=在工作范围内可与终端连接,以提供远程控制功能。内建有虚拟显示器和键盘。
-oc:tooltip.texturepicker=这个工具可以显示放块表面的描述,可用于3D打印定义中。完全不是材质名,完全不是。很抱歉先生,不是。
-oc:tooltip.tier=§8等级 %s
-oc:tooltip.netsplitter=作为动态连接器的存在。每个面的连接设定可通过扳手切换。红石信号可反相所有面的连接设定。
-oc:tooltip.toolong=按住 [§f%s§7] 显示详细物品信息。
-oc:tooltip.transistor=大多数电脑组件中最基础的元素。看上去有些扭曲,但它是有用的。
-oc:tooltip.transposer=可在相邻容器之间自动转移物品和液体。
-oc:tooltip.upgradeangel=允许机器人凭空放置方块,甚至是在没有任何依附的情况下。
-oc:tooltip.upgradebattery=增加机器人存储能量的上限,让其能够运作很长一段时间也不必充电。[nl] 电容:§f%s§7
-oc:tooltip.upgradechunkloader=如果机器人走进了一片森林,周围没有任何生物载入区块,那么它还能继续移动吗? 这个升级组件可以让你确定这点。它能让机器人所处的区块保持载入,但这会让能量不断地消耗。
-oc:tooltip.upgradecontainercard=卡容器组件可以让你方便随意的将卡装入机器人或从中移出。[nl] 最高等级:§f%s§7
-oc:tooltip.upgradecontainerupgrade=卡容器升级组件可以让你方便的将卡装入另一个卡容器或从中移出。[nl] 最高等级:§f%s§7
-oc:tooltip.upgradecrafting=能让机器人的物品栏左上角部分成为合成界面。物品必须在合成界面里排列整齐。
-oc:tooltip.upgradedatabase=能对物品信息进行分类,供其它组件稍后取用。[nl] 可支持条目数量:§f%s§7
-oc:tooltip.upgradeexperience=这个升级能让机器人在执行一些工作时获取经验并累积。它们拥有越多的累积经验,就能够存储越多的能量,越快的挖掘方块并且使用工具时拥有更高的效率。
-oc:tooltip.upgradegenerator=可以让机器人通过燃料充能。燃烧物品得到的发电量取决于燃料的等级。[nl] §f发电效率§7:§a%s%%§7
-oc:tooltip.upgradehover=这个升级组件可让机器人飞得更高而无需爬墙。[nl] 最大高度:§f%s§7
-oc:tooltip.upgradeinventory=这个升级组件为机器人提供了物品背包。如果没有这个升级,机器人将不能存储物品。
-oc:tooltip.upgradeinventorycontroller=这个升级组件可以控制机器人使其与外部容器互动,并能允许机器人将装备上的工具替换成其物品栏中的其它物品。
-oc:tooltip.upgrademf=能让适配器访问不与其相邻的方块。
-oc:tooltip.upgrademf.Linked=§f已连接§7
-oc:tooltip.upgrademf.Unlinked=§f没有连接§7
-oc:tooltip.upgradeleash=这个升级组件可让诸如无人机之类的设备绑在 Isaa——不好意思,*清清嗓子* 我刚才说错了。我只是被告知这原本是用来拴动物的绳子。可以拴很多动物,好奇怪啊。
-oc:tooltip.upgradenavigation=可以让机器人确认所处位置以及定位。定位地点即为用于合成此升级组件用到的地图的中心点。
-oc:tooltip.upgradepiston=这个升级十分有用。它能让机器人像活塞那样移动方块,但 §l不能§7 移动实体。
-oc:tooltip.upgradesign=允许机器人读写告示牌。
-oc:tooltip.upgradesolargenerator=可以让机器人在太阳光的照射下四处奔走。机器人顶部需要无任何方块阻挡。产能速度是斯特林引擎的 %s%%。
-oc:tooltip.upgradetank=为你的机器人装上一个可存储流体的水箱。如果没有升级此功能,你的机器人将无法在内部存储流体。
-oc:tooltip.upgradetankcontroller=这个升级能让你的机器人与外界水箱交互,向其传输流体。
-oc:tooltip.upgradetractorbeam=十分先进的高科技,别名“物品磁铁”。它能让机器人在任何地方捡起3格范围内的掉落物。
-oc:tooltip.waypoint=为安装有导航升级的设备提供参考点。
-oc:tooltip.wirelessnetworkcard=允许在发送正常信息的情况下发送无线网络信息。请确保已设置好 §f信号强度§7 否则不会发出信息。越高的信号强度会导致越高的能量消耗。
-oc:tooltip.worldsensorcard=可读取关于世界的各种信息,例如重力加速度和是否有可供呼吸的大气。使用风险自负。制造商对由卡片输出结果造成的损失不承担任何法律责任。我们不仅有律师,还有现金。不要试图告倒我们。
-oc:tooltip.wrench=螺丝刀和扳手混合体,新手友好,高手毁灭者。
-
-#Achievements
-achievement.oc.adapter=Plug In Baby
-achievement.oc.adapter.desc=和其它 MOD 的方块(甚至是原版 Minecraft 方块)进行互动!
-achievement.oc.assembler=完美
-achievement.oc.assembler.desc=是时候征服世界了!
-achievement.oc.cable=并不是脏兮兮的电线
-achievement.oc.cable.desc=搭配权威认证的反 SCP-229 科技
-achievement.oc.capacitor=本设备含电池
-achievement.oc.capacitor.desc=不可能阻止它
-achievement.oc.card=我们接受卡片
-achievement.oc.card.desc=这是为方便您的使用。我们保证这不是别有用心。
-achievement.oc.case=以备后患
-achievement.oc.case.desc=Because cuboid towers are the best.
-achievement.oc.charger=那就开始做吧!
-achievement.oc.charger.desc=开始充——等等!又忘记红石信号了。
-achievement.oc.chip=全是些小东西
-achievement.oc.chip.desc=曾经真空管也是这样的。
-achievement.oc.cpu=超频
-achievement.oc.cpu.desc=是时候好好利用这些计算循环了
-achievement.oc.disassembler=销毁!
-achievement.oc.disassembler.desc=当你发现你的想法很美好,但现实其实很残酷的时候,就用这个吧。
-achievement.oc.diskDrive=Roundabout
-achievement.oc.diskDrive.desc=Inferior capacity but such delicious sound.
-achievement.oc.drone=啊!飞走了!
-achievement.oc.drone.desc=冷静冷静,直接用核弹让他们在轨道上瞬间爆炸
-achievement.oc.eeprom=每台电脑
-achievement.oc.eeprom.desc=仅限一个,就是这样。这是用来决定最终启动顺序的,明白吗!?
-achievement.oc.floppy=The One Ri- Disk
-achievement.oc.floppy.desc=不要与flappy混淆。[nl]注:软盘英文为floppy disk
-achievement.oc.geolyzer=深入地心
-achievement.oc.geolyzer.desc=It has extraordinary qualities.
-achievement.oc.graphicsCard=LastGen
-achievement.oc.graphicsCard.desc=The way it's meant to be... uh... rendered. Yeah. That.
-achievement.oc.hdd=Hot Dog Dealer(热狗推销员)
-achievement.oc.hdd.desc=等等我不是那个意思。让我想想,好像想起来什么意思了……
-achievement.oc.hologram=下一个次元
-achievement.oc.hologram.desc=因为 2D 很无聊啊。或者本来就这样?
-achievement.oc.keyboard=吸尘器 3000 型
-achievement.oc.keyboard.desc=强烈建议使用时保持将其翻过来并持续摇晃的习惯,以清理其中异物。
-achievement.oc.microcontroller=Little Sisters
-achievement.oc.microcontroller.desc=计算机的小妹妹哦
-achievement.oc.motionSensor=Got the Moves
-achievement.oc.motionSensor.desc=Like Steve Swagger.
-achievement.oc.networkCard=现在我们在聊天了!
-achievement.oc.networkCard.desc=Keep in touch with those distant relatives via transitive relations.
-achievement.oc.openOS=启动
-achievement.oc.openOS.desc=One OS to - wait, I used that one already? Dang.
-achievement.oc.powerDistributor=分享即关怀
-achievement.oc.powerDistributor.desc=当你在平衡供电时需要帮助的时候。
-achievement.oc.rack=Dat Rack
-achievement.oc.rack.desc=我不知道你想歪到哪里去了,我已经说得很明白了,就是服务器架。
-achievement.oc.raid=LFG
-achievement.oc.raid.desc=Heroic plzkthx.
-achievement.oc.ram=随机存取存储器
-achievement.oc.ram.desc=恭喜,你的操作完全正确。
-achievement.oc.redstoneCard=联系
-achievement.oc.redstoneCard.desc=模拟信号时间到。
-achievement.oc.redstoneIO=The Outsider
-achievement.oc.redstoneIO.desc=将红石信号传播到你需要的地方!
-achievement.oc.robot=Beep Boop
-achievement.oc.robot.desc=灭绝!
-achievement.oc.screen=试过反复开关这屏幕没?
-achievement.oc.screen.desc=真没有。毕竟红石信号就可以开关这屏幕了。
-achievement.oc.server=专用
-achievement.oc.server.desc=云服务,现已正式推出。
-achievement.oc.switch=复杂拓扑学
-achievement.oc.switch.desc=远离易碎货物,因为包裹可能会掉下来。
-achievement.oc.tablet=不要吸入
-achievement.oc.tablet.desc=同时请远离儿童,以避免不必要的信用卡过度透支。
-achievement.oc.transistor=Tell Red I said "Hi."
-achievement.oc.transistor.desc=制作一个晶体管然后让它工作。然后听录音带。不用谢我。
-achievement.oc.wirelessNetworkCard=信号
-achievement.oc.wirelessNetworkCard.desc=是时候让数据包踏遍每一个角落了。
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code。
-death.attack.oc.nanomachinesOverload.1=%s 过于贪婪。
-death.attack.oc.nanomachinesOverload.2=%s 神经断裂。
-death.attack.oc.nanomachinesOverload.3=%s 的纳米机器失控暴走了。
-death.attack.oc.nanomachinesHungry.1=%s 被纳米机器吃掉了。
-death.attack.oc.nanomachinesHungry.2=%s 忘记喂饱纳米机器了。
-death.attack.oc.nanomachinesHungry.3=%s 已被分解吸收了。
-
-# NEI Integration
-nei.options.inventory.oredict=显示矿物词典名
-nei.options.inventory.oredict.true=是
-nei.options.inventory.oredict.false=否
-nei.usage.oc.Manual=打开手册
-
-# Waila Integration
-option.oc.address=地址
-option.oc.componentName=组件名
-option.oc.energy=能量
diff --git a/src/main/resources/assets/opencomputers/lang/zh_TW.lang b/src/main/resources/assets/opencomputers/lang/zh_TW.lang
deleted file mode 100644
index 0f7717bab8..0000000000
--- a/src/main/resources/assets/opencomputers/lang/zh_TW.lang
+++ /dev/null
@@ -1,468 +0,0 @@
-# OpenComputer
-# This is the Traditional Chinese file for localizations. by mymag
-
-# Blocks
-tile.oc.accesspoint.name=§c橋接器§7
-tile.oc.adapter.name=連接器
-tile.oc.assembler.name=機器組裝台
-tile.oc.cable.name=線纜
-tile.oc.capacitor.name=電容
-tile.oc.case1.name=基礎電腦機殼
-tile.oc.case2.name=高級電腦機殼
-tile.oc.case3.name=超級電腦機殼
-tile.oc.casecreative.name=電腦機殼(創造模式)
-tile.oc.chameliumblock.name=變色凝膠磚
-tile.oc.charger.name=充電器
-tile.oc.disassembler.name=拆解機
-tile.oc.diskdrive.name=磁碟機
-tile.oc.endstone.name=終界石
-tile.oc.geolyzer.name=硬度分析機
-tile.oc.hologram1.name=全息投影機 (1級)
-tile.oc.hologram2.name=全息投影機 (2級)
-tile.oc.keyboard.name=鍵盤
-tile.oc.microcontroller.name=微型控制器
-tile.oc.motionsensor.name=動作感應器
-tile.oc.netsplitter.name=網路路由器
-tile.oc.powerconverter.name=能源轉換器
-tile.oc.powerdistributor.name=能源分配器
-tile.oc.print.name=3D 列印
-tile.oc.printer.name=3D 列印機
-tile.oc.raid.name=磁碟陣列機(NAS)
-tile.oc.redstone.name=紅石I/O
-tile.oc.relay.name=中繼器
-tile.oc.robot.name=機器人
-tile.oc.robotafterimage.name=機器人
-tile.oc.screen1.name=黑白電腦顯示器
-tile.oc.screen2.name=彩色電腦顯示器
-tile.oc.screen3.name=高畫質電腦顯示器
-tile.oc.rack.name=伺服器機架
-tile.oc.switch.name=路由器
-tile.oc.transposer.name=差轉機
-tile.oc.waypoint.name=路點
-
-# Items
-item.oc.abstractbusCard.name=抽象的介面卡
-item.oc.acid.name=蝕刻藥水
-item.oc.alu.name=算邏運算單元(ALU)
-item.oc.analyzer.name=分析器
-item.oc.apu0.name=加速處理單元 (APU) (1級)
-item.oc.apu1.name=加速處理單元 (APU) (2級)
-item.oc.apu2.name=加速處理單元 (APU) (創造模式)
-item.oc.arrowkeys.name=方向鍵
-item.oc.buttongroup.name=按鈕組
-item.oc.cardbase.name=主板
-item.oc.chamelium.name=變色凝膠
-item.oc.circuitboard.name=電路板
-item.oc.componentbus0.name=基礎排線
-item.oc.componentbus1.name=高級排線
-item.oc.componentbus2.name=超級排線
-item.oc.controlunit.name=控制單元 (CU)
-item.oc.cpu0.name=中央處理器 (CPU) (1級)
-item.oc.cpu1.name=中央處理器 (CPU) (2級)
-item.oc.cpu2.name=中央處理器 (CPU) (3級)
-item.oc.cuttingwire.name=切割線
-item.oc.datacard0.name=資料卡 (1級)
-item.oc.datacard1.name=資料卡 (2級)
-item.oc.datacard2.name=資料卡 (3級)
-item.oc.debugcard.name=除錯卡
-item.oc.debugger.name=網路除錯卡
-item.oc.disk.name=磁碟
-item.oc.drone.name=無人機
-item.oc.dronecase0.name=無人機外殼 (1級)
-item.oc.dronecase1.name=無人機外殼 (2級)
-item.oc.dronecase3.name=無人機外殼 (創造模式)
-item.oc.eeprom.name=電子抹除式可複寫唯讀記憶體(EEPROM)
-item.oc.floppydisk.name=磁碟片
-item.oc.graphicscard0.name=顯示卡
-item.oc.graphicscard1.name=彩色顯示卡
-item.oc.graphicscard2.name=高畫質顯示卡
-item.oc.harddiskdrive0.name=硬碟機 (1級)
-item.oc.harddiskdrive1.name=硬碟機 (2級)
-item.oc.harddiskdrive2.name=硬碟機 (3級)
-item.oc.hoverboots.name=懸停靴
-item.oc.inkcartridge.name=墨水匣
-item.oc.inkcartridgeempty.name=墨水匣(空)
-item.oc.internetcard.name=上網卡
-item.oc.interweb.name=因特網
-item.oc.ironnugget.name=鐵粒
-item.oc.linkedcard.name=連結卡
-item.oc.manual.name=開放式電腦手冊
-item.oc.memory0.name=記憶卡 (1級)
-item.oc.memory1.name=記憶卡 (1.5級)
-item.oc.memory2.name=記憶卡 (2級)
-item.oc.memory3.name=記憶卡 (2.5級)
-item.oc.memory4.name=記憶卡 (3級)
-item.oc.memory5.name=記憶卡 (3.5級)
-item.oc.microchip0.name=微晶片 (1級)
-item.oc.microchip1.name=微晶片 (2級)
-item.oc.microchip2.name=微晶片 (3級)
-item.oc.microcontrollercase0.name=微控制器外殼 (Tier 1)
-item.oc.microcontrollercase1.name=微控制器外殼 (Tier 2)
-item.oc.microcontrollercase3.name=微控制器外殼 (Creative)
-item.oc.nanomachines.name=納米機器
-item.oc.networkcard.name=網路卡
-item.oc.numpad.name=數字鍵盤
-item.oc.present.name=一個小東西...
-item.oc.printedcircuitboard.name=印刷電路板(PCB)
-item.oc.rawcircuitboard.name=電路板材料
-item.oc.redstonecard0.name=紅石卡 (1級)
-item.oc.redstonecard1.name=紅石卡 (2級)
-item.oc.server0.name=伺服器 (1級)
-item.oc.server1.name=伺服器 (2級)
-item.oc.server2.name=伺服器 (3級)
-item.oc.server3.name=伺服器 (創造模式)
-item.oc.tablet.name=平板電腦
-item.oc.tabletcase0.name=平板電腦保護套 (1級)
-item.oc.tabletcase1.name=平板電腦保護套 (2級)
-item.oc.tabletcase3.name=平板電腦保護套 (創造模式)
-item.oc.terminal.name=遠端終端機
-item.oc.texturepicker.name=紋理選擇器
-item.oc.transistor.name=電晶體
-item.oc.upgradeangel.name=天使升級
-item.oc.upgradebattery0.name=電池升級 (1級)
-item.oc.upgradebattery1.name=電池升級 (2級)
-item.oc.upgradebattery2.name=電池升級 (3級)
-item.oc.upgradechunkloader.name=區塊載入器升級
-item.oc.upgradecontainercard0.name=卡片集裝箱 (1級)
-item.oc.upgradecontainercard1.name=卡片集裝箱 (2級)
-item.oc.upgradecontainercard2.name=卡片集裝箱 (3級)
-item.oc.upgradecontainerupgrade0.name=集裝箱升級 (1級)
-item.oc.upgradecontainerupgrade1.name=集裝箱升級 (2級)
-item.oc.upgradecontainerupgrade2.name=集裝箱升級 (3級)
-item.oc.upgradecrafting.name=合成升級
-item.oc.upgradedatabase0.name=資料庫升級 (1級)
-item.oc.upgradedatabase1.name=資料庫升級 (2級)
-item.oc.upgradedatabase2.name=資料庫升級 (3級)
-item.oc.upgradeexperience.name=經驗升級
-item.oc.upgradegenerator.name=發電機升級
-item.oc.upgradehover0.name=懸停升級 (1級)
-item.oc.upgradehover1.name=懸停升級 (2級)
-item.oc.upgradeinventory.name=物品欄升級
-item.oc.upgradeinventorycontroller.name=物品控制器升級
-item.oc.upgradeleash.name=皮帶升級
-item.oc.upgradenavigation.name=導航升級
-item.oc.upgradepiston.name=活塞升級
-item.oc.upgradesign.name=告示牌 I/O 升級
-item.oc.upgradesolargenerator.name=太陽能發電升級
-item.oc.upgradetank.name=水箱升級
-item.oc.upgradetankcontroller.name=高級水箱升級
-item.oc.upgradetractorbeam.name=牽引光束升級
-item.oc.wirelessnetworkcard0.name=無線網卡
-item.oc.wirelessnetworkcard1.name=無線網卡
-item.oc.worldsensorcard.name=世界傳感器卡
-item.oc.wrench.name=螺絲刀扳手
-
-# Entities
-entity.oc.drone.name=無人機
-
-# GUI
-oc:gui.Analyzer.Address=§6位址§f: %s
-oc:gui.Analyzer.AddressCopied=位址複製到剪貼簿.
-oc:gui.Analyzer.ChargerSpeed=§6充電速度§f: %s
-oc:gui.Analyzer.ComponentName=§6設備元件名稱§f: %s
-oc:gui.Analyzer.Components=§6連接元件的數量§f: %s
-oc:gui.Analyzer.CopyToClipboard=點擊複製到剪貼簿。
-oc:gui.Analyzer.LastError=§6上一個錯誤§f: %s
-oc:gui.Analyzer.RobotName=§6名字§f: %s
-oc:gui.Analyzer.RobotOwner=§6持有者§f: %s
-oc:gui.Analyzer.RobotXp=§6經驗值§f: %s
-oc:gui.Analyzer.StoredEnergy=§6儲存能量§f: %s
-oc:gui.Analyzer.TotalEnergy=§6總儲存能量§f: %s
-oc:gui.Analyzer.Users=§6使用者§f: %s
-oc:gui.Analyzer.WirelessStrength=§6信號強度§f: %s
-oc:gui.Assembler.Collect=收集機器人
-oc:gui.Assembler.Complexity=複雜性: %s/%s
-oc:gui.Assembler.InsertCase=裝入電腦機殼(CASE)
-oc:gui.Assembler.InsertCPU=裝入中央處理器(CPU)
-oc:gui.Assembler.InsertRAM=裝入一些記憶體(RAM)
-oc:gui.Assembler.Progress=進度: %s%% (%s)
-oc:gui.Assembler.Run=開始組裝機器人
-oc:gui.Assembler.Warnings=§e警告§7: 缺少某些建議的零組件
-oc:gui.Assembler.Warning.GraphicsCard=顯示卡
-oc:gui.Assembler.Warning.Inventory=物品欄升級組件
-oc:gui.Assembler.Warning.Keyboard=鍵盤
-oc:gui.Assembler.Warning.OS=開機(作業系統) 中等
-oc:gui.Assembler.Warning.Screen=螢幕
-oc:gui.Assembler.Warnings=§e警告§7: 缺少建議的零組件
-oc:gui.Chat.NewVersion=有新版本可用: %s
-oc:gui.Chat.TextureName=§7紋理名稱是 §a%s§f.
-oc:gui.Chat.WarningClassTransformer=There were §cerrors§f running the class transformer. Please report this, together with your (full!) FML §alatest.log§f/§afml-server-latest.log§f logfile, thank you!
-oc:gui.Chat.WarningFingerprint=§c警告§f - 指紋不符!預期 '§a%s§f' 但得到 '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.
-oc:gui.Chat.WarningLink=無法打開鏈接: %s
-oc:gui.Chat.WarningLuaFallback=本機 LUA 函式庫無法使用,電腦將無法維持狀態,他會重新啟動並且載入區塊
-oc:gui.Chat.WarningProjectRed=你正在使用的 Project: Red 模組與 OpenComputers 不相容. 請嘗試更新 Project: Red.
-oc:gui.Chat.WarningRecipes=There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.
-oc:gui.Chat.WarningSimpleComponent=An addon (yours?) using the §aSimpleComponent§f interface did §esomething wrong§f. Component logic could not be injected. Please check your log file for more information.
-oc:gui.Drive.Managed=受管
-oc:gui.Drive.Unmanaged=非受管
-oc:gui.Drive.Warning=§l警告§r: 切換模式會導致目前儲存在硬碟上的所有資料遺失!
-oc:gui.Error.ComponentOverflow=太多的元件連接到電腦上了
-oc:gui.Error.InternalError=內部錯誤,請查看日誌文件。這可能是一個錯誤。
-oc:gui.Error.NoCPU=電腦內沒有安裝中央處理器(CPU).
-oc:gui.Error.NoEnergy=沒有能源
-oc:gui.Error.NoRAM=電腦內沒有安裝記憶卡
-oc:gui.Error.OutOfMemory=記憶體不足
-oc:gui.Manual.Blocks=開放式電腦方塊
-oc:gui.Manual.Home=首頁
-oc:gui.Manual.Items=開放式電腦物品
-oc:gui.Manual.Warning.BlockMissing=方塊不存在
-oc:gui.Manual.Warning.ImageMissing=沒有找到圖片
-oc:gui.Manual.Warning.ItemMissing=物品不存在
-oc:gui.Manual.Warning.OreDictMissing=礦物字典不存在
-oc:gui.Raid.Warning=§4放入的硬碟機會清除硬碟資料.[nl] 移除硬碟機會刪除磁碟陣列機(NAS)資料.
-oc:gui.Robot.Power=能量
-oc:gui.Robot.TurnOff=關閉
-oc:gui.Robot.TurnOn=開啟
-oc:gui.Rack.None=無
-oc:gui.Rack.Back=背面
-oc:gui.Rack.Bottom=底部
-oc:gui.Rack.Left=左
-oc:gui.Rack.Right=右
-oc:gui.Rack.Top=上
-oc:gui.Switch.TransferRate=週期率
-oc:gui.Switch.PacketsPerCycle=封包 / 週期
-oc:gui.Switch.QueueSize=隊列大小
-oc:gui.Terminal.InvalidKey=按鍵無效時,最有可能另一端已經綁定到伺服器。
-oc:gui.Terminal.OutOfRange=沒訊號.
-
-# Containers
-oc:container.accesspoint=橋接器
-oc:container.adapter=連接器
-oc:container.case=電腦
-oc:container.charger=充電器
-oc:container.disassembler=拆解機
-oc:container.diskdrive=硬碟機
-oc:container.printer=印表機
-oc:container.raid=磁碟陣列機(NAS)
-oc:container.relay=中繼器
-oc:container.server=伺服器
-oc:container.rack=伺服器機架
-oc:container.switch=路由器
-oc:container.tabletwrapper=平板電腦
-
-# Keybinds
-key.clipboardPaste=貼上剪貼簿
-key.materialCosts=顯示材料成本
-
-# Item / Block Tooltips
-oc:tooltip.accesspoint=就像一個切換器,但它會接收無線封包並且轉換無線的封包變成有線的封包.
-oc:tooltip.abstractbuscard=允許與 §fStargateTech 2§7 抽象卡傳送與接收 LIP 封包.
-oc:tooltip.acid=一種有毒的假液相物質,通常只有某些海盜會使用它們.[nl]它的腐蝕特性令它非常完美地適用于蝕刻電路板的材料.
-oc:tooltip.adapter=用于控制非電腦組件的方塊,[nl]比如原版或者來自其他模組的方塊.
-oc:tooltip.alu=用來做算邏運算以免你親自代勞,[nl]它更勝任這份差事.
-oc:tooltip.analyzer=用于顯示方塊信息,比如它們的§f地址§7和§f組件名稱§7.[nl]如果計算機未能正常關閉它也會顯示使得計算機崩潰的報錯.
-oc:tooltip.apu=這是 CPU 組成 GPU (或 IGP)的一個處理器, 如果你需要額外的卡片插槽,他可以讓你減少一片顯示卡.[nl] 支援的零組件: §f%s§7[nl] 最大分辨率: §f%sx%s§7[nl] 最大顏色深度: §f%s§7[nl] 運作/tick: §f%s§7
-oc:tooltip.assembler=機器組裝台可以從不同的電腦零組件來組裝一台機器人。
-oc:tooltip.cable=連接方塊的廉價選擇.
-oc:tooltip.capacitor=儲能以備他用.[nl]能夠非常快速地充電放電.
-oc:tooltip.cardbase=正如其名,它是用來安裝其他擴展卡的基本卡板.
-oc:tooltip.case=計算機電腦機殼是構建計算機的基本方塊,[nl]也是各種§f介面卡§7,§f記憶體§7以及§f硬碟§7的外殼.[nl] 格子: §f%s§7
-oc:tooltip.chamelium=3D列印的原料. 不可吞食: 會導致失明與臨時性身體消失
-oc:tooltip.chameliumblock=乾淨清潔. 方便用於3D列印, 只是一個純色的乾淨方塊, 彩色方塊可以讓你發揮創意
-oc:tooltip.charger=將電容器的能量傳輸給相鄰機器人.[nl]傳輸效率取決于輸入的§f紅石信號§7強度,無信號意味著不給機器人充電,而最強信號則意味著全速給機器人充電.
-oc:tooltip.circuitboard=現在我們已經取得一些進展.[nl]可以通過蝕刻來得到印制板.
-oc:tooltip.controlunit=用來控制...控制東西...的單元.[nl]你需要這玩意兒來做CPU.所以反正啦,這個非常重要.
-oc:tooltip.componentbus=這個擴充套件能讓伺服器同時與更多組件通訊, 工作原理類似CPU.[nl] 支援的組件: §f%s§7.
-oc:tooltip.cpu=所有計算機最核心的組件,它的時鐘頻率有點不可靠,[nl]但是你考慮到它是靠便攜日晷來運行的你還能指望啥呢?
-oc:tooltip.cpu.architecture=架構: §f%s§7
-oc:tooltip.cuttingwire=用于將粘土塊切割成電路板的形狀.[nl]使用一次就會壞掉,這可能使得成為歷來最低效的工具.
-oc:tooltip.datacard0=提供了一些先進的演算法,如散列處理以及 deflate/inflate.
-oc:tooltip.datacard1=提供了一些先進的演算法,如散列處理, AES 加密 以及 deflate/inflate.
-oc:tooltip.datacard2=提供了一些先進的演算法,如散列處理, AES 加密, elliptic curve cryptography and deflate/inflate.
-oc:tooltip.debugcard=創造模式物品, 它能讓你更簡易的操控世界來進行測試. 請自己承擔它帶來的危險.
-oc:tooltip.debugger=可以使用輸出錯誤訊息到 OC's 網路. 只能使用在開發模式.
-oc:tooltip.disassembler=拆解還原成它原來的零組件 §l警告§7: 拆解物品過程中 %s%% 有可能破壞掉這些零組件!
-oc:tooltip.disk=用於制造持久存儲設備的原始媒介材料.
-oc:tooltip.diskdrive.cc=已經§a支持§7使用另一個電腦模組(ComputerCraft)的軟碟.
-oc:tooltip.diskdrive=用來讀寫軟碟.
-oc:tooltip.diskusage=磁碟使用量: %s/%s Byte
-oc:tooltip.diskmodemanaged=模式: 受管
-oc:tooltip.diskmodeunmanaged=模式: 非受管
-oc:tooltip.drone=無人機重量輕,速度快的偵察部隊,擁有有限的載貨空間。
-oc:tooltip.dronecase=這個外殼是用來建立無人機的組裝外殼。它有足夠的空間用於少量組件,並終界石供電懸浮。
-oc:tooltip.eeprom=非常小的程式化儲存裝置,可裝入電腦 BIOS 用來開機.
-oc:tooltip.fakeendstone=幾乎一樣好真實的東西,甚至模仿其floatiness!
-oc:tooltip.geolyzer=允許掃描周邊地區的方塊硬度,這個訊息可用於產生區域的全息圖,或用來檢測礦石是非常有用的.
-oc:tooltip.graphicscard=用來改變顯示器顯示內容.[nl]最高分辨率: §f%sx%s§7[nl] 最大色深: §f%s§7
-oc:tooltip.hoverboots=跳得更高, 跌幅更深, 走得更快. 這是一個全新專利的 懸停靴 (TM).
-oc:tooltip.inkcartridge=用於填充墨水的3D打印機。很神奇的原理,不必保留在印表機中。
-oc:tooltip.inkcartridgeempty=這個墨盒已經被吸乾。用染料填充它。或者把它扔掉。看看你是否在乎。
-oc:tooltip.internetcard=這個介面卡允許你發出 HTTP要求到真實的 TCP sockets.
-oc:tooltip.interweb=恭喜,你贏取了 (1) 因特網,你可以使用網路卡連接它,小心,不要餵食巨魔.
-oc:tooltip.ironnugget=顆粒狀的鐵,所以叫鐵粒啦,蠢蠢的感覺...
-oc:tooltip.keyboard=可以連接顯示器,能夠輸入顯示文本.
-oc:tooltip.hologram0=可以透過電腦進行控制以顯示任意像素體積的結構體.[nl] 解析度: §f48x32x48§7 [nl] 最大縮放: §f3x§7 [nl] 色深: §f單色§7
-oc:tooltip.hologram1=可以透過電腦進行控制以顯示任意像素體積的結構體.[nl] 解析度: §f48x32x48§7 [nl] 最大縮放: §f4x§7 [nl] 色深: §f三色§7
-oc:tooltip.linkedcard=這些都是製作成對的,而且只能與它的合作卡通訊,然而,它可以在任何距離,甚至是誇世界溝通,但是發送訊息的消耗的能量非常高.
-oc:tooltip.linkedcard_channel=§8頻道: %s§7
-oc:tooltip.manual=所有你需要知道開放式電腦模組的訊息都在裡面.而且他的需求非常便宜... §o請按 R 繼續§7.
-oc:tooltip.materialcosts=按著 [§f%s§7] 顯示材料成本.
-oc:tooltip.materials=需求材料:
-oc:tooltip.memory=電腦運行必備.[nl]記憶體越大,你就可以運行越復雜的程序.
-oc:tooltip.microchip=通常也管這種芯片叫集成電路.[nl]我也不知道為啥能和紅石一起運行,但事實如此啊.
-oc:tooltip.microcontroller=微控制器是一部小型電腦. 它的目的是在處理非常具體的任務, 只能執行儲存在 EEPROM 的單一獨立程式.[nl] §c無法連結外部零組件.§7
-oc:tooltip.microcontrollercase=微控制器的基本組件. 將其放入組裝機裡添加其他的零組件
-oc:tooltip.motionsensor=可以檢測到附近活物的移動,需要在視線內不能有阻擋物.
-oc:tooltip.nanomachines=如果你敢,插入控制單元與一組奈米機器
-oc:tooltip.networkcard=允許通過其他方塊(比如線纜)相連的遠程計算機能夠向彼此發送信息進行交互.
-oc:tooltip.poweracceptor=能源轉換速度: §f%s/t§7
-oc:tooltip.powerconverter.BuildCraft=§f建築模組minecraft焦耳(BC-MJ)§7: §a%s:%s§7
-oc:tooltip.powerconverter.Factorization=§f因式分解 (Charge)§7: §a%s:%s§7
-oc:tooltip.powerconverter.IndustrialCraft2=§f工業時代 EU(IC²-EU)§7: §a%s:%s§7
-oc:tooltip.powerconverter.Mekanism=§f通用機器焦耳(Joules)§7: §a%s:%s§7
-oc:tooltip.powerconverter.ThermalExpansion=§f熱能擴展RF(TE-RF)§7: §a%s:%s§7
-oc:tooltip.powerconverter.ResonantEngine=§f諧振引擎庫侖§7: §a%s:%s§7
-oc:tooltip.powerconverter=將其他模組的能量轉化為本模組的內部能源形式.轉換率:
-oc:tooltip.powerdistributor=在不同網絡中分配能量.[nl]用來通過包含多個理論上獨立的子網絡的轉換器在系統中共享能量時很實用.
-oc:tooltip.present=... for your troubles. Open this present for a chance to receive some §kphat lewt§7![nl]§8Craft OpenComputers items when the time is right for a chance to receive a present.§7
-oc:tooltip.print.BeaconBase=§8一盞燈的基座
-oc:tooltip.print.LightValue=§8發出的光: %s.
-oc:tooltip.print.RedstoneLevel=§8紅石輸出: %s.
-oc:tooltip.printedcircuitboard=基本的構建方塊用來裝入擴充卡與記憶體模組
-oc:tooltip.printer=允許使用玩家自定義的墨水匣 Chamelium 與 Ink Cartridges. 必須使用電腦來進行配置. 遠離小朋友
-oc:tooltip.raid=使用三個硬碟機然後連接電腦成為一個更大容量的資料儲存系統
-oc:tooltip.printedcircuitboard=擴展卡,記憶體等的基板.
-oc:tooltip.rawcircuitboard=能夠在熔爐或者類似爐子中加工強化成其他材料.
-oc:tooltip.redstone=能夠在方塊周圍接收以及發送紅石信號.[nl]可以被與之相連的計算機控制.基本上就像一個外置紅石卡.
-oc:tooltip.redstonecard.ProjectRed=已經§a支持§fProjectRed§7.
-oc:tooltip.redstonecard.RedLogic=已經§a支持§7§f紅石邏輯(RedLogic)§7中的紅石系統.
-oc:tooltip.redstonecard.RedNet=已經§a支援§7MFR中的§f紅石網絡(RedNet)§7.
-oc:tooltip.redstonecard.WirelessCBE=已經§a支援§f無線紅石 (ChickenBones)§7.
-oc:tooltip.redstonecard.WirelessSV=已經§a支援§f無線紅石 (SlimeVoid)§7.
-oc:tooltip.redstonecard=能夠在計算機和機器人四周接收以及發送紅石信號.
-oc:tooltip.robot=和計算機不同,機器人能夠移動并且像玩家那些與世界之中的東西交互.[nl]然而,它們§o不能§r§7直接與外設進行交互!
-# The underscore makes sure this isn't hidden with the rest of the tooltip.
-oc:tooltip.robot_level=§f等級§7: §a%s§7.
-oc:tooltip.robot_storedenergy=§f儲能§7: §a%s§7.
-oc:tooltip.screen=由電腦機殼內的顯示卡控制來顯示文字.[nl]最高分辨率: §f%sx%s§7[nl] 最大色深: §f%s§7
-oc:tooltip.server=這是一台伺服器, 他非常棒, 但是他可以使用元件去升級他功能就像電腦一樣. 他可以插入伺服器機架上執行.
-oc:tooltip.server.Components=安裝的元件:
-oc:tooltip.rack=提供安裝最多達四個伺服器。為每個伺服器提供了一個內置的虛擬鍵盤和螢幕元件,相當於一個遠程終端。
-oc:tooltip.switch=允許設備相互連接不同的網絡.[nl]僅能傳遞網絡信息,通過路由器方式設備并不互相可見.[nl]例如可以通過這種方式來建立獨立網絡但仍允許其使用網卡通訊.
-oc:tooltip.tablet=一台平板電腦, 可以在旅行中使用LUA. 使用潛行按鍵來啟動或是關閉他
-oc:tooltip.tabletcase=平板電腦的機殼,將它放置在機器組裝台內製作一台平板電腦
-oc:tooltip.terminal=允許遠程控制伺服器,只要你在它的範圍內。就像一個隨身型螢幕和鍵盤。按住Shift鍵並滑鼠右鍵單擊某個服務器的服務器機架終端綁定它。
-oc:tooltip.texturepicker=可以工具允許顯示方塊該面向的紋理描述, 主要用於3D印表機. 完全沒有紋理名字,沒了!
-oc:tooltip.tier=§8等級 %s
-oc:tooltip.netsplitter=作為一個動態連接器。每邊的連接可以通過用扳手擊中它進行切換。所有邊的連接可以通過應用紅石信號反轉。
-oc:tooltip.toolong=按住潛行鍵([§f%s§7])以查看詳細提示信息.
-oc:tooltip.transistor=在多數其他計算機的零件中都很基礎的元件.[nl]引腳有點彎了,但還能用。
-oc:tooltip.transposer=允許相鄰的箱子與液體容器之間的物品液體transferral
-oc:tooltip.upgradeangel=讓機器人能夠憑空放置方塊在任何地方,即使沒有參考點可以依附放置。
-oc:tooltip.upgradebattery=增加機器人可儲存的能量,讓它可以工作更長的時間不需要補充能量. [nl] 容量: §f%s§7
-oc:tooltip.upgradechunkloader=如果機器人在森林中移動,周圍沒有其他玩家,它真的會動嗎? 這個升級組件可以確保它持續地在作用中,它使區塊持續在載入狀態,但會不斷消耗能量,維持它。
-oc:tooltip.upgradecontainercard=這個集裝箱升級組件允許動態裝配機器人內的某個插卡. [nl] 最大等級: §f%s§7
-oc:tooltip.upgradecontainerupgrade=這個集裝箱升級組件允許動態裝配機器人內的某個升級組件 [nl] 最大等級: §f%s§7
-oc:tooltip.upgradecrafting=使得機器人能夠將其物品欄的左上區域作為合成網格來制做物品.[nl]物品欄內物品擺放必須與工作臺中一致.
-oc:tooltip.upgradedatabase=這個升級允許儲存用於檢索與其他組件的堆疊訊息.[nl] 支持的條目: §f%s§7
-oc:tooltip.upgradeexperience=這個升級組件,能夠讓機器人執行各種操作,累積更多的經驗,然後它會獲得更多的能量,更多的儲存空間,速度更快,它收割更有效率,也能使用工具。
-oc:tooltip.upgradegenerator=用來不斷地消耗燃料發電,燃燒物品并基于它們的燃燒值隨著時間推移產生電力.[nl] §f效率§7: §a%s%%§7。
-oc:tooltip.upgradehover=可以升級可以讓機器人飛離地面更高,而且不用爬牆.[nl] 最大高度: §f%s§7
-oc:tooltip.upgradeinventory=這個升級組件提供機器人一個物品放置的空間,沒有這個升級組件,機器人將不能再內部儲存任何物品。
-oc:tooltip.upgradeinventoryController=這個升級組件可以讓機器人更好的控制如何與外部互動物品,並且允許他交換或是裝備物品欄內的工具。
-oc:tooltip.upgradeleash=允許一些設備,如無人機, 來綁定 Isaa- excuse me... *chatter* My apologies. 我只是被告知這其實是用來綁住多種動物在木樁上.
-oc:tooltip.upgradenavigation=可以用來確定機器人的位置和方向。該位置是相對於被用來製作這個升級地圖的中心。
-oc:tooltip.upgradepiston=這個升級十分有用. 它能讓機器人像活塞那樣移動方塊, 但 §l不能§7 移動實體.
-oc:tooltip.upgradesign=允許讀取文字與寫入文字到告示牌
-oc:tooltip.upgradesolarGenerator=在移動中可以從陽光獲取能量. 機器人上方必須保持無遮蔽狀態才能. 產生能量 %s%% 速度的能量給引擎。
-oc:tooltip.upgradetank=為你的機器人裝上一個可存儲流體的水箱. 如果沒有升級此功能, 你的機器人將無法在內部存儲流體.
-oc:tooltip.upgradetankcontroller=這個升級能讓你的機器人與外界水箱交互, 向其傳輸流體.
-oc:tooltip.upgradetractorbeam=裝備機器人具有非常先進的技術,綽號"物品磁鐵"。它能夠拾取三個方塊內的任何地方。
-oc:tooltip.waypoint=提供一個參考點到與導航設備的升級。
-oc:tooltip.wirelessnetworkcard=允許在發送正常信息外無線發送網絡信息.[nl]請確保已設置好§f信號強度§7否則不會發出無線數據包。
-oc:tooltip.worldsensorcard=允許讀取世界訊息,比如重力,以及是否在大氣下,傳回結果.
-oc:tooltip.wrench=螺絲刀和扳手的混合體,這個工具是簡單易學,但很難掌握。
-
-#Achievements
-achievement.oc.adapter=插上寶寶
-achievement.oc.adapter.desc=Interact with blocks from other mods and even vanilla Minecraft!
-achievement.oc.assembler=美妙
-achievement.oc.assembler.desc=Time to take over the world!
-achievement.oc.cable=不是一個骯髒的電線
-achievement.oc.cable.desc=With patented anti-cable-spaghetti technology.
-achievement.oc.capacitor=包括電池
-achievement.oc.capacitor.desc=You cannot stop it.
-achievement.oc.card=我們接受信用卡
-achievement.oc.card.desc=For your convenience. No ulterior motive, promise.
-achievement.oc.case=出現故障時
-achievement.oc.case.desc=Because cuboid towers are the best.
-achievement.oc.charger=好吧,讓我們做到這一點
-achievement.oc.charger.desc=Chaaaaaaaaaarg- dang, forgot the redstone signal again.
-achievement.oc.chip=所有小事
-achievement.oc.chip.desc=Because vacuum tubes are so yesteryear.
-achievement.oc.cpu=超頻
-achievement.oc.cpu.desc=Time to make good use of those computing cycles.
-achievement.oc.disassembler=從頭開始
-achievement.oc.disassembler.desc=In case one of your brilliant ideas turns out to be not that brilliant after all.
-achievement.oc.diskDrive=環狀交叉路
-achievement.oc.diskDrive.desc=Inferior capacity but such delicious sound.
-achievement.oc.drone=飛走
-achievement.oc.drone.desc=Keep calm and nuke it from orbit.
-achievement.oc.eeprom=只能有1
-achievement.oc.eeprom.desc=Per computer, that is. For deterministic boot order, you know?
-achievement.oc.floppy=在一個RI-磁碟
-achievement.oc.floppy.desc=Not to be confused with Flappy.
-achievement.oc.geolyzer=腳踏實地
-achievement.oc.geolyzer.desc=It has extraordinary qualities.
-achievement.oc.graphicsCard=LastGen
-achievement.oc.graphicsCard.desc=The way it's meant to be... uh... rendered. Yeah. That.
-achievement.oc.hdd=熱狗經銷商
-achievement.oc.hdd.desc=No wait, that's not what that meant. Hang on, almost got it...
-achievement.oc.hologram=下一個維度
-achievement.oc.hologram.desc=Because 2D is boring. Or is it?
-achievement.oc.keyboard=DirtCatcher3000
-achievement.oc.keyboard.desc=It is highly recommended to resist the urge to flip them around and shake them.
-achievement.oc.microcontroller=小妹妹
-achievement.oc.microcontroller.desc=The small sibling of computers.
-achievement.oc.motionSensor=能動
-achievement.oc.motionSensor.desc=Like Steve Swagger.
-achievement.oc.networkCard=現在我們談論!
-achievement.oc.networkCard.desc=Keep in touch with those distant relatives via transitive relations.
-achievement.oc.openOS=開機
-achievement.oc.openOS.desc=One OS to - wait, I used that one already? Dang.
-achievement.oc.powerDistributor=共享是關懷
-achievement.oc.powerDistributor.desc=When you need some help balancing all that power.
-achievement.oc.rack=Dat Rack
-achievement.oc.rack.desc=I don't know what you're thinking of, I clearly meant the server rack.
-achievement.oc.raid=LFG
-achievement.oc.raid.desc=Heroic plzkthx.
-achievement.oc.ram=隨機存取存儲器
-achievement.oc.ram.desc=Congratulations, you're Doin' It Right.
-achievement.oc.redstoneCard=聯繫
-achievement.oc.redstoneCard.desc=Time to go analog.
-achievement.oc.redstoneIO=局外人
-achievement.oc.redstoneIO.desc=Taking redstone signals where you want them.
-achievement.oc.robot=嗶布普
-achievement.oc.robot.desc=EXTERMINATE!
-achievement.oc.screen=Have you tried turning it off and on again?
-achievement.oc.screen.desc=No seriously. A redstone pulse can toggle a screen's power, after all.
-achievement.oc.server=專用
-achievement.oc.server.desc=雲服務,我們來了。
-achievement.oc.switch=複雜的拓撲
-achievement.oc.switch.desc=避免易碎物品因遺失資料的可能性。
-achievement.oc.tablet=不要嚥下
-achievement.oc.tablet.desc=Also keep away from small children to avoid unexpected overdrawing of your credit card.
-achievement.oc.transistor=告訴紅石說:“你好。”
-achievement.oc.transistor.desc=Create a Transistor to get started. Then listen to the soundtrack. No need to thank me.
-achievement.oc.wirelessNetworkCard=信號
-achievement.oc.wirelessNetworkCard.desc=Time to go where no packet has gone before.
-
-# Death messages. Note that the number of entries here must match the number
-# set in the actual damage source in code.
-death.attack.oc.nanomachinesOverload.1=%s 獲得貪婪稱號。
-death.attack.oc.nanomachinesOverload.2=%s 神經衰弱。
-death.attack.oc.nanomachinesOverload.3=奈米機器 %s 失去控制
-death.attack.oc.nanomachinesHungry.1=%s 被奈米機器吃掉
-death.attack.oc.nanomachinesHungry.2=%s 沒有定時餵食奈米機器
-death.attack.oc.nanomachinesHungry.3=%s 已被消化。
-
-# NEI Integration
-nei.options.inventory.oredict=顯示礦物字典名稱
-nei.options.inventory.oredict.true=真
-nei.options.inventory.oredict.false=假
-nei.usage.oc.Manual=打開手冊
-
-# Waila Integration
-option.oc.address=位址
-option.oc.componentName=組件名稱
-option.oc.energy=能源
diff --git a/src/main/resources/assets/opencomputers/lang/zh_cn.json b/src/main/resources/assets/opencomputers/lang/zh_cn.json
new file mode 100644
index 0000000000..7d07804ac0
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/zh_cn.json
@@ -0,0 +1,454 @@
+{
+ "tile.oc.adapter": "适配器",
+ "tile.oc.assembler": "装配器",
+ "tile.oc.cable": "线缆",
+ "tile.oc.capacitor": "电容",
+ "tile.oc.carpetedcapacitor": "踩踏发电电容",
+ "tile.oc.case1": "基础机箱",
+ "tile.oc.case2": "高级机箱",
+ "tile.oc.case3": "超级机箱",
+ "tile.oc.casecreative": "创造模式机箱",
+ "tile.oc.chameliumblock": "变色块",
+ "tile.oc.charger": "充电器",
+ "tile.oc.disassembler": "拆解器",
+ "tile.oc.diskdrive": "软盘驱动器",
+ "tile.oc.endstone": "末地石",
+ "tile.oc.geolyzer": "地质分析仪",
+ "tile.oc.hologram1": "基础全息地图投影仪",
+ "tile.oc.hologram2": "高级全息地图投影仪",
+ "tile.oc.keyboard": "键盘",
+ "tile.oc.microcontroller": "单片机",
+ "tile.oc.motionsensor": "运动传感器",
+ "tile.oc.netsplitter": "网络分配器",
+ "tile.oc.powerconverter": "能量转换器",
+ "tile.oc.powerdistributor": "能量分配器",
+ "tile.oc.print": "3D 打印",
+ "tile.oc.printer": "3D 打印机",
+ "tile.oc.raid": "Raid磁盘阵列",
+ "tile.oc.redstone": "红石 I/O 端口",
+ "tile.oc.relay": "中继器",
+ "tile.oc.robot": "机器人",
+ "tile.oc.robotafterimage": "机器人",
+ "tile.oc.screen1": "基础显示屏",
+ "tile.oc.screen2": "高级显示屏",
+ "tile.oc.screen3": "超级显示屏",
+ "tile.oc.rack": "机架",
+ "tile.oc.transposer": "转运器",
+ "tile.oc.waypoint": "路径点",
+ "item.oc.abstractbuscard": "抽象类总线卡",
+ "item.oc.acid": "酸液",
+ "item.oc.alu": "算术逻辑单元(ALU)",
+ "item.oc.analyzer": "分析器",
+ "item.oc.apu0": "高级加速运算单元(APU)",
+ "item.oc.apu1": "超级加速运算单元(APU)",
+ "item.oc.apu2": "创造加速运算单元(APU)",
+ "item.oc.arrowkeys": "方向键",
+ "item.oc.buttongroup": "按钮组",
+ "item.oc.cardbase": "基板",
+ "item.oc.chamelium": "变色材料",
+ "item.oc.circuitboard": "电路板",
+ "item.oc.componentbus0": "基础组件总线",
+ "item.oc.componentbus1": "高级组件总线",
+ "item.oc.componentbus2": "超级组件总线",
+ "item.oc.componentbus3": "创造模式组件总线",
+ "item.oc.controlunit": "控制单元(CU)",
+ "item.oc.cpu0": "基础中央处理器(CPU)",
+ "item.oc.cpu1": "高级中央处理器(CPU)",
+ "item.oc.cpu2": "超级中央处理器(CPU)",
+ "item.oc.cuttingwire": "切割线",
+ "item.oc.datacard0": "基础数据卡",
+ "item.oc.datacard1": "高级数据卡",
+ "item.oc.datacard2": "超级数据卡",
+ "item.oc.debugcard": "调试卡",
+ "item.oc.debugger": "网络调试器",
+ "item.oc.diamondchip": "钻石芯片",
+ "item.oc.disk": "磁碟",
+ "item.oc.diskdrivemountable": "可挂载软盘驱动器",
+ "item.oc.drone": "无人机",
+ "item.oc.dronecase0": "基础无人机外壳",
+ "item.oc.dronecase1": "高级无人机外壳",
+ "item.oc.dronecase3": "创造无人机外壳",
+ "item.oc.eeprom": "EEPROM",
+ "item.oc.floppydisk": "软盘",
+ "item.oc.GraphicsCard0": "基础显卡",
+ "item.oc.GraphicsCard1": "高级显卡",
+ "item.oc.GraphicsCard2": "超级显卡",
+ "item.oc.HardDiskDrive0": "基础磁盘驱动器",
+ "item.oc.HardDiskDrive1": "高级磁盘驱动器",
+ "item.oc.HardDiskDrive2": "超级磁盘驱动器",
+ "item.oc.hoverBoots": "悬浮靴",
+ "item.oc.inkcartridge": "墨盒",
+ "item.oc.inkcartridgeempty": "空墨盒",
+ "item.oc.internetcard": "因特网卡",
+ "item.oc.Interweb": "因特网",
+ "item.oc.ironnugget": "铁粒",
+ "item.oc.linkedcard": "连接卡",
+ "item.oc.manual": "开放式电脑使用手册",
+ "item.oc.memory0": "内存条-T1",
+ "item.oc.memory1": "内存条-T1.5",
+ "item.oc.memory2": "内存条-T2",
+ "item.oc.memory3": "内存条-T2.5",
+ "item.oc.memory4": "内存条-T3",
+ "item.oc.memory5": "内存条-T3.5",
+ "item.oc.microchip0": "简易微芯片",
+ "item.oc.microchip1": "高级微芯片",
+ "item.oc.microchip2": "超级微芯片",
+ "item.oc.microcontrollercase0": "基础单片机外壳",
+ "item.oc.microcontrollercase1": "高级单片机外壳",
+ "item.oc.microcontrollercase3": "创造单片机外壳",
+ "item.oc.nanomachines": "纳米机器",
+ "item.oc.networkcard": "网卡",
+ "item.oc.numpad": "数字键盘",
+ "item.oc.present": "一点小礼物……",
+ "item.oc.printedcircuitboard": "印刷电路板(PCB)",
+ "item.oc.rawcircuitboard": "未加工电路板",
+ "item.oc.redstonecard0": "基础红石卡",
+ "item.oc.redstonecard1": "高级红石卡",
+ "item.oc.server0": "基础服务器",
+ "item.oc.server1": "高级服务器",
+ "item.oc.server2": "超级服务器",
+ "item.oc.server3": "创造模式服务器",
+ "item.oc.tablet": "平板电脑",
+ "item.oc.tabletcase0": "基础平板电脑外壳",
+ "item.oc.tabletcase1": "高级平板电脑外壳",
+ "item.oc.tabletcase3": "创造模式平板电脑外壳",
+ "item.oc.terminal": "终端",
+ "item.oc.terminalserver": "终端服务器",
+ "item.oc.texturepicker": "纹理选择器",
+ "item.oc.transistor": "晶体管",
+ "item.oc.upgradeangel": "天使方块升级",
+ "item.oc.upgradebattery0": "基础电池升级",
+ "item.oc.upgradebattery1": "高级电池升级",
+ "item.oc.upgradebattery2": "超级电池升级",
+ "item.oc.upgradechunkloader": "区块载入升级",
+ "item.oc.upgradecontainercard0": "基础卡槽",
+ "item.oc.upgradecontainercard1": "高级卡槽",
+ "item.oc.upgradecontainercard2": "超级卡槽",
+ "item.oc.upgradecontainerupgrade0": "基础升级组件容器",
+ "item.oc.upgradecontainerupgrade1": "高级升级组件容器",
+ "item.oc.upgradecontainerupgrade2": "超级升级组件容器",
+ "item.oc.upgradecrafting": "合成升级",
+ "item.oc.upgradedatabase0": "基础数据库升级",
+ "item.oc.upgradedatabase1": "高级数据库升级",
+ "item.oc.upgradedatabase2": "超级数据库升级",
+ "item.oc.upgradeexperience": "经验升级",
+ "item.oc.upgradegenerator": "发电机升级",
+ "item.oc.upgradehover0": "基础悬浮升级",
+ "item.oc.upgradehover1": "高级悬浮升级",
+ "item.oc.upgradeinventory": "物品栏升级",
+ "item.oc.upgradeinventorycontroller": "物品栏控制器升级",
+ "item.oc.upgradeleash": "缰绳升级",
+ "item.oc.upgrademf": "MFU",
+ "item.oc.upgradenavigation": "导航升级",
+ "item.oc.upgradepiston": "活塞升级",
+ "item.oc.upgradesign": "告示牌读写升级",
+ "item.oc.upgradesolargenerator": "太阳能发电机升级",
+ "item.oc.upgradetank": "水箱升级",
+ "item.oc.upgradetankcontroller": "储罐升级",
+ "item.oc.upgradetractorbeam": "牵引光束升级",
+ "item.oc.upgradetrading": "交易升级",
+ "item.oc.wirelessnetworkcard0": "基础无线网卡",
+ "item.oc.wirelessnetworkcard1": "高级无线网卡",
+ "item.oc.worldsensorcard": "世界传感器卡",
+ "item.oc.wrench": "螺丝刀扳手",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.Drone": "无人机",
+ "oc:gui.Analyzer.Address": "§6地址§f:%s",
+ "oc:gui.Analyzer.AddressCopied": "地址已复制到剪贴板。",
+ "oc:gui.Analyzer.ChargerSpeed": "§6充电速度§f:%s",
+ "oc:gui.Analyzer.ComponentName": "§6组件名§f:%s",
+ "oc:gui.Analyzer.Components": "§6已连接组件的数量§f:%s",
+ "oc:gui.Analyzer.CopyToClipboard": "点击以复制到剪贴板。",
+ "oc:gui.Analyzer.LastError": "§6上一个错误§f:%s",
+ "oc:gui.Analyzer.RobotName": "§6名称§f:%s",
+ "oc:gui.Analyzer.RobotOwner": "§6主人§f:%s",
+ "oc:gui.Analyzer.RobotXp": "§6经验§f:%s(等级 %s)",
+ "oc:gui.Analyzer.StoredEnergy": "§6存储能量§f:%s",
+ "oc:gui.Analyzer.TotalEnergy": "§6存储能量上限§f:%s",
+ "oc:gui.Analyzer.Users": "§6用户§f:%s",
+ "oc:gui.Analyzer.WirelessStrength": "§6信号强度§f:%s",
+ "oc:gui.Assembler.Collect": "收集输出",
+ "oc:gui.Assembler.Complexity": "复杂度:%s/%s",
+ "oc:gui.Assembler.InsertCase": "插入一个机箱",
+ "oc:gui.Assembler.InsertCPU": "插入一个CPU",
+ "oc:gui.Assembler.InsertRAM": "插入一些存储器",
+ "oc:gui.Assembler.Progress": "进度:%s%%(%s)",
+ "oc:gui.Assembler.Run": "组装",
+ "oc:gui.Assembler.Warning.BIOS": "BIOS",
+ "oc:gui.Assembler.Warning.GraphicsCard": "显卡",
+ "oc:gui.Assembler.Warning.Inventory": "物品栏升级",
+ "oc:gui.Assembler.Warning.Keyboard": "键盘",
+ "oc:gui.Assembler.Warning.OS": "运行环境",
+ "oc:gui.Assembler.Warning.Screen": "显示屏",
+ "oc:gui.Assembler.Warnings": "§e警告§7:推荐的组件丢失。",
+ "oc:gui.Chat.NewVersion": "有新版本可用:%s",
+ "oc:gui.Chat.TextureName": "§7材质名为§a%s§f。",
+ "oc:gui.Chat.WarningClassTransformer": "执行类转换器时发生§c错误§f。请务必反馈此问题,反馈时一并附上 FML 的日志文件 §alatest.log/fml-server-latest.log§f,谢谢!",
+ "oc:gui.Chat.WarningFingerprint": "§c警告§f——指纹校验不匹配!应为 '§a%s§f',实为 '§e%s§f'。如果你不是在反混淆环境下运行游戏的模组开发者,我们§l强烈§f建议你重新下载开放式电脑模组,因为你现在使用的 JAR 文件已被修改。",
+ "oc:gui.Chat.WarningLink": "无法打开链接:%s",
+ "oc:gui.Chat.WarningLuaFallback": "无法使用原生 Lua 库,电脑无法持久化当前状态。它们会在区块载入时重启。",
+ "oc:gui.Chat.WarningProjectRed": "你目前使用的 Project:Red 版本不兼容 OpenComputers,请更新 Project:Red。",
+ "oc:gui.Chat.WarningRecipes": "加载合成表时遇到一个或多个错误。部分物品或因此无法合成。查阅日志文件以获取详细信息。",
+ "oc:gui.Drive.Managed": "受管理",
+ "oc:gui.Drive.Unmanaged": "不受管理",
+ "oc:gui.Drive.ReadOnlyLock": "只读锁定",
+ "oc:gui.Drive.ReadOnlyLockWarning": "§l只读§r锁定.除非抹掉该磁盘,否则无法关闭.",
+ "oc:gui.Drive.Warning": "§l警告§r:切换模式将会导致当前磁盘上所有数据丢失!",
+ "oc:gui.Error.ComponentOverflow": "过多的组件连接了计算机。",
+ "oc:gui.Error.InternalError": "内部错误,请检查日志文件。这可能是个Bug。",
+ "oc:gui.Error.NoCPU": "这台计算机上没有安装CPU。",
+ "oc:gui.Error.NoEnergy": "能量不足。",
+ "oc:gui.Error.NoRAM": "这台计算机上没有安装内存。",
+ "oc:gui.Error.OutOfMemory": "内存溢出。",
+ "oc:gui.Manual.Blocks": "开放式电脑-方块",
+ "oc:gui.Manual.Home": "主页",
+ "oc:gui.Manual.Items": "开放式电脑-物品",
+ "oc:gui.Manual.Warning.BlockMissing": "该方块不可用。",
+ "oc:gui.Manual.Warning.ImageMissing": "未找到图片。",
+ "oc:gui.Manual.Warning.ItemMissing": "该物品不可用。",
+ "oc:gui.Manual.Warning.OreDictMissing": "该矿物词典条目不可用。",
+ "oc:gui.Raid.Warning": "§4添加磁盘会抹掉该磁盘。\n移除磁盘会使Raid无法使用。",
+ "oc:gui.Robot.Power": "能量",
+ "oc:gui.Robot.TurnOff": "关闭",
+ "oc:gui.Robot.TurnOn": "开启\n§7使用分析器来追踪错误。§r",
+ "oc:gui.ServerRack.Back": "后",
+ "oc:gui.ServerRack.Bottom": "底部",
+ "oc:gui.ServerRack.Left": "左",
+ "oc:gui.ServerRack.None": "无",
+ "oc:gui.ServerRack.Right": "右",
+ "oc:gui.Rack.Enabled": "启用",
+ "oc:gui.Rack.Disabled": "禁用",
+ "oc:gui.ServerRack.Top": "上",
+ "oc:gui.Switch.PacketsPerCycle": "数据包 / 周期",
+ "oc:gui.Switch.QueueSize": "队列长度",
+ "oc:gui.Switch.TransferRate": "传输速率",
+ "oc:gui.Terminal.InvalidKey": "无效键,看上去另一个终端已绑定到这台服务器。",
+ "oc:gui.Terminal.OutOfRange": "无信号。",
+ "oc:container.adapter": "适配器",
+ "oc:container.case": "计算机",
+ "oc:container.charger": "充电器",
+ "oc:container.disassembler": "分解器",
+ "oc:container.diskdrive": "磁盘驱动器",
+ "oc:container.printer": "打印机",
+ "oc:container.raid": "Raid磁盘阵列",
+ "oc:container.relay": "中继器",
+ "oc:container.server": "服务器",
+ "oc:container.rack": "机架",
+ "oc:container.tabletwrapper": "平板电脑",
+ "key.opencomputers.clipboardPaste": "粘贴到剪贴板",
+ "oc:tooltip.abstractbuscard": "允许计算机向§f星门科技2§7的抽象类总线发送或接收 LIP 数据包。",
+ "oc:tooltip.acid": "一种有毒的虚构液体,通常只有某些海盗会使用它们。然而它应该有别的用途。",
+ "oc:tooltip.adapter": "用于控制非电脑组件的方块,比如原版或者来自其它模组的方块。",
+ "oc:tooltip.alu": "用来做算术及逻辑运算而不用你亲自代劳,它更能胜任这份差事。",
+ "oc:tooltip.analyzer": "用于显示方块信息,比如它们的§f地址§7和§f组件名称§7。如果计算机未能正常关闭它也会显示使计算机崩溃的报错。",
+ "oc:tooltip.apu": "如果你只是需要一个额外的卡槽,这就是你需要的自带 GPU(或者集成图形处理器 IGP)的 CPU。\n支持的组件:§f%s§7\n最大分辨率:§f%sx%s§7\n最高色深:§f%s§7\n运算/tick:§f%s§7",
+ "oc:tooltip.assembler": "允许使用若干不同的电脑组件来组装机器人。",
+ "oc:tooltip.cable": "连接方块的廉价选择。",
+ "oc:tooltip.capacitor": "储能以备不时之需。能够非常快速地充电或放电。",
+ "oc:tooltip.carpetedcapacitor": "储能以备不时之需。能够非常快速地充电或放电。有羊或豹猫踩上去的时候就能充电。",
+ "oc:tooltip.cardbase": "正如其名,它是用来安装其它扩展卡的基本卡板。",
+ "oc:tooltip.case": "计算机机箱是构建计算机的基本方块,也是各种§f扩展卡§7,§f存储器§7以及§f硬盘§7的外壳。\n格子:§f%s§7",
+ "oc:tooltip.chamelium": "3D打印的基本原材料。不要误吸:或造成失明和暂时失去意识。",
+ "oc:tooltip.chameliumblock": "整洁干净的玩意。对于彩色 3D 打印相当实用,或者只是拿它的整洁干净的色彩来装饰你的华丽的基地。",
+ "oc:tooltip.charger": "将电容器的能量传输给相邻机器人。传输效率取决于输入的§f红石信号§7强度,无信号意味着不给机器人充电,而最强信号则意味着全速给机器人充电。",
+ "oc:tooltip.circuitboard": "现在我们已经取得一些进展。可以通过蚀刻来得到印制电路板。",
+ "oc:tooltip.controlunit": "用来控制……控制东西……的单元。你需要这玩意儿来做 CPU。所以反正啦,这个非常重要。",
+ "oc:tooltip.componentbus": "这个扩展能让服务器同时与更多组件通讯,工作原理类似 CPU。\n支持的组件:§f%s§7",
+ "oc:tooltip.cpu": "所有计算机最核心的组件,它的时钟频率有点不可靠,但是你考虑到它是靠便携日晷来运行的,还能指望什么呢?\n支持组件:§f%s§7",
+ "oc:tooltip.cpu.Architecture": "架构:§f%s§7",
+ "oc:tooltip.cuttingwire": "用于将粘土块切割成电路板的形状。使用一次就会坏掉,这可能使得成为历来最低效的工具。",
+ "oc:tooltip.datacard0": "提供数种高级算法,例如散列、压缩和解压缩算法。",
+ "oc:tooltip.datacard1": "提供数种高级算法,例如散列、AES 加密、压缩和解压缩算法。",
+ "oc:tooltip.datacard2": "提供数种高级算法,例如散列、AES 加密、椭圆曲线加密、压缩和解压缩算法。",
+ "oc:tooltip.debugcard": "创造模式物品,它能让你更简易的操控世界来进行测试。请自己承担它带来的危险。",
+ "oc:tooltip.debugger": "用于在 OpenComputer 的内部网络格栅中输出调试信息。请在开发者指导下使用。",
+ "oc:tooltip.diamondchip": "一小粒正在发光的钻石。永远不会破镜重圆。",
+ "oc:tooltip.disassembler": "将物品分解成基础组件。§l警告§7:分解得到的物品会有 %s%% 的几率在分解过程中损坏!",
+ "oc:tooltip.disk": "用于制造持久存储设备的原始媒介材料。",
+ "oc:tooltip.diskdrive.CC": "§a支持§7 ComputerCraft 的软盘。",
+ "oc:tooltip.diskdrive": "用来读写软盘。可以给机器人安装使其可以插入软盘。",
+ "oc:tooltip.diskdrivemountable": "和普通软驱用途一样,但必须装载在机架里。",
+ "oc:tooltip.diskusage": "磁盘使用:%s/%s 字节",
+ "oc:tooltip.diskmodemanaged": "模式:管理",
+ "oc:tooltip.diskmodeunmanaged": "模式:不受管理",
+ "oc:tooltip.drone": "无人机是一种轻量而快速的侦查单位,自身拥有有限的载物空间。",
+ "oc:tooltip.dronecase": "这个外壳将会在组装机中组装出无人机。这个外壳可容纳少量组件,并内建末地石驱动的悬浮系统。",
+ "oc:tooltip.eeporm": "小型的可编程存储器,可存储电脑启动所用的BIOS。",
+ "oc:tooltip.fakeendstone": "几乎可以以假乱真,甚至更加轻盈!",
+ "oc:tooltip.geolyzer": "可以检测周围方块的硬度。这些信息对编写全息地图程序或检测矿物都有很大的帮助。",
+ "oc:tooltip.graphicscard": "用来改变屏幕上的显示内容。最高分辨率:§f%sx%s§7\n最高色深:§f%s§7\n运算/tick:§f%s§7",
+ "oc:tooltip.hoverboots": "跳得更高,摔得更深,走得更快。一切尽在 Hover Boots™,已获顶级认证。",
+ "oc:tooltip.inkcartridge": "用于重新填装3D打印机的墨水。因为某些原因这些墨水不必保留在打印机里。",
+ "oc:tooltip.inkcartridgeempty": "此墨盒经过深度干燥处理。用颜料重新装填,抑或弃置。看我脸色行事。",
+ "oc:tooltip.internetcard": "因特网卡可以让你发送HTTP请求以及使用货真价实的TCP套接字。",
+ "oc:tooltip.interweb": "恭喜,你赢得了一个因特网。你可以使用因特网卡来连接它。注意:不要水贴钓鱼",
+ "oc:tooltip.ironnugget": "颗粒状的铁,所以叫铁粒啦,蠢蠢的感觉……",
+ "oc:tooltip.keyboard": "可以连接屏幕来输入显示文本。",
+ "oc:tooltip.hologram0": "一个能通过电脑控制来投射出任何三维结构的全息投影仪.\n分辨率:§f48x32x48§7\n最大显示规模:§f3x§7\n最高色深:§f黑白§7",
+ "oc:tooltip.hologram1": "使用电脑控制的高级全息投影仪。\n分辨率:§f48x32x48§7\n最大显示规模:§f4x§7\n最高色深:§f三原色§7",
+ "oc:tooltip.linkedcard": "连接卡可以成对合成,并且它们只能与各自对应的连接卡交互。然而,它们之间的交互没有距离限制,甚至可以跨越不同的世界。但它们传递信息所需要的能量消耗不多不少。",
+ "oc:tooltip.linkedcard_channel": "§8频道:%s§7",
+ "oc:tooltip.manual": "包含你需要的关于 OpenComputer 的一切信息。还有更多。为此你只需要……§o请按R键继续§7。",
+ "oc:tooltip.memory": "电脑运行必备。内存越大,你就可以运行越复杂的程序。",
+ "oc:tooltip.microchip": "通常也管这种芯片叫集成电路。我也不知道为什么能和红石一起运行,但事实如此。",
+ "oc:tooltip.microcontroller": "单片机是被压缩到不能再压缩的电脑。它们更多是用于执行特殊任务,并只运行一个内建于EEPROM中的简单程序。\n§c不能和外置组件相连接。§7",
+ "oc:tooltip.microcontrollercase": "单片机基础组件。在组装机中为其添加各种组件并组装单片机。",
+ "oc:tooltip.motionsensor": "可以检测附近生物的动向。检测需要无遮挡物的环境。",
+ "oc:tooltip.nanomachines": "控制单元,同时还是一堆可以吸入的纳米机器(如果你愿意的话)。",
+ "oc:tooltip.networkcard": "允许通过其他方块(比如线缆)相连的远程计算机能够向彼此发送信息进行交互。",
+ "oc:tooltip.poweracceptor": "能量转换速度:§f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§fMJ§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§fCharge§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§fEU§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§fJoules§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§fRF§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§fCoulombs§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "将其它模组的能量转化为本模组的内部能源形式。转换比:",
+ "oc:tooltip.powerdistributor": "在不同网络中分配能量。很实用于通过包含多个理论上独立子网络的转换器在系统中共享能量。",
+ "oc:tooltip.present": "……它随时为你的麻烦待命。打开此礼物将有机会获得 §kphat lewt§7!\n§8在时机合适时,合成 OpenComputers 的物品。§7",
+ "oc:tooltip.print.BeaconBase": "§8可用作信标底座。",
+ "oc:tooltip.print.LightValue": "§8光强:%s。",
+ "oc:tooltip.print.RedstoneLevel": "§8红石信号强度:%s。",
+ "oc:tooltip.printedcircuitboard": "扩展卡、内存等组件的基础板。",
+ "oc:tooltip.printer": "利用变色物质和墨盒打印出用户自定义的形状。需要用电脑进行配置。不要让幼童接触。就是这样。",
+ "oc:tooltip.raid": "允许将三块硬盘组成一个大文件系统供所有与其连接的电脑使用。",
+ "oc:tooltip.rawcircuitboard": "能在支持原版熔炉配方的炉子中加工强化。",
+ "oc:tooltip.redstone": "能够在方块周围接收或发送红石信号。可以被与之相连的计算机控制。基本上就像一个外置红石卡。",
+ "oc:tooltip.redstonecard.Charset": "§a兼容§7 §fSimpleLogic§7。",
+ "oc:tooltip.redstonecard.ProjectRed": "§a兼容§7 §fProject Red§7。",
+ "oc:tooltip.redstonecard.RedLogic": "§a兼容§7 §fRedLogic§7。",
+ "oc:tooltip.redstonecard.RedNet": "§a兼容§7 §fRedNet§7。",
+ "oc:tooltip.redstonecard.WirelessCBE": "§a兼容§7 §f无线红石(ChickenBones)§7。",
+ "oc:tooltip.redstonecard.WirelessSV": "§a兼容§7 §f无线红石(SlimeVoid)§7。",
+ "oc:tooltip.redstonecard": "允许在计算机和机器人四周接收或发送红石信号。",
+ "oc:tooltip.relay": "可将不同网络连接在一起。仅信息可通过此设备传递,其它元件仍不可见。用法举例:可用于保持多个独立网络的通信。",
+ "oc:tooltip.robot": "和计算机不同,机器人能够移动并且像玩家那样与世界中的东西交互。然而,它们§o不能§r§7直接与外设进行交互!",
+ "oc:tooltip.robot_level": "§f等级§7:§a%s§7。",
+ "oc:tooltip.robot_storedenergy": "§f存储能量§7:§a%s§7。",
+ "oc:tooltip.screen": "显示文本,运作需要机箱中的显卡。\n最高分辨率:§f%sx%s§7\n最高色深:§f%s§7",
+ "oc:tooltip.server": "这就是服务器,它与许多其它的服务器拥有相似功能,但这台服务器可以使用组件进行升级,就像升级机箱一样。它也可以放入服务器机架中运行。",
+ "oc:tooltip.server.Components": "已安装的组件:",
+ "oc:tooltip.rack": "它能装下四台服务器或者别的设备。",
+ "oc:tooltip.tablet": "一台平板电脑,为 Lua 新人准备。潜行时右击可强制关机。",
+ "oc:tooltip.tabletcase": "平板电脑的基础外壳。在组装机中添加组件以制造平板电脑。",
+ "oc:tooltip.terminal": "可以远程控制服务器,不过前提是你处于信号范围内。使用方法相同于显示屏与键盘. Shift 右击机架中的服务器可以绑定对应的终端。",
+ "oc:tooltip.terminalserver": "在工作范围内可与终端连接,以提供远程控制功能。内建有虚拟显示器和键盘。",
+ "oc:tooltip.texturepicker": "这个工具可以显示放块表面的描述,可用于3D打印定义中。完全不是材质名,完全不是。很抱歉先生,不是。",
+ "oc:tooltip.tier": "§8等级 %s",
+ "oc:tooltip.netsplitter": "作为动态连接器的存在。每个面的连接设定可通过扳手切换。红石信号可反相所有面的连接设定。",
+ "oc:tooltip.toolong": "按住 [§f%s§7] 显示详细物品信息。",
+ "oc:tooltip.transistor": "大多数电脑组件中最基础的元素。看上去有些扭曲,但它是有用的。",
+ "oc:tooltip.transposer": "可在相邻容器之间自动转移物品和液体。",
+ "oc:tooltip.upgradeangel": "允许机器人凭空放置方块,甚至是在没有任何依附的情况下。",
+ "oc:tooltip.upgradebattery": "增加机器人存储能量的上限,让其能够运作很长一段时间也不必充电。\n电容:§f%s§7",
+ "oc:tooltip.upgradechunkloader": "如果机器人走进了一片森林,周围没有任何生物载入区块,那么它还能继续移动吗? 这个升级组件可以让你确定这点。它能让机器人所处的区块保持载入,但这会让能量不断地消耗。",
+ "oc:tooltip.upgradecontainercard": "卡容器组件可以让你方便随意的将卡装入机器人或从中移出。\n最高等级:§f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "卡容器升级组件可以让你方便的将卡装入另一个卡容器或从中移出。\n最高等级:§f%s§7",
+ "oc:tooltip.upgradecrafting": "能让机器人的物品栏左上角部分成为合成界面。物品必须在合成界面里排列整齐。",
+ "oc:tooltip.upgradedatabase": "能对物品信息进行分类,供其它组件稍后取用。\n可支持条目数量:§f%s§7",
+ "oc:tooltip.upgradeexperience": "这个升级能让机器人在执行一些工作时获取经验并累积。它们拥有越多的累积经验,就能够存储越多的能量,越快的挖掘方块并且使用工具时拥有更高的效率。",
+ "oc:tooltip.upgradegenerator": "可以让机器人通过燃料充能。燃烧物品得到的发电量取决于燃料的等级。\n§f发电效率§7:§a%s%%§7",
+ "oc:tooltip.upgradehover": "这个升级组件可让机器人飞得更高而无需爬墙。\n最大高度:§f%s§7",
+ "oc:tooltip.upgradeinventory": "这个升级组件为机器人提供了物品背包。如果没有这个升级,机器人将不能存储物品。",
+ "oc:tooltip.upgradeinventorycontroller": "这个升级组件可以控制机器人使其与外部容器互动,并能允许机器人将装备上的工具替换成其物品栏中的其它物品。",
+ "oc:tooltip.upgrademf": "能让适配器访问不与其相邻的方块。",
+ "oc:tooltip.upgrademf.Linked": "§f已连接§7",
+ "oc:tooltip.upgrademf.Unlinked": "§f没有连接§7",
+ "oc:tooltip.upgradeleash": "这个升级组件可让诸如无人机之类的设备绑在 Isaa——不好意思,*清清嗓子* 我刚才说错了。我只是被告知这原本是用来拴动物的绳子。可以拴很多动物,好奇怪啊。",
+ "oc:tooltip.upgradenavigation": "可以让机器人确认所处位置以及定位。定位地点即为用于合成此升级组件用到的地图的中心点。",
+ "oc:tooltip.upgradepiston": "这个升级十分有用。它能让机器人像活塞那样移动方块,但 §l不能§7 移动实体。",
+ "oc:tooltip.upgradesign": "允许机器人读写告示牌。",
+ "oc:tooltip.upgradesolargenerator": "可以让机器人在太阳光的照射下四处奔走。机器人顶部需要无任何方块阻挡。产能速度是斯特林引擎的 %s%%。",
+ "oc:tooltip.upgradetank": "为你的机器人装上一个可存储流体的水箱。如果没有升级此功能,你的机器人将无法在内部存储流体。",
+ "oc:tooltip.upgradetankcontroller": "这个升级能让你的机器人与外界水箱交互,向其传输流体。",
+ "oc:tooltip.upgradetractorbeam": "十分先进的高科技,别名“物品磁铁”。它能让机器人在任何地方捡起3格范围内的掉落物。",
+ "oc:tooltip.waypoint": "为安装有导航升级的设备提供参考点。",
+ "oc:tooltip.wirelessnetworkcard": "允许在发送正常信息的情况下发送无线网络信息。请确保已设置好 §f信号强度§7 否则不会发出信息。越高的信号强度会导致越高的能量消耗。",
+ "oc:tooltip.worldsensorcard": "可读取关于世界的各种信息,例如重力加速度和是否有可供呼吸的大气。使用风险自负。制造商对由卡片输出结果造成的损失不承担任何法律责任。我们不仅有律师,还有现金。不要试图告倒我们。",
+ "oc:tooltip.wrench": "螺丝刀和扳手混合体,新手友好,高手毁灭者。",
+ "achievement.oc.adapter": "Plug In Baby",
+ "achievement.oc.adapter.desc": "和其它 MOD 的方块(甚至是原版 Minecraft 方块)进行互动!",
+ "achievement.oc.assembler": "完美",
+ "achievement.oc.assembler.desc": "是时候征服世界了!",
+ "achievement.oc.cable": "并不是脏兮兮的电线",
+ "achievement.oc.cable.desc": "搭配权威认证的反 SCP-229 科技",
+ "achievement.oc.capacitor": "本设备含电池",
+ "achievement.oc.capacitor.desc": "不可能阻止它",
+ "achievement.oc.card": "我们接受卡片",
+ "achievement.oc.card.desc": "这是为方便您的使用。我们保证这不是别有用心。",
+ "achievement.oc.case": "以备后患",
+ "achievement.oc.case.desc": "Because cuboid towers are the best.",
+ "achievement.oc.charger": "那就开始做吧!",
+ "achievement.oc.charger.desc": "开始充——等等!又忘记红石信号了。",
+ "achievement.oc.chip": "全是些小东西",
+ "achievement.oc.chip.desc": "曾经真空管也是这样的。",
+ "achievement.oc.cpu": "超频",
+ "achievement.oc.cpu.desc": "是时候好好利用这些计算循环了",
+ "achievement.oc.disassembler": "销毁!",
+ "achievement.oc.disassembler.desc": "当你发现你的想法很美好,但现实其实很残酷的时候,就用这个吧。",
+ "achievement.oc.diskDrive": "Roundabout",
+ "achievement.oc.diskDrive.desc": "Inferior capacity but such delicious sound.",
+ "achievement.oc.drone": "啊!飞走了!",
+ "achievement.oc.drone.desc": "冷静冷静,直接用核弹让他们在轨道上瞬间爆炸",
+ "achievement.oc.eeprom": "每台电脑",
+ "achievement.oc.eeprom.desc": "仅限一个,就是这样。这是用来决定最终启动顺序的,明白吗!?",
+ "achievement.oc.floppy": "The One Ri- Disk",
+ "achievement.oc.floppy.desc": "不要与flappy混淆。\n注:软盘英文为floppy disk",
+ "achievement.oc.geolyzer": "深入地心",
+ "achievement.oc.geolyzer.desc": "It has extraordinary qualities.",
+ "achievement.oc.graphicsCard": "LastGen",
+ "achievement.oc.graphicsCard.desc": "The way it's meant to be... uh... rendered. Yeah. That.",
+ "achievement.oc.hdd": "Hot Dog Dealer(热狗推销员)",
+ "achievement.oc.hdd.desc": "等等我不是那个意思。让我想想,好像想起来什么意思了……",
+ "achievement.oc.hologram": "下一个次元",
+ "achievement.oc.hologram.desc": "因为 2D 很无聊啊。或者本来就这样?",
+ "achievement.oc.keyboard": "吸尘器 3000 型",
+ "achievement.oc.keyboard.desc": "强烈建议使用时保持将其翻过来并持续摇晃的习惯,以清理其中异物。",
+ "achievement.oc.microcontroller": "Little Sisters",
+ "achievement.oc.microcontroller.desc": "计算机的小妹妹哦",
+ "achievement.oc.motionSensor": "Got the Moves",
+ "achievement.oc.motionSensor.desc": "Like Steve Swagger.",
+ "achievement.oc.networkCard": "现在我们在聊天了!",
+ "achievement.oc.networkCard.desc": "Keep in touch with those distant relatives via transitive relations.",
+ "achievement.oc.openOS": "启动",
+ "achievement.oc.openOS.desc": "One OS to - wait, I used that one already? Dang.",
+ "achievement.oc.powerDistributor": "分享即关怀",
+ "achievement.oc.powerDistributor.desc": "当你在平衡供电时需要帮助的时候。",
+ "achievement.oc.rack": "Dat Rack",
+ "achievement.oc.rack.desc": "我不知道你想歪到哪里去了,我已经说得很明白了,就是服务器架。",
+ "achievement.oc.raid": "LFG",
+ "achievement.oc.raid.desc": "Heroic plzkthx.",
+ "achievement.oc.ram": "随机存取存储器",
+ "achievement.oc.ram.desc": "恭喜,你的操作完全正确。",
+ "achievement.oc.redstoneCard": "联系",
+ "achievement.oc.redstoneCard.desc": "模拟信号时间到。",
+ "achievement.oc.redstoneIO": "The Outsider",
+ "achievement.oc.redstoneIO.desc": "将红石信号传播到你需要的地方!",
+ "achievement.oc.robot": "Beep Boop",
+ "achievement.oc.robot.desc": "灭绝!",
+ "achievement.oc.screen": "试过反复开关这屏幕没?",
+ "achievement.oc.screen.desc": "真没有。毕竟红石信号就可以开关这屏幕了。",
+ "achievement.oc.server": "专用",
+ "achievement.oc.server.desc": "云服务,现已正式推出。",
+ "achievement.oc.switch": "复杂拓扑学",
+ "achievement.oc.switch.desc": "远离易碎货物,因为包裹可能会掉下来。",
+ "achievement.oc.tablet": "不要吸入",
+ "achievement.oc.tablet.desc": "同时请远离儿童,以避免不必要的信用卡过度透支。",
+ "achievement.oc.transistor": "Tell Red I said \"Hi.\"",
+ "achievement.oc.transistor.desc": "制作一个晶体管然后让它工作。然后听录音带。不用谢我。",
+ "achievement.oc.wirelessNetworkCard": "信号",
+ "achievement.oc.wirelessNetworkCard.desc": "是时候让数据包踏遍每一个角落了。",
+ "death.attack.oc.nanomachinesOverload.1": "%s 过于贪婪。",
+ "death.attack.oc.nanomachinesOverload.2": "%s 神经断裂。",
+ "death.attack.oc.nanomachinesOverload.3": "%s 的纳米机器失控暴走了。",
+ "death.attack.oc.nanomachinesHungry.1": "%s 被纳米机器吃掉了。",
+ "death.attack.oc.nanomachinesHungry.2": "%s 忘记喂饱纳米机器了。",
+ "death.attack.oc.nanomachinesHungry.3": "%s 已被分解吸收了。",
+ "nei.options.inventory.oredict": "显示矿物词典名",
+ "nei.options.inventory.oredict.true": "是",
+ "nei.options.inventory.oredict.false": "否",
+ "nei.usage.oc.Manual": "打开手册",
+ "option.oc.address": "地址",
+ "option.oc.componentName": "组件名",
+ "option.oc.energy": "能量"
+}
diff --git a/src/main/resources/assets/opencomputers/lang/zh_tw.json b/src/main/resources/assets/opencomputers/lang/zh_tw.json
new file mode 100644
index 0000000000..16a3469ad9
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/lang/zh_tw.json
@@ -0,0 +1,444 @@
+{
+ "tile.oc.accesspoint": "§c橋接器§7",
+ "tile.oc.adapter": "連接器",
+ "tile.oc.assembler": "機器組裝台",
+ "tile.oc.cable": "線纜",
+ "tile.oc.capacitor": "電容",
+ "tile.oc.case1": "基礎電腦機殼",
+ "tile.oc.case2": "高級電腦機殼",
+ "tile.oc.case3": "超級電腦機殼",
+ "tile.oc.casecreative": "電腦機殼(創造模式)",
+ "tile.oc.chameliumblock": "變色凝膠磚",
+ "tile.oc.charger": "充電器",
+ "tile.oc.disassembler": "拆解機",
+ "tile.oc.diskdrive": "磁碟機",
+ "tile.oc.endstone": "終界石",
+ "tile.oc.geolyzer": "硬度分析機",
+ "tile.oc.hologram1": "全息投影機 (1級)",
+ "tile.oc.hologram2": "全息投影機 (2級)",
+ "tile.oc.keyboard": "鍵盤",
+ "tile.oc.microcontroller": "微型控制器",
+ "tile.oc.motionsensor": "動作感應器",
+ "tile.oc.netsplitter": "網路路由器",
+ "tile.oc.powerconverter": "能源轉換器",
+ "tile.oc.powerdistributor": "能源分配器",
+ "tile.oc.print": "3D 列印",
+ "tile.oc.printer": "3D 列印機",
+ "tile.oc.raid": "磁碟陣列機(NAS)",
+ "tile.oc.redstone": "紅石I/O",
+ "tile.oc.relay": "中繼器",
+ "tile.oc.robot": "機器人",
+ "tile.oc.robotafterimage": "機器人",
+ "tile.oc.screen1": "黑白電腦顯示器",
+ "tile.oc.screen2": "彩色電腦顯示器",
+ "tile.oc.screen3": "高畫質電腦顯示器",
+ "tile.oc.rack": "伺服器機架",
+ "tile.oc.switch": "路由器",
+ "tile.oc.transposer": "差轉機",
+ "tile.oc.waypoint": "路點",
+ "item.oc.abstractbusCard": "抽象的介面卡",
+ "item.oc.acid": "蝕刻藥水",
+ "item.oc.alu": "算邏運算單元(ALU)",
+ "item.oc.analyzer": "分析器",
+ "item.oc.apu0": "加速處理單元 (APU) (1級)",
+ "item.oc.apu1": "加速處理單元 (APU) (2級)",
+ "item.oc.apu2": "加速處理單元 (APU) (創造模式)",
+ "item.oc.arrowkeys": "方向鍵",
+ "item.oc.buttongroup": "按鈕組",
+ "item.oc.cardbase": "主板",
+ "item.oc.chamelium": "變色凝膠",
+ "item.oc.circuitboard": "電路板",
+ "item.oc.componentbus0": "基礎排線",
+ "item.oc.componentbus1": "高級排線",
+ "item.oc.componentbus2": "超級排線",
+ "item.oc.controlunit": "控制單元 (CU)",
+ "item.oc.cpu0": "中央處理器 (CPU) (1級)",
+ "item.oc.cpu1": "中央處理器 (CPU) (2級)",
+ "item.oc.cpu2": "中央處理器 (CPU) (3級)",
+ "item.oc.cuttingwire": "切割線",
+ "item.oc.datacard0": "資料卡 (1級)",
+ "item.oc.datacard1": "資料卡 (2級)",
+ "item.oc.datacard2": "資料卡 (3級)",
+ "item.oc.debugcard": "除錯卡",
+ "item.oc.debugger": "網路除錯卡",
+ "item.oc.disk": "磁碟",
+ "item.oc.drone": "無人機",
+ "item.oc.dronecase0": "無人機外殼 (1級)",
+ "item.oc.dronecase1": "無人機外殼 (2級)",
+ "item.oc.dronecase3": "無人機外殼 (創造模式)",
+ "item.oc.eeprom": "電子抹除式可複寫唯讀記憶體(EEPROM)",
+ "item.oc.floppydisk": "磁碟片",
+ "item.oc.graphicscard0": "顯示卡",
+ "item.oc.graphicscard1": "彩色顯示卡",
+ "item.oc.graphicscard2": "高畫質顯示卡",
+ "item.oc.harddiskdrive0": "硬碟機 (1級)",
+ "item.oc.harddiskdrive1": "硬碟機 (2級)",
+ "item.oc.harddiskdrive2": "硬碟機 (3級)",
+ "item.oc.hoverboots": "懸停靴",
+ "item.oc.inkcartridge": "墨水匣",
+ "item.oc.inkcartridgeempty": "墨水匣(空)",
+ "item.oc.internetcard": "上網卡",
+ "item.oc.interweb": "因特網",
+ "item.oc.ironnugget": "鐵粒",
+ "item.oc.linkedcard": "連結卡",
+ "item.oc.manual": "開放式電腦手冊",
+ "item.oc.memory0": "記憶卡 (1級)",
+ "item.oc.memory1": "記憶卡 (1.5級)",
+ "item.oc.memory2": "記憶卡 (2級)",
+ "item.oc.memory3": "記憶卡 (2.5級)",
+ "item.oc.memory4": "記憶卡 (3級)",
+ "item.oc.memory5": "記憶卡 (3.5級)",
+ "item.oc.microchip0": "微晶片 (1級)",
+ "item.oc.microchip1": "微晶片 (2級)",
+ "item.oc.microchip2": "微晶片 (3級)",
+ "item.oc.microcontrollercase0": "微控制器外殼 (Tier 1)",
+ "item.oc.microcontrollercase1": "微控制器外殼 (Tier 2)",
+ "item.oc.microcontrollercase3": "微控制器外殼 (Creative)",
+ "item.oc.nanomachines": "納米機器",
+ "item.oc.networkcard": "網路卡",
+ "item.oc.numpad": "數字鍵盤",
+ "item.oc.present": "一個小東西...",
+ "item.oc.printedcircuitboard": "印刷電路板(PCB)",
+ "item.oc.rawcircuitboard": "電路板材料",
+ "item.oc.redstonecard0": "紅石卡 (1級)",
+ "item.oc.redstonecard1": "紅石卡 (2級)",
+ "item.oc.server0": "伺服器 (1級)",
+ "item.oc.server1": "伺服器 (2級)",
+ "item.oc.server2": "伺服器 (3級)",
+ "item.oc.server3": "伺服器 (創造模式)",
+ "item.oc.tablet": "平板電腦",
+ "item.oc.tabletcase0": "平板電腦保護套 (1級)",
+ "item.oc.tabletcase1": "平板電腦保護套 (2級)",
+ "item.oc.tabletcase3": "平板電腦保護套 (創造模式)",
+ "item.oc.terminal": "遠端終端機",
+ "item.oc.texturepicker": "紋理選擇器",
+ "item.oc.transistor": "電晶體",
+ "item.oc.upgradeangel": "天使升級",
+ "item.oc.upgradebattery0": "電池升級 (1級)",
+ "item.oc.upgradebattery1": "電池升級 (2級)",
+ "item.oc.upgradebattery2": "電池升級 (3級)",
+ "item.oc.upgradechunkloader": "區塊載入器升級",
+ "item.oc.upgradecontainercard0": "卡片集裝箱 (1級)",
+ "item.oc.upgradecontainercard1": "卡片集裝箱 (2級)",
+ "item.oc.upgradecontainercard2": "卡片集裝箱 (3級)",
+ "item.oc.upgradecontainerupgrade0": "集裝箱升級 (1級)",
+ "item.oc.upgradecontainerupgrade1": "集裝箱升級 (2級)",
+ "item.oc.upgradecontainerupgrade2": "集裝箱升級 (3級)",
+ "item.oc.upgradecrafting": "合成升級",
+ "item.oc.upgradedatabase0": "資料庫升級 (1級)",
+ "item.oc.upgradedatabase1": "資料庫升級 (2級)",
+ "item.oc.upgradedatabase2": "資料庫升級 (3級)",
+ "item.oc.upgradeexperience": "經驗升級",
+ "item.oc.upgradegenerator": "發電機升級",
+ "item.oc.upgradehover0": "懸停升級 (1級)",
+ "item.oc.upgradehover1": "懸停升級 (2級)",
+ "item.oc.upgradeinventory": "物品欄升級",
+ "item.oc.upgradeinventorycontroller": "物品控制器升級",
+ "item.oc.upgradeleash": "皮帶升級",
+ "item.oc.upgradenavigation": "導航升級",
+ "item.oc.upgradepiston": "活塞升級",
+ "item.oc.upgradesign": "告示牌 I/O 升級",
+ "item.oc.upgradesolargenerator": "太陽能發電升級",
+ "item.oc.upgradetank": "水箱升級",
+ "item.oc.upgradetankcontroller": "高級水箱升級",
+ "item.oc.upgradetractorbeam": "牽引光束升級",
+ "item.oc.wirelessnetworkcard0": "無線網卡",
+ "item.oc.wirelessnetworkcard1": "無線網卡",
+ "item.oc.worldsensorcard": "世界傳感器卡",
+ "item.oc.wrench": "螺絲刀扳手",
+ "itemGroup.OpenComputers": "OpenComputers",
+ "entity.oc.drone": "無人機",
+ "oc:gui.Analyzer.Address": "§6位址§f: %s",
+ "oc:gui.Analyzer.AddressCopied": "位址複製到剪貼簿.",
+ "oc:gui.Analyzer.ChargerSpeed": "§6充電速度§f: %s",
+ "oc:gui.Analyzer.ComponentName": "§6設備元件名稱§f: %s",
+ "oc:gui.Analyzer.Components": "§6連接元件的數量§f: %s",
+ "oc:gui.Analyzer.CopyToClipboard": "點擊複製到剪貼簿。",
+ "oc:gui.Analyzer.LastError": "§6上一個錯誤§f: %s",
+ "oc:gui.Analyzer.RobotName": "§6名字§f: %s",
+ "oc:gui.Analyzer.RobotOwner": "§6持有者§f: %s",
+ "oc:gui.Analyzer.RobotXp": "§6經驗值§f: %s",
+ "oc:gui.Analyzer.StoredEnergy": "§6儲存能量§f: %s",
+ "oc:gui.Analyzer.TotalEnergy": "§6總儲存能量§f: %s",
+ "oc:gui.Analyzer.Users": "§6使用者§f: %s",
+ "oc:gui.Analyzer.WirelessStrength": "§6信號強度§f: %s",
+ "oc:gui.Assembler.Collect": "收集機器人",
+ "oc:gui.Assembler.Complexity": "複雜性: %s/%s",
+ "oc:gui.Assembler.InsertCase": "裝入電腦機殼(CASE)",
+ "oc:gui.Assembler.InsertCPU": "裝入中央處理器(CPU)",
+ "oc:gui.Assembler.InsertRAM": "裝入一些記憶體(RAM)",
+ "oc:gui.Assembler.Progress": "進度: %s%% (%s)",
+ "oc:gui.Assembler.Run": "開始組裝機器人",
+ "oc:gui.Assembler.Warnings": "§e警告§7: 缺少某些建議的零組件",
+ "oc:gui.Assembler.Warning.GraphicsCard": "顯示卡",
+ "oc:gui.Assembler.Warning.Inventory": "物品欄升級組件",
+ "oc:gui.Assembler.Warning.Keyboard": "鍵盤",
+ "oc:gui.Assembler.Warning.OS": "開機(作業系統) 中等",
+ "oc:gui.Assembler.Warning.Screen": "螢幕",
+ "oc:gui.Assembler.Warnings": "§e警告§7: 缺少建議的零組件",
+ "oc:gui.Chat.NewVersion": "有新版本可用: %s",
+ "oc:gui.Chat.TextureName": "§7紋理名稱是 §a%s§f.",
+ "oc:gui.Chat.WarningClassTransformer": "There were §cerrors§f running the class transformer. Please report this, together with your (full!) FML §alatest.log§f/§afml-server-latest.log§f logfile, thank you!",
+ "oc:gui.Chat.WarningFingerprint": "§c警告§f - 指紋不符!預期 '§a%s§f' 但得到 '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.",
+ "oc:gui.Chat.WarningLink": "無法打開鏈接: %s",
+ "oc:gui.Chat.WarningLuaFallback": "本機 LUA 函式庫無法使用,電腦將無法維持狀態,他會重新啟動並且載入區塊",
+ "oc:gui.Chat.WarningProjectRed": "你正在使用的 Project: Red 模組與 OpenComputers 不相容. 請嘗試更新 Project: Red.",
+ "oc:gui.Chat.WarningRecipes": "There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.",
+ "oc:gui.Drive.Managed": "受管",
+ "oc:gui.Drive.Unmanaged": "非受管",
+ "oc:gui.Drive.Warning": "§l警告§r: 切換模式會導致目前儲存在硬碟上的所有資料遺失!",
+ "oc:gui.Error.ComponentOverflow": "太多的元件連接到電腦上了",
+ "oc:gui.Error.InternalError": "內部錯誤,請查看日誌文件。這可能是一個錯誤。",
+ "oc:gui.Error.NoCPU": "電腦內沒有安裝中央處理器(CPU).",
+ "oc:gui.Error.NoEnergy": "沒有能源",
+ "oc:gui.Error.NoRAM": "電腦內沒有安裝記憶卡",
+ "oc:gui.Error.OutOfMemory": "記憶體不足",
+ "oc:gui.Manual.Blocks": "開放式電腦方塊",
+ "oc:gui.Manual.Home": "首頁",
+ "oc:gui.Manual.Items": "開放式電腦物品",
+ "oc:gui.Manual.Warning.BlockMissing": "方塊不存在",
+ "oc:gui.Manual.Warning.ImageMissing": "沒有找到圖片",
+ "oc:gui.Manual.Warning.ItemMissing": "物品不存在",
+ "oc:gui.Manual.Warning.OreDictMissing": "礦物字典不存在",
+ "oc:gui.Raid.Warning": "§4放入的硬碟機會清除硬碟資料.\n移除硬碟機會刪除磁碟陣列機(NAS)資料.",
+ "oc:gui.Robot.Power": "能量",
+ "oc:gui.Robot.TurnOff": "關閉",
+ "oc:gui.Robot.TurnOn": "開啟",
+ "oc:gui.Rack.None": "無",
+ "oc:gui.Rack.Back": "背面",
+ "oc:gui.Rack.Bottom": "底部",
+ "oc:gui.Rack.Left": "左",
+ "oc:gui.Rack.Right": "右",
+ "oc:gui.Rack.Top": "上",
+ "oc:gui.Switch.TransferRate": "週期率",
+ "oc:gui.Switch.PacketsPerCycle": "封包 / 週期",
+ "oc:gui.Switch.QueueSize": "隊列大小",
+ "oc:gui.Terminal.InvalidKey": "按鍵無效時,最有可能另一端已經綁定到伺服器。",
+ "oc:gui.Terminal.OutOfRange": "沒訊號.",
+ "oc:container.accesspoint": "橋接器",
+ "oc:container.adapter": "連接器",
+ "oc:container.case": "電腦",
+ "oc:container.charger": "充電器",
+ "oc:container.disassembler": "拆解機",
+ "oc:container.diskdrive": "硬碟機",
+ "oc:container.printer": "印表機",
+ "oc:container.raid": "磁碟陣列機(NAS)",
+ "oc:container.relay": "中繼器",
+ "oc:container.server": "伺服器",
+ "oc:container.rack": "伺服器機架",
+ "oc:container.switch": "路由器",
+ "oc:container.tabletwrapper": "平板電腦",
+ "key.opencomputers.clipboardPaste": "貼上剪貼簿",
+ "key.opencomputers.materialCosts": "顯示材料成本",
+ "oc:tooltip.accesspoint": "就像一個切換器,但它會接收無線封包並且轉換無線的封包變成有線的封包.",
+ "oc:tooltip.abstractbuscard": "允許與 §fStargateTech 2§7 抽象卡傳送與接收 LIP 封包.",
+ "oc:tooltip.acid": "一種有毒的假液相物質,通常只有某些海盜會使用它們.\n它的腐蝕特性令它非常完美地適用于蝕刻電路板的材料.",
+ "oc:tooltip.adapter": "用于控制非電腦組件的方塊,\n比如原版或者來自其他模組的方塊.",
+ "oc:tooltip.alu": "用來做算邏運算以免你親自代勞,\n它更勝任這份差事.",
+ "oc:tooltip.analyzer": "用于顯示方塊信息,比如它們的§f地址§7和§f組件名稱§7.\n如果計算機未能正常關閉它也會顯示使得計算機崩潰的報錯.",
+ "oc:tooltip.apu": "這是 CPU 組成 GPU (或 IGP)的一個處理器, 如果你需要額外的卡片插槽,他可以讓你減少一片顯示卡.\n支援的零組件: §f%s§7\n最大分辨率: §f%sx%s§7\n最大顏色深度: §f%s§7\n運作/tick: §f%s§7",
+ "oc:tooltip.assembler": "機器組裝台可以從不同的電腦零組件來組裝一台機器人。",
+ "oc:tooltip.cable": "連接方塊的廉價選擇.",
+ "oc:tooltip.capacitor": "儲能以備他用.\n能夠非常快速地充電放電.",
+ "oc:tooltip.cardbase": "正如其名,它是用來安裝其他擴展卡的基本卡板.",
+ "oc:tooltip.case": "計算機電腦機殼是構建計算機的基本方塊,\n也是各種§f介面卡§7,§f記憶體§7以及§f硬碟§7的外殼.\n格子: §f%s§7",
+ "oc:tooltip.chamelium": "3D列印的原料. 不可吞食: 會導致失明與臨時性身體消失",
+ "oc:tooltip.chameliumblock": "乾淨清潔. 方便用於3D列印, 只是一個純色的乾淨方塊, 彩色方塊可以讓你發揮創意",
+ "oc:tooltip.charger": "將電容器的能量傳輸給相鄰機器人.\n傳輸效率取決于輸入的§f紅石信號§7強度,無信號意味著不給機器人充電,而最強信號則意味著全速給機器人充電.",
+ "oc:tooltip.circuitboard": "現在我們已經取得一些進展.\n可以通過蝕刻來得到印制板.",
+ "oc:tooltip.controlunit": "用來控制...控制東西...的單元.\n你需要這玩意兒來做CPU.所以反正啦,這個非常重要.",
+ "oc:tooltip.componentbus": "這個擴充套件能讓伺服器同時與更多組件通訊, 工作原理類似CPU.\n支援的組件: §f%s§7.",
+ "oc:tooltip.cpu": "所有計算機最核心的組件,它的時鐘頻率有點不可靠,\n但是你考慮到它是靠便攜日晷來運行的你還能指望啥呢?",
+ "oc:tooltip.cpu.architecture": "架構: §f%s§7",
+ "oc:tooltip.cuttingwire": "用于將粘土塊切割成電路板的形狀.\n使用一次就會壞掉,這可能使得成為歷來最低效的工具.",
+ "oc:tooltip.datacard0": "提供了一些先進的演算法,如散列處理以及 deflate/inflate.",
+ "oc:tooltip.datacard1": "提供了一些先進的演算法,如散列處理, AES 加密 以及 deflate/inflate.",
+ "oc:tooltip.datacard2": "提供了一些先進的演算法,如散列處理, AES 加密, elliptic curve cryptography and deflate/inflate.",
+ "oc:tooltip.debugcard": "創造模式物品, 它能讓你更簡易的操控世界來進行測試. 請自己承擔它帶來的危險.",
+ "oc:tooltip.debugger": "可以使用輸出錯誤訊息到 OC's 網路. 只能使用在開發模式.",
+ "oc:tooltip.disassembler": "拆解還原成它原來的零組件 §l警告§7: 拆解物品過程中 %s%% 有可能破壞掉這些零組件!",
+ "oc:tooltip.disk": "用於制造持久存儲設備的原始媒介材料.",
+ "oc:tooltip.diskdrive.cc": "已經§a支持§7使用另一個電腦模組(ComputerCraft)的軟碟.",
+ "oc:tooltip.diskdrive": "用來讀寫軟碟.",
+ "oc:tooltip.diskusage": "磁碟使用量: %s/%s Byte",
+ "oc:tooltip.diskmodemanaged": "模式: 受管",
+ "oc:tooltip.diskmodeunmanaged": "模式: 非受管",
+ "oc:tooltip.drone": "無人機重量輕,速度快的偵察部隊,擁有有限的載貨空間。",
+ "oc:tooltip.dronecase": "這個外殼是用來建立無人機的組裝外殼。它有足夠的空間用於少量組件,並終界石供電懸浮。",
+ "oc:tooltip.eeprom": "非常小的程式化儲存裝置,可裝入電腦 BIOS 用來開機.",
+ "oc:tooltip.fakeendstone": "幾乎一樣好真實的東西,甚至模仿其floatiness!",
+ "oc:tooltip.geolyzer": "允許掃描周邊地區的方塊硬度,這個訊息可用於產生區域的全息圖,或用來檢測礦石是非常有用的.",
+ "oc:tooltip.graphicscard": "用來改變顯示器顯示內容.\n最高分辨率: §f%sx%s§7\n最大色深: §f%s§7",
+ "oc:tooltip.hoverboots": "跳得更高, 跌幅更深, 走得更快. 這是一個全新專利的 懸停靴 (TM).",
+ "oc:tooltip.inkcartridge": "用於填充墨水的3D打印機。很神奇的原理,不必保留在印表機中。",
+ "oc:tooltip.inkcartridgeempty": "這個墨盒已經被吸乾。用染料填充它。或者把它扔掉。看看你是否在乎。",
+ "oc:tooltip.internetcard": "這個介面卡允許你發出 HTTP要求到真實的 TCP sockets.",
+ "oc:tooltip.interweb": "恭喜,你贏取了 (1) 因特網,你可以使用網路卡連接它,小心,不要餵食巨魔.",
+ "oc:tooltip.ironnugget": "顆粒狀的鐵,所以叫鐵粒啦,蠢蠢的感覺...",
+ "oc:tooltip.keyboard": "可以連接顯示器,能夠輸入顯示文本.",
+ "oc:tooltip.hologram0": "可以透過電腦進行控制以顯示任意像素體積的結構體.\n解析度: §f48x32x48§7\n最大縮放: §f3x§7\n色深: §f單色§7",
+ "oc:tooltip.hologram1": "可以透過電腦進行控制以顯示任意像素體積的結構體.\n解析度: §f48x32x48§7\n最大縮放: §f4x§7\n色深: §f三色§7",
+ "oc:tooltip.linkedcard": "這些都是製作成對的,而且只能與它的合作卡通訊,然而,它可以在任何距離,甚至是誇世界溝通,但是發送訊息的消耗的能量非常高.",
+ "oc:tooltip.linkedcard_channel": "§8頻道: %s§7",
+ "oc:tooltip.manual": "所有你需要知道開放式電腦模組的訊息都在裡面.而且他的需求非常便宜... §o請按 R 繼續§7.",
+ "oc:tooltip.materialcosts": "按著 [§f%s§7] 顯示材料成本.",
+ "oc:tooltip.materials": "需求材料:",
+ "oc:tooltip.memory": "電腦運行必備.\n記憶體越大,你就可以運行越復雜的程序.",
+ "oc:tooltip.microchip": "通常也管這種芯片叫集成電路.\n我也不知道為啥能和紅石一起運行,但事實如此啊.",
+ "oc:tooltip.microcontroller": "微控制器是一部小型電腦. 它的目的是在處理非常具體的任務, 只能執行儲存在 EEPROM 的單一獨立程式.\n§c無法連結外部零組件.§7",
+ "oc:tooltip.microcontrollercase": "微控制器的基本組件. 將其放入組裝機裡添加其他的零組件",
+ "oc:tooltip.motionsensor": "可以檢測到附近活物的移動,需要在視線內不能有阻擋物.",
+ "oc:tooltip.nanomachines": "如果你敢,插入控制單元與一組奈米機器",
+ "oc:tooltip.networkcard": "允許通過其他方塊(比如線纜)相連的遠程計算機能夠向彼此發送信息進行交互.",
+ "oc:tooltip.poweracceptor": "能源轉換速度: §f%s/t§7",
+ "oc:tooltip.powerconverter.BuildCraft": "§f建築模組minecraft焦耳(BC-MJ)§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Factorization": "§f因式分解 (Charge)§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.IndustrialCraft2": "§f工業時代 EU(IC²-EU)§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.Mekanism": "§f通用機器焦耳(Joules)§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ThermalExpansion": "§f熱能擴展RF(TE-RF)§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter.ResonantEngine": "§f諧振引擎庫侖§7: §a%s:%s§7",
+ "oc:tooltip.powerconverter": "將其他模組的能量轉化為本模組的內部能源形式.轉換率:",
+ "oc:tooltip.powerdistributor": "在不同網絡中分配能量.\n用來通過包含多個理論上獨立的子網絡的轉換器在系統中共享能量時很實用.",
+ "oc:tooltip.present": "... for your troubles. Open this present for a chance to receive some §kphat lewt§7!\n§8Craft OpenComputers items when the time is right for a chance to receive a present.§7",
+ "oc:tooltip.print.BeaconBase": "§8一盞燈的基座",
+ "oc:tooltip.print.LightValue": "§8發出的光: %s.",
+ "oc:tooltip.print.RedstoneLevel": "§8紅石輸出: %s.",
+ "oc:tooltip.printedcircuitboard": "基本的構建方塊用來裝入擴充卡與記憶體模組",
+ "oc:tooltip.printer": "允許使用玩家自定義的墨水匣 Chamelium 與 Ink Cartridges. 必須使用電腦來進行配置. 遠離小朋友",
+ "oc:tooltip.raid": "使用三個硬碟機然後連接電腦成為一個更大容量的資料儲存系統",
+ "oc:tooltip.printedcircuitboard": "擴展卡,記憶體等的基板.",
+ "oc:tooltip.rawcircuitboard": "能夠在熔爐或者類似爐子中加工強化成其他材料.",
+ "oc:tooltip.redstone": "能夠在方塊周圍接收以及發送紅石信號.\n可以被與之相連的計算機控制.基本上就像一個外置紅石卡.",
+ "oc:tooltip.redstonecard.ProjectRed": "已經§a支持§fProjectRed§7.",
+ "oc:tooltip.redstonecard.RedLogic": "已經§a支持§7§f紅石邏輯(RedLogic)§7中的紅石系統.",
+ "oc:tooltip.redstonecard.RedNet": "已經§a支援§7MFR中的§f紅石網絡(RedNet)§7.",
+ "oc:tooltip.redstonecard.WirelessCBE": "已經§a支援§f無線紅石 (ChickenBones)§7.",
+ "oc:tooltip.redstonecard.WirelessSV": "已經§a支援§f無線紅石 (SlimeVoid)§7.",
+ "oc:tooltip.redstonecard": "能夠在計算機和機器人四周接收以及發送紅石信號.",
+ "oc:tooltip.robot": "和計算機不同,機器人能夠移動并且像玩家那些與世界之中的東西交互.\n然而,它們§o不能§r§7直接與外設進行交互!",
+ "oc:tooltip.robot_level": "§f等級§7: §a%s§7.",
+ "oc:tooltip.robot_storedenergy": "§f儲能§7: §a%s§7.",
+ "oc:tooltip.screen": "由電腦機殼內的顯示卡控制來顯示文字.\n最高分辨率: §f%sx%s§7\n最大色深: §f%s§7",
+ "oc:tooltip.server": "這是一台伺服器, 他非常棒, 但是他可以使用元件去升級他功能就像電腦一樣. 他可以插入伺服器機架上執行.",
+ "oc:tooltip.server.Components": "安裝的元件:",
+ "oc:tooltip.rack": "提供安裝最多達四個伺服器。為每個伺服器提供了一個內置的虛擬鍵盤和螢幕元件,相當於一個遠程終端。",
+ "oc:tooltip.switch": "允許設備相互連接不同的網絡.\n僅能傳遞網絡信息,通過路由器方式設備并不互相可見.\n例如可以通過這種方式來建立獨立網絡但仍允許其使用網卡通訊.",
+ "oc:tooltip.tablet": "一台平板電腦, 可以在旅行中使用LUA. 使用潛行按鍵來啟動或是關閉他",
+ "oc:tooltip.tabletcase": "平板電腦的機殼,將它放置在機器組裝台內製作一台平板電腦",
+ "oc:tooltip.terminal": "允許遠程控制伺服器,只要你在它的範圍內。就像一個隨身型螢幕和鍵盤。按住Shift鍵並滑鼠右鍵單擊某個服務器的服務器機架終端綁定它。",
+ "oc:tooltip.texturepicker": "可以工具允許顯示方塊該面向的紋理描述, 主要用於3D印表機. 完全沒有紋理名字,沒了!",
+ "oc:tooltip.tier": "§8等級 %s",
+ "oc:tooltip.netsplitter": "作為一個動態連接器。每邊的連接可以通過用扳手擊中它進行切換。所有邊的連接可以通過應用紅石信號反轉。",
+ "oc:tooltip.toolong": "按住潛行鍵([§f%s§7])以查看詳細提示信息.",
+ "oc:tooltip.transistor": "在多數其他計算機的零件中都很基礎的元件.\n引腳有點彎了,但還能用。",
+ "oc:tooltip.transposer": "允許相鄰的箱子與液體容器之間的物品液體transferral",
+ "oc:tooltip.upgradeangel": "讓機器人能夠憑空放置方塊在任何地方,即使沒有參考點可以依附放置。",
+ "oc:tooltip.upgradebattery": "增加機器人可儲存的能量,讓它可以工作更長的時間不需要補充能量.\n容量: §f%s§7",
+ "oc:tooltip.upgradechunkloader": "如果機器人在森林中移動,周圍沒有其他玩家,它真的會動嗎? 這個升級組件可以確保它持續地在作用中,它使區塊持續在載入狀態,但會不斷消耗能量,維持它。",
+ "oc:tooltip.upgradecontainercard": "這個集裝箱升級組件允許動態裝配機器人內的某個插卡.\n最大等級: §f%s§7",
+ "oc:tooltip.upgradecontainerupgrade": "這個集裝箱升級組件允許動態裝配機器人內的某個升級組件\n最大等級: §f%s§7",
+ "oc:tooltip.upgradecrafting": "使得機器人能夠將其物品欄的左上區域作為合成網格來制做物品.\n物品欄內物品擺放必須與工作臺中一致.",
+ "oc:tooltip.upgradedatabase": "這個升級允許儲存用於檢索與其他組件的堆疊訊息.\n支持的條目: §f%s§7",
+ "oc:tooltip.upgradeexperience": "這個升級組件,能夠讓機器人執行各種操作,累積更多的經驗,然後它會獲得更多的能量,更多的儲存空間,速度更快,它收割更有效率,也能使用工具。",
+ "oc:tooltip.upgradegenerator": "用來不斷地消耗燃料發電,燃燒物品并基于它們的燃燒值隨著時間推移產生電力.\n§f效率§7: §a%s%%§7。",
+ "oc:tooltip.upgradehover": "可以升級可以讓機器人飛離地面更高,而且不用爬牆.\n最大高度: §f%s§7",
+ "oc:tooltip.upgradeinventory": "這個升級組件提供機器人一個物品放置的空間,沒有這個升級組件,機器人將不能再內部儲存任何物品。",
+ "oc:tooltip.upgradeinventoryController": "這個升級組件可以讓機器人更好的控制如何與外部互動物品,並且允許他交換或是裝備物品欄內的工具。",
+ "oc:tooltip.upgradeleash": "允許一些設備,如無人機, 來綁定 Isaa- excuse me... *chatter* My apologies. 我只是被告知這其實是用來綁住多種動物在木樁上.",
+ "oc:tooltip.upgradenavigation": "可以用來確定機器人的位置和方向。該位置是相對於被用來製作這個升級地圖的中心。",
+ "oc:tooltip.upgradepiston": "這個升級十分有用. 它能讓機器人像活塞那樣移動方塊, 但 §l不能§7 移動實體.",
+ "oc:tooltip.upgradesign": "允許讀取文字與寫入文字到告示牌",
+ "oc:tooltip.upgradesolarGenerator": "在移動中可以從陽光獲取能量. 機器人上方必須保持無遮蔽狀態才能. 產生能量 %s%% 速度的能量給引擎。",
+ "oc:tooltip.upgradetank": "為你的機器人裝上一個可存儲流體的水箱. 如果沒有升級此功能, 你的機器人將無法在內部存儲流體.",
+ "oc:tooltip.upgradetankcontroller": "這個升級能讓你的機器人與外界水箱交互, 向其傳輸流體.",
+ "oc:tooltip.upgradetractorbeam": "裝備機器人具有非常先進的技術,綽號\"物品磁鐵\"。它能夠拾取三個方塊內的任何地方。",
+ "oc:tooltip.waypoint": "提供一個參考點到與導航設備的升級。",
+ "oc:tooltip.wirelessnetworkcard": "允許在發送正常信息外無線發送網絡信息.\n請確保已設置好§f信號強度§7否則不會發出無線數據包。",
+ "oc:tooltip.worldsensorcard": "允許讀取世界訊息,比如重力,以及是否在大氣下,傳回結果.",
+ "oc:tooltip.wrench": "螺絲刀和扳手的混合體,這個工具是簡單易學,但很難掌握。",
+ "achievement.oc.adapter": "插上寶寶",
+ "achievement.oc.adapter.desc": "Interact with blocks from other mods and even vanilla Minecraft!",
+ "achievement.oc.assembler": "美妙",
+ "achievement.oc.assembler.desc": "Time to take over the world!",
+ "achievement.oc.cable": "不是一個骯髒的電線",
+ "achievement.oc.cable.desc": "With patented anti-cable-spaghetti technology.",
+ "achievement.oc.capacitor": "包括電池",
+ "achievement.oc.capacitor.desc": "You cannot stop it.",
+ "achievement.oc.card": "我們接受信用卡",
+ "achievement.oc.card.desc": "For your convenience. No ulterior motive, promise.",
+ "achievement.oc.case": "出現故障時",
+ "achievement.oc.case.desc": "Because cuboid towers are the best.",
+ "achievement.oc.charger": "好吧,讓我們做到這一點",
+ "achievement.oc.charger.desc": "Chaaaaaaaaaarg- dang, forgot the redstone signal again.",
+ "achievement.oc.chip": "所有小事",
+ "achievement.oc.chip.desc": "Because vacuum tubes are so yesteryear.",
+ "achievement.oc.cpu": "超頻",
+ "achievement.oc.cpu.desc": "Time to make good use of those computing cycles.",
+ "achievement.oc.disassembler": "從頭開始",
+ "achievement.oc.disassembler.desc": "In case one of your brilliant ideas turns out to be not that brilliant after all.",
+ "achievement.oc.diskDrive": "環狀交叉路",
+ "achievement.oc.diskDrive.desc": "Inferior capacity but such delicious sound.",
+ "achievement.oc.drone": "飛走",
+ "achievement.oc.drone.desc": "Keep calm and nuke it from orbit.",
+ "achievement.oc.eeprom": "只能有1",
+ "achievement.oc.eeprom.desc": "Per computer, that is. For deterministic boot order, you know?",
+ "achievement.oc.floppy": "在一個RI-磁碟",
+ "achievement.oc.floppy.desc": "Not to be confused with Flappy.",
+ "achievement.oc.geolyzer": "腳踏實地",
+ "achievement.oc.geolyzer.desc": "It has extraordinary qualities.",
+ "achievement.oc.graphicsCard": "LastGen",
+ "achievement.oc.graphicsCard.desc": "The way it's meant to be... uh... rendered. Yeah. That.",
+ "achievement.oc.hdd": "熱狗經銷商",
+ "achievement.oc.hdd.desc": "No wait, that's not what that meant. Hang on, almost got it...",
+ "achievement.oc.hologram": "下一個維度",
+ "achievement.oc.hologram.desc": "Because 2D is boring. Or is it?",
+ "achievement.oc.keyboard": "DirtCatcher3000",
+ "achievement.oc.keyboard.desc": "It is highly recommended to resist the urge to flip them around and shake them.",
+ "achievement.oc.microcontroller": "小妹妹",
+ "achievement.oc.microcontroller.desc": "The small sibling of computers.",
+ "achievement.oc.motionSensor": "能動",
+ "achievement.oc.motionSensor.desc": "Like Steve Swagger.",
+ "achievement.oc.networkCard": "現在我們談論!",
+ "achievement.oc.networkCard.desc": "Keep in touch with those distant relatives via transitive relations.",
+ "achievement.oc.openOS": "開機",
+ "achievement.oc.openOS.desc": "One OS to - wait, I used that one already? Dang.",
+ "achievement.oc.powerDistributor": "共享是關懷",
+ "achievement.oc.powerDistributor.desc": "When you need some help balancing all that power.",
+ "achievement.oc.rack": "Dat Rack",
+ "achievement.oc.rack.desc": "I don't know what you're thinking of, I clearly meant the server rack.",
+ "achievement.oc.raid": "LFG",
+ "achievement.oc.raid.desc": "Heroic plzkthx.",
+ "achievement.oc.ram": "隨機存取存儲器",
+ "achievement.oc.ram.desc": "Congratulations, you're Doin' It Right.",
+ "achievement.oc.redstoneCard": "聯繫",
+ "achievement.oc.redstoneCard.desc": "Time to go analog.",
+ "achievement.oc.redstoneIO": "局外人",
+ "achievement.oc.redstoneIO.desc": "Taking redstone signals where you want them.",
+ "achievement.oc.robot": "嗶布普",
+ "achievement.oc.robot.desc": "EXTERMINATE!",
+ "achievement.oc.screen": "Have you tried turning it off and on again?",
+ "achievement.oc.screen.desc": "No seriously. A redstone pulse can toggle a screen's power, after all.",
+ "achievement.oc.server": "專用",
+ "achievement.oc.server.desc": "雲服務,我們來了。",
+ "achievement.oc.switch": "複雜的拓撲",
+ "achievement.oc.switch.desc": "避免易碎物品因遺失資料的可能性。",
+ "achievement.oc.tablet": "不要嚥下",
+ "achievement.oc.tablet.desc": "Also keep away from small children to avoid unexpected overdrawing of your credit card.",
+ "achievement.oc.transistor": "告訴紅石說:“你好。”",
+ "achievement.oc.transistor.desc": "Create a Transistor to get started. Then listen to the soundtrack. No need to thank me.",
+ "achievement.oc.wirelessNetworkCard": "信號",
+ "achievement.oc.wirelessNetworkCard.desc": "Time to go where no packet has gone before.",
+ "death.attack.oc.nanomachinesOverload.1": "%s 獲得貪婪稱號。",
+ "death.attack.oc.nanomachinesOverload.2": "%s 神經衰弱。",
+ "death.attack.oc.nanomachinesOverload.3": "奈米機器 %s 失去控制",
+ "death.attack.oc.nanomachinesHungry.1": "%s 被奈米機器吃掉",
+ "death.attack.oc.nanomachinesHungry.2": "%s 沒有定時餵食奈米機器",
+ "death.attack.oc.nanomachinesHungry.3": "%s 已被消化。",
+ "nei.options.inventory.oredict": "顯示礦物字典名稱",
+ "nei.options.inventory.oredict.true": "真",
+ "nei.options.inventory.oredict.false": "假",
+ "nei.usage.oc.Manual": "打開手冊",
+ "option.oc.address": "位址",
+ "option.oc.componentName": "組件名稱",
+ "option.oc.energy": "能源"
+}
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.32.arm.so b/src/main/resources/assets/opencomputers/lib/lua52/native.32.arm.so
deleted file mode 100644
index e21c6aa412..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.32.arm.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.32.bsd.so b/src/main/resources/assets/opencomputers/lib/lua52/native.32.bsd.so
deleted file mode 100644
index df03aa6683..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.32.bsd.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.32.dll b/src/main/resources/assets/opencomputers/lib/lua52/native.32.dll
deleted file mode 100644
index db48708e32..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.32.dll and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.32.dylib b/src/main/resources/assets/opencomputers/lib/lua52/native.32.dylib
deleted file mode 100644
index 6498ec7e5b..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.32.dylib and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.32.so b/src/main/resources/assets/opencomputers/lib/lua52/native.32.so
deleted file mode 100644
index 4c47ab5ee3..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.32.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.64.bsd.so b/src/main/resources/assets/opencomputers/lib/lua52/native.64.bsd.so
deleted file mode 100644
index 715dccfaba..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.64.bsd.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.64.dll b/src/main/resources/assets/opencomputers/lib/lua52/native.64.dll
deleted file mode 100644
index 0b31407532..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.64.dll and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.64.dylib b/src/main/resources/assets/opencomputers/lib/lua52/native.64.dylib
deleted file mode 100644
index b7e7f4a182..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.64.dylib and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua52/native.64.so b/src/main/resources/assets/opencomputers/lib/lua52/native.64.so
deleted file mode 100644
index c6fe8fa82b..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua52/native.64.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.32.bsd.so b/src/main/resources/assets/opencomputers/lib/lua53/native.32.bsd.so
deleted file mode 100644
index a0d0445993..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.32.bsd.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.32.dll b/src/main/resources/assets/opencomputers/lib/lua53/native.32.dll
deleted file mode 100644
index c19c93dc72..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.32.dll and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.32.dylib b/src/main/resources/assets/opencomputers/lib/lua53/native.32.dylib
deleted file mode 100644
index c95eaacc80..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.32.dylib and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.32.so b/src/main/resources/assets/opencomputers/lib/lua53/native.32.so
deleted file mode 100644
index fc9bb697da..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.32.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.64.bsd.so b/src/main/resources/assets/opencomputers/lib/lua53/native.64.bsd.so
deleted file mode 100644
index f0a919079e..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.64.bsd.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.64.dll b/src/main/resources/assets/opencomputers/lib/lua53/native.64.dll
deleted file mode 100644
index 34d3a19319..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.64.dll and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.64.dylib b/src/main/resources/assets/opencomputers/lib/lua53/native.64.dylib
deleted file mode 100644
index 6702f27498..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.64.dylib and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/lib/lua53/native.64.so b/src/main/resources/assets/opencomputers/lib/lua53/native.64.so
deleted file mode 100644
index bbb8306361..0000000000
Binary files a/src/main/resources/assets/opencomputers/lib/lua53/native.64.so and /dev/null differ
diff --git a/src/main/resources/assets/opencomputers/loot/loot.properties b/src/main/resources/assets/opencomputers/loot/loot.properties
index c1886e02c3..c007863721 100644
--- a/src/main/resources/assets/opencomputers/loot/loot.properties
+++ b/src/main/resources/assets/opencomputers/loot/loot.properties
@@ -7,18 +7,18 @@
#The color defaults to gray. It must be a dye's ore-dict name.
# General purpose.
-network=Network (Network Stack):1:dyeLime
-plan9k=Plan9k (Operating System):1:dyeRed
-irc=OpenIRC (IRC Client):1:dyeLightBlue
-openloader=OpenLoader (Boot Loader):1:dyeMagenta
-openos=OpenOS (Operating System):0:dyeGreen
-oppm=OPPM (Package Manager):0:dyeCyan
+network=Network (Network Stack):1:lime
+plan9k=Plan9k (Operating System):1:red
+irc=OpenIRC (IRC Client):1:light_blue
+openloader=OpenLoader (Boot Loader):1:magenta
+openos=OpenOS (Operating System):0:green
+oppm=OPPM (Package Manager):0:cyan
# Robot utilities.
-builder=Builder:1:dyeYellow
-dig=Digger:2:dyeBrown
-maze=Mazer:1:dyeOrange
+builder=Builder:1:yellow
+dig=Digger:2:brown
+maze=Mazer:1:orange
# Drivers for components.
-data=Data Card Software:0:dyePink
-generator=Generator Upgrade Software:0:dyePurple
+data=Data Card Software:0:pink
+generator=Generator Upgrade Software:0:purple
diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua
index ab07bd6a34..723b04ba8f 100644
--- a/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua
+++ b/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua
@@ -86,7 +86,7 @@ local read_handler = {hint = function(line, index)
return hints
end}
-io.write("\27[37m".._VERSION .. " Copyright (C) 1994-2017 Lua.org, PUC-Rio\n")
+io.write("\27[37m".._VERSION .. " Copyright (C) 1994-2022 Lua.org, PUC-Rio\n")
io.write("\27[33mEnter a statement and hit enter to evaluate it.\n")
io.write("Prefix an expression with '=' to show its value.\n")
io.write("Press Ctrl+D to exit the interpreter.\n\27[37m")
diff --git a/src/main/resources/assets/opencomputers/models/item/cable.json b/src/main/resources/assets/opencomputers/models/item/cable.json
new file mode 100644
index 0000000000..5485f33463
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/cable.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/air"
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyered.json b/src/main/resources/assets/opencomputers/models/item/floppy_black.json
similarity index 56%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyered.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_black.json
index eda33de570..e0820566c1 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyered.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_black.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyered"
+ "layer0": "opencomputers:items/floppy_black"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyeblue.json b/src/main/resources/assets/opencomputers/models/item/floppy_blue.json
similarity index 55%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyeblue.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_blue.json
index 5ab2f34ba8..4da3bf3a04 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyeblue.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_blue.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyeblue"
+ "layer0": "opencomputers:items/floppy_blue"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyelime.json b/src/main/resources/assets/opencomputers/models/item/floppy_brown.json
similarity index 55%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyelime.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_brown.json
index 244c7750a3..ba52c60827 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyelime.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_brown.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyelime"
+ "layer0": "opencomputers:items/floppy_brown"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyecyan.json b/src/main/resources/assets/opencomputers/models/item/floppy_cyan.json
similarity index 55%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyecyan.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_cyan.json
index ef844c9a22..9726f0d09d 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyecyan.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_cyan.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyecyan"
+ "layer0": "opencomputers:items/floppy_cyan"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyegreen.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyegreen.json
deleted file mode 100644
index 915a2910e7..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyegreen.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyegreen"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyelightblue.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyelightblue.json
deleted file mode 100644
index 635991a8ca..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyelightblue.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyelightblue"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyelightgray.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyelightgray.json
deleted file mode 100644
index 3eadf282bb..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyelightgray.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyelightgray"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyemagenta.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyemagenta.json
deleted file mode 100644
index be3ff99ca4..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyemagenta.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyemagenta"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyeorange.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyeorange.json
deleted file mode 100644
index c2860686cd..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyeorange.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyeorange"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyepink.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyepink.json
deleted file mode 100644
index 3ac45505d5..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyepink.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyepink"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyepurple.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyepurple.json
deleted file mode 100644
index 4c13535ad3..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyepurple.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyepurple"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyewhite.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyewhite.json
deleted file mode 100644
index a8f9b07b06..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyewhite.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyewhite"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyeyellow.json b/src/main/resources/assets/opencomputers/models/item/floppy_dyeyellow.json
deleted file mode 100644
index 911ca8afba..0000000000
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyeyellow.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "parent": "opencomputers:item/flat",
- "textures": {
- "layer0": "opencomputers:items/floppy_dyeyellow"
- }
-}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_gray.json b/src/main/resources/assets/opencomputers/models/item/floppy_gray.json
new file mode 100644
index 0000000000..4dd9bd3ce3
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_gray.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_gray"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_green.json b/src/main/resources/assets/opencomputers/models/item/floppy_green.json
new file mode 100644
index 0000000000..d7c33188fc
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_green.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_green"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyeblack.json b/src/main/resources/assets/opencomputers/models/item/floppy_light_blue.json
similarity index 54%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyeblack.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_light_blue.json
index 263e9e5997..54f58d4304 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyeblack.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_light_blue.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyeblack"
+ "layer0": "opencomputers:items/floppy_light_blue"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyebrown.json b/src/main/resources/assets/opencomputers/models/item/floppy_light_gray.json
similarity index 54%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyebrown.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_light_gray.json
index c3209a408f..d2c929426f 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyebrown.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_light_gray.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyebrown"
+ "layer0": "opencomputers:items/floppy_light_gray"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_lime.json b/src/main/resources/assets/opencomputers/models/item/floppy_lime.json
new file mode 100644
index 0000000000..fe4dac3318
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_lime.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_lime"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_dyegray.json b/src/main/resources/assets/opencomputers/models/item/floppy_magenta.json
similarity index 55%
rename from src/main/resources/assets/opencomputers/models/item/floppy_dyegray.json
rename to src/main/resources/assets/opencomputers/models/item/floppy_magenta.json
index f66055135d..1f73c298d8 100644
--- a/src/main/resources/assets/opencomputers/models/item/floppy_dyegray.json
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_magenta.json
@@ -1,6 +1,6 @@
{
"parent": "opencomputers:item/flat",
"textures": {
- "layer0": "opencomputers:items/floppy_dyegray"
+ "layer0": "opencomputers:items/floppy_magenta"
}
}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_orange.json b/src/main/resources/assets/opencomputers/models/item/floppy_orange.json
new file mode 100644
index 0000000000..aa239efa60
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_orange.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_orange"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_pink.json b/src/main/resources/assets/opencomputers/models/item/floppy_pink.json
new file mode 100644
index 0000000000..2c9d99b64c
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_pink.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_pink"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_purple.json b/src/main/resources/assets/opencomputers/models/item/floppy_purple.json
new file mode 100644
index 0000000000..b036df4d7a
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_purple.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_purple"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_red.json b/src/main/resources/assets/opencomputers/models/item/floppy_red.json
new file mode 100644
index 0000000000..b1f4c81056
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_red.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_red"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_white.json b/src/main/resources/assets/opencomputers/models/item/floppy_white.json
new file mode 100644
index 0000000000..4fff4486df
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_white.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_white"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/floppy_yellow.json b/src/main/resources/assets/opencomputers/models/item/floppy_yellow.json
new file mode 100644
index 0000000000..8013fb314a
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/floppy_yellow.json
@@ -0,0 +1,6 @@
+{
+ "parent": "opencomputers:item/flat",
+ "textures": {
+ "layer0": "opencomputers:items/floppy_yellow"
+ }
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/netsplitter.json b/src/main/resources/assets/opencomputers/models/item/netsplitter.json
new file mode 100644
index 0000000000..5485f33463
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/netsplitter.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/air"
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/print.json b/src/main/resources/assets/opencomputers/models/item/print.json
new file mode 100644
index 0000000000..5485f33463
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/print.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/air"
+}
diff --git a/src/main/resources/assets/opencomputers/models/item/robot.json b/src/main/resources/assets/opencomputers/models/item/robot.json
new file mode 100644
index 0000000000..5485f33463
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/models/item/robot.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/air"
+}
diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes
deleted file mode 100644
index d8da5c9fb8..0000000000
--- a/src/main/resources/assets/opencomputers/recipes/default.recipes
+++ /dev/null
@@ -1,700 +0,0 @@
-# Do not change this file, it is rewritten each time you start the game.
-# Instead, use the user.recipes file to edit recipes by redefining them there.
-
-analyzer {
- input: [[torchRedstoneActive, "", ""]
- ["oc:materialTransistor", nuggetGold, ""]
- ["oc:materialCircuitBoardPrinted", nuggetGold, ""]]
-}
-hoverboots {
- input: [[iron_nugget, "oc:hoverUpgrade2", iron_nugget]
- [leather, "oc:droneCase1", leather]
- [iron_nugget, "oc:capacitor", iron_nugget]]
-}
-manual {
- type: shapeless
- input: [book, "oc:circuitChip1"]
-}
-nanomachines {
- input: [["oc:chamelium", "oc:wlanCard2", "oc:chamelium"]
- ["oc:cpu2", "oc:materialAcid", "oc:ram1"]
- ["oc:chamelium", "oc:capacitor", "oc:chamelium"]]
-}
-texturepicker {
- input: [[dyeBlack, dyeRed, dyeGreen]
- [dyeBlue, "oc:analyzer", dyePurple]
- [dyeYellow, dyeMagenta, dyeWhite]]
-}
-wrench {
- input: [[ingotIron, "", ingotIron]
- ["", "oc:circuitChip2", ""],
- ["", ingotIron, ""]]
-}
-lootdisks: [
- {
- name: "opencomputers:openos"
- type: shapeless
- input: ["oc:floppy", "oc:manual"]
- },
- {
- name: "opencomputers:oppm"
- type: shapeless
- input: ["oc:floppy", "oc:materialInterweb"]
- }
-]
-luabios {
- type: shapeless
- input: ["oc:eeprom", "oc:manual"]
-}
-
-dronecase1 {
- input: [["oc:stoneEndstone", compass, "oc:stoneEndstone"]
- ["oc:circuitChip1", "oc:microcontrollerCase1", "oc:circuitChip1"]
- ["oc:stoneEndstone", "oc:componentBus2", "oc:stoneEndstone"]]
-}
-dronecase2 {
- input: [["oc:stoneEndstone", compass, "oc:stoneEndstone"]
- ["oc:circuitChip2", "oc:microcontrollerCase2", "oc:circuitChip2"]
- ["oc:stoneEndstone", "oc:componentBus3", "oc:stoneEndstone"]]
-}
-microcontrollercase1 {
- input: [[iron_nugget, "oc:circuitChip1", iron_nugget]
- [redstone, chest, redstone]
- [iron_nugget, "oc:materialCircuitBoardPrinted", iron_nugget]]
-}
-microcontrollercase2 {
- input: [[nuggetGold, "oc:circuitChip3", nuggetGold]
- [blockRedstone, chest, blockRedstone]
- [nuggetGold, "oc:materialCircuitBoardPrinted", nuggetGold]]
-}
-terminal {
- input: [[iron_nugget, "oc:solarGeneratorUpgrade", iron_nugget]
- ["oc:circuitChip3", "oc:screen2", "oc:wlanCard2"]
- [iron_nugget, "oc:keyboard", iron_nugget]]
-}
-tabletcase1 {
- input: [[ingotGold, button, ingotGold]
- ["oc:componentBus1", "oc:screen2", "oc:circuitChip3"]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-tabletcase2 {
- input: [["oc:circuitChip2", button, ingotGold]
- ["oc:componentBus3", "oc:screen2", "oc:circuitChip3"]
- ["oc:circuitChip2", "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-
-diskdrivemountable {
- input: [[obsidian, "oc:circuitChip1", obsidian]
- [fenceIron, "oc:diskDrive", fenceIron]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-server1 {
- input: [[ingotIron, "oc:ram2", ingotIron]
- ["oc:circuitChip1", "oc:componentBus1", "oc:circuitChip1"]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-server2 {
- input: [[ingotGold, "oc:ram4", ingotGold]
- ["oc:circuitChip2", "oc:componentBus2", "oc:circuitChip2"]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-server3 {
- input: [[gemDiamond, "oc:ram6", gemDiamond]
- ["oc:circuitChip3", "oc:componentBus3", "oc:circuitChip3"]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-terminalserver {
- input: [[obsidian, "oc:wlanCard", obsidian]
- ["oc:wlanCard", "oc:circuitChip2", "oc:wlanCard2"]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-
-ram1 {
- input: [["oc:circuitChip1", iron_nugget, "oc:circuitChip1"]
- ["", "oc:materialCircuitBoardPrinted", ""]]
-}
-ram2 {
- input: [["oc:circuitChip1", "oc:circuitChip2", "oc:circuitChip1"]
- ["", "oc:materialCircuitBoardPrinted", ""]]
-}
-ram3 {
- input: [["oc:circuitChip2", iron_nugget, "oc:circuitChip2"]
- ["", "oc:materialCircuitBoardPrinted", ""]]
-}
-ram4 {
- input: [["oc:circuitChip2", "oc:circuitChip3", "oc:circuitChip2"]
- ["", "oc:materialCircuitBoardPrinted", ""]]
-}
-ram5 {
- input: [["oc:circuitChip3", iron_nugget, "oc:circuitChip3"]
- ["", "oc:materialCircuitBoardPrinted", ""]]
-}
-ram6 {
- input: [["oc:circuitChip3", "oc:circuitChip3", "oc:circuitChip3"]
- ["oc:circuitChip2", "oc:materialCircuitBoardPrinted", "oc:circuitChip2"]]
-}
-
-eeprom {
- input: [[nuggetGold, "oc:materialTransistor", nuggetGold]
- [paper, "oc:circuitChip1", paper]
- [nuggetGold, torchRedstoneActive, nuggetGold]]
-}
-floppy {
- input: [[iron_nugget, lever, iron_nugget]
- [paper, "oc:materialDisk", paper]
- [iron_nugget, paper, iron_nugget]]
-}
-hdd1 {
- input: [["oc:circuitChip1", "oc:materialDisk", ingotIron]
- ["oc:materialCircuitBoardPrinted", "oc:materialDisk", craftingPiston]
- ["oc:circuitChip1", "oc:materialDisk", ingotIron]]
-}
-hdd2 {
- input: [["oc:circuitChip2", "oc:materialDisk", ingotGold]
- ["oc:materialCircuitBoardPrinted", "oc:materialDisk", craftingPiston]
- ["oc:circuitChip2", "oc:materialDisk", ingotGold]]
-}
-hdd3 {
- input: [["oc:circuitChip3", "oc:materialDisk", gemDiamond]
- ["oc:materialCircuitBoardPrinted", "oc:materialDisk", craftingPiston]
- ["oc:circuitChip3", "oc:materialDisk", gemDiamond]]
-}
-
-datacard1 {
- input: [[iron_nugget, "oc:materialALU", "oc:circuitChip2"]
- ["", "oc:materialCard", ""]]
-}
-datacard2 {
- input: [[nuggetGold, "oc:cpu1", "oc:circuitChip3"]
- ["", "oc:materialCard", ""]]
-}
-datacard3 {
- input: [[chipDiamond, "oc:cpu2", "oc:ram5"]
- ["", "oc:materialCard", ""]]
-}
-graphicscard1 {
- input: [["oc:circuitChip1", "oc:materialALU", "oc:ram1"]
- ["", "oc:materialCard", ""]]
-}
-graphicscard2 {
- input: [["oc:circuitChip2", "oc:materialALU", "oc:ram3"]
- ["", "oc:materialCard", ""]]
-}
-graphicscard3 {
- input: [["oc:circuitChip3", "oc:materialALU", "oc:ram5"]
- ["", "oc:materialCard", ""]]
-}
-internetcard {
- input: [["oc:materialInterweb", "oc:circuitChip2", torchRedstoneActive]
- ["", "oc:materialCard", obsidian]]
-}
-redstonecard1 {
- input: [[torchRedstoneActive, "oc:circuitChip1", ""]
- ["", "oc:materialCard", ""]]
-}
-redstonecard2 {
- input: [[blockRedstone, "oc:circuitChip2", materialEnderPearl]
- ["", "oc:materialCard", ""]]
-}
-lancard {
- input: [["oc:cable", "oc:circuitChip1", ""]
- ["", "oc:materialCard", ""]]
-}
-wlancard1 {
- input: [[torchRedstoneActive, "oc:circuitChip1", torchRedstoneActive]
- ["", "oc:materialCard", ""]]
-}
-wlancard2 {
- input: [[materialEnderPearl, "oc:circuitChip2", ""]
- ["", "oc:materialCard", ""]]
-}
-linkedcard {
- input: [[eyeOfEnder, "", eyeOfEnder]
- ["oc:lanCard", "oc:materialInterweb", "oc:lanCard"]
- ["oc:circuitChip3", "", "oc:circuitChip3"]]
- output: 2 # Note: all resulting cards are linked to each other.
-}
-
-abstractbuscard {
- input: [[{block="StargateTech2:block.busCable"}, {item="StargateTech2:naquadah", subID=3}, ""]
- ["", "oc:materialCard", ""]]
-}
-worldsensorcard {
- input: [[{item="galacticraftcore:sensor_lens"}, "oc:circuitChip2", ""]
- ["", "oc:materialCard", ""]]
-}
-
-angelupgrade {
- input: [[ingotIron, materialEnderPearl, ingotIron]
- ["oc:circuitChip1", pistonStickyBase, "oc:circuitChip1"]
- [ingotIron, materialEnderPearl, ingotIron]]
-}
-batteryupgrade1 {
- input: [[iron_nugget, nuggetGold, iron_nugget]
- [fenceIron, "oc:capacitor", fenceIron]
- [iron_nugget, nuggetGold, iron_nugget]]
-}
-batteryupgrade2 {
- input: [[iron_nugget, "oc:capacitor", iron_nugget]
- [fenceIron, nuggetGold, fenceIron]
- [iron_nugget, "oc:capacitor", iron_nugget]]
-}
-batteryupgrade3 {
- input: [[iron_nugget, "oc:capacitor", iron_nugget]
- ["oc:capacitor", chipDiamond, "oc:capacitor"]
- [iron_nugget, "oc:capacitor", iron_nugget]]
-}
-chunkloaderupgrade {
- input: [[ingotGold, blockGlass, ingotGold]
- ["oc:circuitChip3", eyeOfEnder, "oc:circuitChip3"]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-craftingupgrade {
- input: [[ingotIron, "", ingotIron]
- ["oc:circuitChip1", workbench, "oc:circuitChip1"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-databaseupgrade1 {
- input: [[ingotIron, "oc:analyzer", ingotIron]
- ["oc:circuitChip1", "oc:hdd1", "oc:circuitChip1"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-databaseupgrade2 {
- input: [[ingotIron, "oc:analyzer", ingotIron]
- ["oc:circuitChip2", "oc:hdd2", "oc:circuitChip2"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-databaseupgrade3 {
- input: [[ingotIron, "oc:analyzer", ingotIron]
- ["oc:circuitChip3", "oc:hdd3", "oc:circuitChip3"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-experienceupgrade {
- input: [[ingotGold, "", ingotGold]
- ["oc:circuitChip2", emerald, "oc:circuitChip2"]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-generatorupgrade {
- input: [[ingotIron, "", ingotIron]
- ["oc:circuitChip1", craftingPiston, "oc:circuitChip1"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-hoverupgrade1 {
- input: [[feather, "oc:circuitChip1", feather]
- [iron_nugget, leather, iron_nugget]
- [feather, "oc:materialCircuitBoardPrinted", feather]]
-}
-hoverupgrade2 {
- input: [["oc:stoneEndstone", "oc:circuitChip2", "oc:stoneEndstone"]
- [nuggetGold, ingotIron, nuggetGold]
- ["oc:stoneEndstone", "oc:materialCircuitBoardPrinted", "oc:stoneEndstone"]]
-}
-inventoryupgrade {
- input: [[plankWood, hopper, plankWood]
- [dropper, chest, craftingPiston]
- [plankWood, "oc:circuitChip1", plankWood]]
-}
-inventorycontrollerupgrade {
- input: [[ingotGold, "oc:analyzer", ingotGold]
- [dropper, "oc:circuitChip2", craftingPiston]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-mfu {
- input: [["oc:chamelium", gemLapis, "oc:chamelium"]
- ["oc:linkedCard", "oc:adapter", "oc:linkedCard"]
- ["oc:chamelium", gemLapis, "oc:chamelium"]]
-}
-leashupgrade {
- input: [[ingotIron, {item="minecraft:lead"}, ingotIron]
- [{item="minecraft:lead"}, "oc:materialCU", {item="minecraft:lead"}]
- [ingotIron, {item="minecraft:lead"}, ingotIron]]
-}
-navigationupgrade {
- input: [[ingotGold, compass, ingotGold]
- ["oc:circuitChip2", {item=filled_map, subID=any}, "oc:circuitChip2"]
- [ingotGold, potion, ingotGold]]
-}
-pistonupgrade {
- input: [[ingotIron, craftingPiston, ingotIron]
- [stickWood, "oc:circuitChip1", stickWood]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-stickypistonupgrade {
- type: shapeless
- input: ["oc:pistonUpgrade", "minecraft:slime_ball"]
- output: 1
-}
-signupgrade {
- input: [[ingotIron, dyeBlack, ingotIron]
- ["oc:circuitChip1", stickWood, "oc:circuitChip1"]
- [ingotIron, pistonStickyBase, ingotIron]]
-}
-solargeneratorupgrade {
- input: [[blockGlass, blockGlass, blockGlass]
- ["oc:circuitChip3", blockLapis, "oc:circuitChip3"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-tankupgrade {
- input: [[plankWood, fenceIron, plankWood]
- [dispenser, cauldron, craftingPiston]
- [plankWood, "oc:circuitChip1", plankWood]]
-}
-tankcontrollerupgrade {
- input: [[ingotGold, glassBottle, ingotGold]
- [dispenser, "oc:circuitChip2", craftingPiston]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-tractorbeamupgrade {
- input: [[ingotGold, craftingPiston, ingotGold]
- [ingotIron, "oc:capacitor", ingotIron]
- [ingotGold, "oc:circuitChip3", ingotGold]]
-}
-tradingupgrade {
- input: [[ingotGold, chest, ingotGold]
- [emerald, "oc:circuitChip2", emerald]
- [dropper, "oc:materialCircuitBoardPrinted", craftingPiston]]
-}
-
-cardcontainer1 {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- [craftingPiston, chest, ""]
- [ingotIron, "oc:materialCard", ingotIron]]
-}
-cardcontainer2 {
- input: [[ingotIron, "oc:circuitChip2", ingotIron]
- [craftingPiston, chest, ""]
- [ingotIron, "oc:materialCard", ingotIron]]
-}
-cardcontainer3 {
- input: [[ingotGold, "oc:circuitChip2", ingotGold]
- [craftingPiston, chest, ""]
- [ingotGold, "oc:materialCard", ingotGold]]
-}
-upgradecontainer1 {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- [craftingPiston, chest, ""]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-upgradecontainer2 {
- input: [[ingotIron, "oc:circuitChip2", ingotIron]
- [craftingPiston, chest, ""]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-upgradecontainer3 {
- input: [[ingotGold, "oc:circuitChip2", ingotGold]
- [craftingPiston, chest, ""]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-
-ingotiron {
- type: shapeless
- input: [iron_nugget, iron_nugget, iron_nugget,
- iron_nugget, iron_nugget, iron_nugget,
- iron_nugget, iron_nugget, iron_nugget]
-}
-chipdiamond {
- type: shapeless
- input: ["oc:materialCuttingWire", gemDiamond]
- output: 6
-}
-gemDiamond = false
-
-cuttingwire {
- input: [[stickWood, nuggetIron, stickWood]]
-}
-acid {
- type: shapeless
- input: [bucketWater, sugar, slimeball, fermentedSpiderEye, bone]
-}
-disk {
- input: [["", iron_nugget, ""]
- [iron_nugget, "", iron_nugget]
- ["", iron_nugget, ""]]
-}
-chamelium {
- input: [[gravel, redstone, gravel],
- [redstone, {item=coal, subID=1}, redstone],
- [gravel, {item="minecraft:water_bucket"}, gravel]]
- output: 16
-}
-chameliumblock {
- input: [["oc:chamelium", "oc:chamelium", "oc:chamelium"],
- ["oc:chamelium", "oc:chamelium", "oc:chamelium"],
- ["oc:chamelium", "oc:chamelium", "oc:chamelium"]]
-}
-endstone {
- input: [[materialEnderPearl, "oc:chameliumBlock", materialEnderPearl]
- ["oc:chameliumBlock", materialEnderPearl, "oc:chameliumBlock"]
- [materialEnderPearl, "oc:chameliumBlock", materialEnderPearl]]
- output: 4
-}
-inkcartridgeempty {
- input: [[iron_nugget, dispenser, iron_nugget],
- ["oc:materialTransistor", bucket, "oc:materialTransistor"],
- [iron_nugget, "oc:materialCircuitBoardPrinted", iron_nugget]]
-}
-inkcartridge {
- type: shapeless
- input: [dyeCyan, dyeMagenta, dyeYellow, dyeBlack, "oc:inkCartridgeEmpty"]
-}
-
-buttongroup {
- input: [[button, button, button]
- [button, button, button]]
-}
-arrowkeys {
- input: [["", button, ""]
- [button, button, button]]
-}
-numpad {
- input: [[button, button, button]
- [button, button, button]
- [button, button, button]]
-}
-
-transistor {
- input: [[ingotIron, ingotIron, ingotIron]
- [nuggetGold, paper, nuggetGold]
- ["", redstone, ""]]
- output: 8
-}
-chip1 {
- input: [[iron_nugget, iron_nugget, iron_nugget]
- [redstone, "oc:materialTransistor", redstone]
- [iron_nugget, iron_nugget, iron_nugget]]
- output: 8
-}
-chip2 {
- input: [[nuggetGold, nuggetGold, nuggetGold]
- [redstone, "oc:materialTransistor", redstone]
- [nuggetGold, nuggetGold, nuggetGold]]
- output: 4
-}
-chip3 {
- input: [[chipDiamond, chipDiamond, chipDiamond]
- [redstone, "oc:materialTransistor", redstone]
- [chipDiamond, chipDiamond, chipDiamond]]
- output: 2
-}
-alu {
- input: [[iron_nugget, redstone, iron_nugget]
- ["oc:materialTransistor", "oc:circuitChip1", "oc:materialTransistor"]
- [iron_nugget, "oc:materialTransistor", iron_nugget]]
-}
-apu1 {
- input: [[nuggetGold, "oc:circuitChip1", nuggetGold]
- ["oc:cpu2", "oc:componentBus1", "oc:graphicsCard1"]
- [nuggetGold, "oc:circuitChip1", nuggetGold]]
-}
-apu2 {
- input: [[chipDiamond, "oc:circuitChip2", chipDiamond]
- ["oc:cpu3", "oc:componentBus2", "oc:graphicsCard2"]
- [chipDiamond, "oc:circuitChip2", chipDiamond]]
-}
-componentbus1 {
- input: [[iron_nugget, redstone, iron_nugget]
- ["oc:circuitChip1", "oc:materialCU", ""]
- [iron_nugget, "oc:materialCircuitBoardPrinted", iron_nugget]]
-}
-componentbus2 {
- input: [[nuggetGold, redstone, nuggetGold]
- ["oc:circuitChip2", "oc:materialCU", ""]
- [nuggetGold, "oc:materialCircuitBoardPrinted", nuggetGold]]
-}
-componentbus3 {
- input: [[chipDiamond, redstone, chipDiamond]
- ["oc:circuitChip3", "oc:materialCU", ""]
- [chipDiamond, "oc:materialCircuitBoardPrinted", chipDiamond]]
-}
-cpu1 {
- input: [[iron_nugget, redstone, iron_nugget]
- ["oc:circuitChip1", "oc:materialCU", "oc:circuitChip1"]
- [iron_nugget, "oc:materialALU", iron_nugget]]
-}
-cpu2 {
- input: [[nuggetGold, redstone, nuggetGold]
- ["oc:circuitChip2", "oc:materialCU", "oc:circuitChip2"]
- [nuggetGold, "oc:materialALU", nuggetGold]]
-}
-cpu3 {
- input: [[chipDiamond, redstone, chipDiamond]
- ["oc:circuitChip3", "oc:materialCU", "oc:circuitChip3"]
- [chipDiamond, "oc:materialALU", chipDiamond]]
-}
-cu {
- input: [[nuggetGold, redstone, nuggetGold]
- ["oc:materialTransistor", clock, "oc:materialTransistor"]
- [nuggetGold, "oc:materialTransistor", nuggetGold]]
-}
-
-rawcircuitboard {
- type: shapeless
- input: [ingotGold, clay, dyeGreen]
- output: 8
-}
-circuitboard = false
-printedcircuitboard {
- type: furnace
- input: "oc:materialCircuitBoardRaw"
-}
-card {
- input: [[iron_nugget, "", ""]
- [iron_nugget, "oc:materialCircuitBoardPrinted", ""]
- [iron_nugget, nuggetGold, ""]]
-}
-
-interweb {
- input: [[string, string, string]
- [string, materialEnderPearl, string]
- [string, string, string]]
-}
-
-adapter {
- input: [[ingotIron, "oc:cable", ingotIron]
- ["oc:cable", "oc:circuitChip1", "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-assembler {
- input: [[ingotIron, workbench, ingotIron]
- [craftingPiston, "oc:circuitChip2", craftingPiston]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-cable {
- input: [["", iron_nugget, ""]
- [iron_nugget, redstone, iron_nugget]
- ["", iron_nugget, ""]]
- output: 4
-}
-luaBios {
- type: shapeless
- input: ["oc:eeprom", "oc:manual"]
-}
-carpetedcapacitor {
- type: shapeless
- input: [carpet, "oc:capacitor"]
-}
-capacitor {
- input: [[ingotIron, "oc:materialTransistor", ingotIron]
- [nuggetGold, paper, nuggetGold]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-charger {
- input: [[ingotIron, ingotGold, ingotIron]
- ["oc:capacitor", "oc:circuitChip2", "oc:capacitor"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-case1 {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- [fenceIron, chest, fenceIron]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-case2 {
- input: [[ingotGold, "oc:circuitChip2", ingotGold]
- [fenceIron, chest, fenceIron]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-case3 {
- input: [[gemDiamond, "oc:circuitChip3", gemDiamond]
- [fenceIron, chest, fenceIron]
- [gemDiamond, "oc:materialCircuitBoardPrinted", gemDiamond]]
-}
-disassembler {
- input: [["oc:materialCU", paneGlass, "oc:analyzer"]
- [craftingPiston, "", obsidian]
- [ingotIron, bucketLava, ingotIron]]
-}
-diskdrive {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- [craftingPiston, stickWood, ""]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-geolyzer {
- input: [[ingotGold, compass, ingotGold]
- [eyeOfEnder, "oc:circuitChip2", eyeOfEnder]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-hologram1 {
- input: [["oc:circuitChip2", paneGlass, "oc:circuitChip2"]
- ["oc:materialCircuitBoardPrinted", chipDiamond, "oc:materialCircuitBoardPrinted"]
- [obsidian, yellowDust, obsidian]]
-}
-hologram2 {
- input: [["oc:circuitChip3", blockGlass, "oc:circuitChip3"]
- ["oc:materialCircuitBoardPrinted", gemDiamond, "oc:materialCircuitBoardPrinted"]
- [obsidian, blazePowder, obsidian]]
-}
-keyboard {
- input: [["oc:materialButtonGroup", "oc:materialButtonGroup", "oc:materialButtonGroup"]
- ["oc:materialButtonGroup", "oc:materialArrowKey", "oc:materialNumPad"]]
-}
-motionsensor {
- input: [[ingotGold, daylightDetector, ingotGold]
- [daylightDetector, "oc:cpu2", daylightDetector]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-netsplitter {
- input: [[ingotIron, "oc:cable", ingotIron]
- ["oc:cable", craftingPiston, "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-printer {
- input: [[ingotIron, hopper, ingotIron]
- [craftingPiston, "oc:circuitChip3", craftingPiston]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-powerconverter {
- input: [[ingotIron, "oc:cable", ingotIron]
- [ingotGold, "oc:circuitChip1", ingotGold]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-powerdistributor {
- input: [[ingotIron, ingotGold, ingotIron]
- ["oc:cable", "oc:circuitChip1", "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-rack {
- input: [[gemDiamond, "oc:wlanCard2", gemDiamond]
- [fenceIron, chest, fenceIron]
- ["oc:relay", "oc:materialCircuitBoardPrinted", "oc:powerDistributor"]]
-}
-raid {
- input: [[iron_nugget, "oc:cpu3", iron_nugget]
- ["oc:ram1", "oc:diskDrive", "oc:ram1"]
- [iron_nugget, "oc:circuitChip2", iron_nugget]]
-}
-redstone {
- input: [[ingotIron, "oc:circuitChip3", ingotIron]
- [blockRedstone, "oc:redstoneCard1", blockRedstone]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-relay {
- input: [[ingotIron, "oc:cable", ingotIron]
- ["oc:cable", "oc:lanCard", "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-screen1 {
- input: [[ingotIron, redstone, ingotIron]
- [redstone, "oc:circuitChip1", blockGlass]
- [ingotIron, redstone, ingotIron]]
-}
-screen2 {
- input: [[ingotGold, dyeRed, ingotGold]
- [dyeGreen, "oc:circuitChip2", blockGlass]
- [ingotGold, dyeBlue, ingotGold]]
-}
-screen3 {
- input: [[obsidian, yellowDust, obsidian]
- [yellowDust, "oc:circuitChip3", blockGlass]
- [obsidian, yellowDust, obsidian]]
-}
-transposer {
- input: [[ingotIron, "oc:inventoryControllerUpgrade", ingotIron]
- [hopper, bucket, hopper]
- [ingotIron, "oc:tankControllerUpgrade", ingotIron]]
- output: 4
-}
-waypoint {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- ["oc:materialTransistor", "oc:materialInterweb", "oc:materialTransistor"],
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
diff --git a/src/main/resources/assets/opencomputers/recipes/gregtech.recipes b/src/main/resources/assets/opencomputers/recipes/gregtech.recipes
deleted file mode 100644
index 1c3a45134d..0000000000
--- a/src/main/resources/assets/opencomputers/recipes/gregtech.recipes
+++ /dev/null
@@ -1,353 +0,0 @@
-# Do not change this file, it is rewritten each time you start the game.
-# Instead, use the user.recipes file to edit recipes by redefining them there.
-
-# Note that there is support for a number of GregTech machines, by using the
-# appropriate `type` specifier. Available types are:
-# - gt_alloySmelter : Alloy Smelter Recipe
-# - gt_assembler : Circuit Assembler Machine
-# - gt_bender : Plate Bending Machine Recipe
-# - gt_canner : Canning Machine Recipe
-# - gt_chemical : Chemical Recipe
-# - gt_cnc : CNC-Machine Recipe
-# - gt_cutter : Cutter Recipe
-# - gt_fluidCanner : Fluid Canner Recipe
-# - gt_formingPress : Forming Press Recipe
-# - gt_lathe : Lathe Machine Recipe
-# - gt_laserEngraver: Laser Engraver Recipe
-# - gt_wiremill : Wiremill Recipe
-#
-# For these types, there a few more options for inputs and outputs. A full
-# recipe using all these options would look like this:
-# name {
-# type: gt_???
-# input: ["primaryInput", "possiblyOptionalSecondaryInput"]
-# count: [1, 2] # would mean 1 of primary, 2 of secondary
-# output: 2 # size of primary output stack
-# eu: EU consumed for the operation
-# time: time it takes to complete the operation, in ticks.
-# # The following are usually optional.
-# secondaryOutput: ["secondaryOutput1", "secondaryOutput2"] # Max number depends on machine.
-# secondaryOutputCount: [2, 2] # Like `count` to `input`.
-# inputFluid: {name="water", amount="500"}
-# outputFluid: {name="lava"} # defaults to amount = 1000
-# }
-
-include file("hardmode.recipes")
-
-analyzer {
- # 32762 = Portable Scanner
- input: [["oc:materialTransistor", torchRedstoneActive, "oc:materialTransistor"]
- ["oc:circuitChip2", {item="gt.metaitem.01", subID=32762}, "oc:circuitChip2"]
- [screwAluminium, craftingToolScrewdriver, screwAluminium]]
-}
-
-server1 {
- input: [["oc:circuitChip1", "oc:ram4", "oc:circuitChip1"]
- ["oc:circuitChip2", "oc:case1", "oc:circuitChip2"]
- [craftingToolScrewdriver, "oc:materialCircuitBoardPrinted", craftingToolWrench]]
-}
-server2 {
- input: [["oc:circuitChip2", "oc:ram5", "oc:circuitChip2"]
- ["oc:circuitChip3", "oc:case2", "oc:circuitChip3"]
- [craftingToolScrewdriver, "oc:materialCircuitBoardPrinted", craftingToolWrench]]
-}
-server3 {
- input: [["oc:circuitChip3", "oc:ram6", "oc:circuitChip3"]
- ["oc:circuitChip3", "oc:case3", "oc:circuitChip3"]
- [craftingToolScrewdriver, "oc:materialCircuitBoardPrinted", craftingToolWrench]]
-}
-
-ram1 {
- type: gt_assembler
- input: ["oc:circuitChip1", "oc:materialCircuitBoardPrinted"]
- count: [3, 3]
- eu: 32
- time: 250
-}
-ram2 {
- input: [["oc:circuitChip1", "oc:circuitChip1", "oc:circuitChip1"]
- ["oc:ram1", "oc:materialCircuitBoardPrinted", "oc:ram1"]
- ["", craftingToolWrench, ""]]
-}
-ram3 {
- input: [["oc:circuitChip2", "oc:circuitChip2", "oc:circuitChip2"]
- ["oc:ram2", "oc:materialCircuitBoardPrinted", "oc:ram2"]
- [circuitElite, craftingToolWrench, circuitElite]]
-}
-ram4 {
- input: [["oc:circuitChip2", "oc:circuitChip2", "oc:circuitChip2"]
- ["oc:ram3", "oc:materialCircuitBoardPrinted", "oc:ram3"]
- [circuitElite, craftingToolWrench, circuitElite]]
-}
-ram5 {
- input: [["oc:circuitChip3", "oc:circuitChip3", "oc:circuitChip3"]
- ["oc:ram4", "oc:materialCircuitBoardPrinted", "oc:ram4"]
- [circuitUltimate, craftingToolWrench, circuitUltimate]]
-}
-ram6 {
- input: [["oc:circuitChip3", "oc:circuitChip3", "oc:circuitChip3"]
- ["oc:ram5", "oc:materialCircuitBoardPrinted", "oc:ram5"]
- [circuitUltimate, craftingToolWrench, circuitUltimate]]
-}
-
-floppy {
- input: [[screwAluminium, lever, screwAluminium]
- [plateAluminium, "oc:materialDisk", plateAluminium]
- [screwAluminium, craftingToolScrewdriver, screwAluminium]]
-}
-hdd1 {
- input: [["oc:ram1", "oc:materialDisk", "oc:ram1"]
- ["oc:ram1", "oc:materialDisk", "oc:ram1"]
- [screwAluminium, craftingToolScrewdriver, "oc:circuitChip2"]]
-}
-hdd2 {
- input: [["oc:hdd1", "oc:materialCircuitBoardPrinted" , "oc:hdd1"]
- ["oc:circuitChip2", screwTitanium, "oc:circuitChip2"]
- [screwTitanium, craftingToolScrewdriver, screwTitanium]]
-}
-hdd3 {
- input: [["oc:hdd2", "oc:materialCircuitBoardPrinted", "oc:hdd2"]
- ["oc:circuitChip3", screwTungstenSteel, "oc:circuitChip3"]
- [screwTungstenSteel , craftingToolScrewdriver, screwTungstenSteel]]
-}
-
-# graphicsCard1 { fallback to default }
-# graphicsCard2 { fallback to default }
-# graphicsCard3 { fallback to default }
-redstonecard {
- input: [[screwStainlessSteel , "oc:circuitChip2" , screwStainlessSteel]
- ["comparator", "oc:materialCard", diode]
- [screwStainlessSteel , craftingToolScrewdriver, screwStainlessSteel]]
-}
-lancard {
- input: [[screwStainlessSteel , "oc:circuitChip2" , screwStainlessSteel]
- ["oc:cable", "oc:materialCard", "oc:cable"]
- [screwStainlessSteel , craftingToolScrewdriver, screwStainlessSteel]]
-}
-wlancard1 {
- input: [[screwAluminium , "oc:circuitChip2" , screwAluminium]
- [torchRedstoneActive, "oc:lanCard", torchRedstoneActive]
- [screwAluminium , craftingToolScrewdriver, screwAluminium]]
-}
-wlancard2 {
- input: [[screwTitanium , "oc:circuitChip3" , screwTitanium]
- [materialEnderPearl, "oc:lanCard", materialEnderPearl]
- [screwTitanium , craftingToolScrewdriver, screwTitanium]]
-}
-
-craftingupgrade {
- # 1 = LV Casing
- input: [[screwStainlessSteel, "oc:materialCircuitBoardPrinted" , screwStainlessSteel]
- ["oc:circuitChip2", {block="gt.blockcasings", subID=1}, "oc:circuitChip2"]
- [screwStainlessSteel, craftingToolScrewdriver, screwStainlessSteel]]
-}
-generatorupgrade {
- input: [[screwStainlessSteel, "oc:materialCircuitBoardPrinted" , screwStainlessSteel]
- ["oc:circuitChip2", craftingGenerator, "oc:circuitChip2"]
- [screwStainlessSteel, craftingToolScrewdriver, screwStainlessSteel]]
-}
-navigationupgrade {
- # 2 = MV Casing
- input: [[{block="gt.blockcasings", subID=2}, compass, screwStainlessSteel]
- ["oc:circuitChip3", {item=filled_map, subID=any}, "oc:circuitChip3"]
- [screwStainlessSteel, potion, craftingToolScrewdriver]]
-}
-signupgrade {
- input: [[screwAluminium, dyeBlack, screwAluminium]
- ["oc:circuitChip1", stickWood, "oc:circuitChip1"]
- [screwAluminium, craftingToolScrewdriver, screwAluminium]]
-}
-solargeneratorupgrade {
- # 32750 = Solar Panel
- input: [[screwTitanium, "", screwTitanium]
- ["oc:circuitChip3", {item="gt.metaitem.01", subID=32750} , "oc:circuitChip3"]
- [screwTitanium, craftingToolScrewdriver, screwTitanium]]
-}
-
-cuttingwire {
- input: [[stickWood, ingotTin, stickWood]
- ["", craftingToolWireCutter, ""]]
-}
-disk {
- input: [["", plateAluminium, ""]
- [plateAluminium, "", plateAluminium]
- ["", plateAluminium, ""]]
-}
-
-# buttonGroup { fallback to default }
-# arrowKeys { fallback to default }
-# numPad { fallback to default }
-
-transistor {
- type: gt_assembler
- input: [redstone, stickIron]
- count: [1, 3]
- eu: 16
- time: 500
- output: 6
-}
-chip1 {
- type: gt_assembler
- input: ["ic2.itemPartCircuit", "oc:materialTransistor"]
- count: [1, 4]
- eu: 25
- time: 480
- output: 4
-}
-chip2 {
- type: gt_assembler
- input: ["ic2.itemPartCircuitAdv", "oc:materialTransistor"]
- count: [1, 8]
- eu: 25
- time: 640
- output: 4
-}
-chip3 {
- type: gt_assembler
- input: [circuitData, "oc:materialTransistor"]
- count: [1, 16]
- eu: 25
- time: 800
- output: 4
-}
-alu {
- type: gt_assembler
- input: [comparator, "oc:circuitChip1"]
- count: [3, 1]
- eu: 24
- time: 500
- output: 1
-}
-cpu1 {
- input: [["oc:circuitChip2", "oc:materialALU", "oc:circuitChip2"]
- [plateAluminium, "oc:materialCU", plateAluminium]
- [screwAluminium, craftingToolScrewdriver, screwAluminium]]
-}
-cpu2 {
- input: [["oc:circuitChip2", plateStainlessSteel, "oc:circuitChip2"]
- ["oc:ram3", "oc:cpu1", "oc:ram3"]
- ["oc:circuitChip2", craftingToolScrewdriver, "oc:circuitChip2"]]
-}
-cpu3 {
- input: [["oc:circuitChip3", plateTitanium, "oc:circuitChip3"]
- ["oc:ram5", "oc:cpu2", "oc:ram5"]
- ["oc:circuitChip3", craftingToolScrewdriver, "oc:circuitChip3"]]
-}
-cu {
- type: gt_assembler
- input: [circuitElite, "oc:materialTransistor"]
- count: [1, 6]
- eu: 32
- time: 750
- output: 3
-}
-
-# rawCircuitBoard { fallback to default }
-circuitboard {
- type: furnace
- input: "oc:materialCircuitBoardRaw"
-}
-printedcircuitboard {
- type:shaped
- input: [[dustTinyGold, cellSulfuricAcid]
- ["oc:materialCircuitBoard", dustTinyGold]]
-}
-card {
- input: [[stickIron, "oc:circuitChip2", "oc:materialTransistor"]
- [stickIron, "oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted"]
- [craftingToolScrewdriver, nuggetGold, nuggetGold]]
-}
-
-adapter {
- input: [["oc:cable", "oc:circuitChip1", "oc:cable"]
- ["", {block="gt.blockcasings", subID=1}, ""]
- ["oc:materialCircuitBoardPrinted", "oc:cable", craftingToolWrench]]
-}
-cable {
- type: gt_assembler
- input: [craftingWireCopper, dustEmerald]
- count: [8, 1]
- eu: 32
- time: 64
- output: 8
-}
-carpetedcapacitor {
- type: shapeless
- input: [carpet, "oc:capacitor"]
-}
-capacitor {
- # 7 = CESU
- input: [["", {item="ic2.blockElectric", subID=7}, ""]
- [{block="gt.blockcasings", subID=1}, "oc:materialTransistor", {block="gt.blockcasings", subID=1}]
- ["oc:materialCircuitBoardPrinted", craftingToolWrench, "oc:materialCircuitBoardPrinted"]]
-}
-charger {
- # 2 = Chargepad (MFE)
- input: [["", plateStainlessSteel, ""]
- [{item="ic2.blockChargepad", subID=2}, {block="gt.blockcasings", subID=3}, {item="ic2.blockChargepad", subID=2}]
- ["oc:circuitChip3", craftingToolWrench, "oc:materialCircuitBoardPrinted"]]
-}
-case1 {
- input: [[screwAluminium, "oc:materialCircuitBoardPrinted", craftingToolWrench]
- ["ic2.reactorVentSpread", {block="gt.blockcasings", subID=1}, "ic2.reactorVentSpread"]
- [screwAluminium, "oc:circuitChip1", craftingToolScrewdriver]]
-}
-case2 {
- input: [[screwStainlessSteel , "oc:materialCircuitBoardPrinted", craftingToolWrench]
- [{item="ic2.reactorVentGold", subID=1}, "oc:case1", {item="ic2.reactorVentGold", subID=1}]
- [screwStainlessSteel, "oc:circuitChip2", craftingToolScrewdriver]]
-}
-case3 {
- input: [[screwTitanium , "oc:materialCircuitBoardPrinted", craftingToolWrench]
- [{item="ic2.reactorVentDiamond", subID=1}, "oc:case2", {item="ic2.reactorVentDiamond", subID=1}]
- [screwTitanium, "oc:circuitChip3", craftingToolScrewdriver]]
-}
-diskdrive {
- input: [["", "oc:circuitChip2", ""]
- [craftingPiston, {block="gt.blockcasings", subID=1}, craftingLensWhite]
- ["oc:circuitChip2", craftingToolWrench, "oc:circuitChip2"]]
-}
-# keyboard { fallback to default }
-powerconverter {
- # 4 = MV Transformer
- input: [["", "oc:circuitChip2", ""]
- [plateAluminium, {item="ic2.blockElectric", subID=4}, plateAluminium]
- ["oc:materialCircuitBoardPrinted", craftingToolWrench, "oc:materialCircuitBoardPrinted"]]
-}
-powerdistributor {
- # 7 = CESU
- input: [["", plateAluminium, ""]
- [{item="ic2.blockElectric", subID=7}, {block="gt.blockcasings", subID=2}, circuitMaster]
- ["oc:materialCircuitBoardPrinted", plateAluminium, craftingToolWrench]]
-}
-rack {
- input: [[craftingToolScrewdriver, "oc:wlanCard2", craftingToolWrench]
- [{item="ic2.reactorVentDiamond", subID=1}, chest, {item="ic2.reactorVentDiamond", subID=1}]
- ["oc:relay", "oc:materialCircuitBoardPrinted","oc:powerDistributor"]]
-}
-redstone {
- # 32731 = Activity Detector
- input: [[plateRedstone, "oc:materialCircuitBoardPrinted", plateRedstone]
- [{item="gt.metaitem.01", subID=32731}, {block="gt.blockcasings", subID=2}, "oc:redstoneCard1"]
- ["oc:circuitChip2", "oc:materialCircuitBoardPrinted", "oc:circuitChip2"]]
-}
-relay {
- input: [["", "oc:lanCard", ""]
- ["oc:cable", {block="gt.blockcasings", subID=2}, "oc:cable"]
- ["oc:materialCircuitBoardPrinted", craftingToolWrench, "oc:materialCircuitBoardPrinted"]]
-}
-screen1 {
- input: [[plateAluminium, plateAluminium, craftingToolWrench]
- [redstone, "oc:materialTransistor", paneGlass]
- [plateAluminium, plateAluminium, craftingToolScrewdriver]]
-}
-screen2 {
- input: [[plateStainlessSteel, screwStainlessSteel, craftingToolWrench]
- ["oc:circuitChip2", "oc:screen1", {item="gt.metaitem.01", subID=32740}]
- [plateStainlessSteel, screwStainlessSteel, craftingToolScrewdriver]]
-}
-screen3 {
- input: [[plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolWrench]
- ["oc:circuitChip3", "oc:screen2", "oc:circuitChip3"]
- [plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolScrewdriver]]
-}
diff --git a/src/main/resources/assets/opencomputers/recipes/hardmode.recipes b/src/main/resources/assets/opencomputers/recipes/hardmode.recipes
deleted file mode 100644
index 14cc0646af..0000000000
--- a/src/main/resources/assets/opencomputers/recipes/hardmode.recipes
+++ /dev/null
@@ -1,411 +0,0 @@
-# Do not change this file, it is rewritten each time you start the game.
-# Instead, use the user.recipes file to edit recipes by redefining them there.
-
-include file("default.recipes")
-
-analyzer {
- input: [["", torchRedstoneActive, ""]
- ["oc:materialTransistor", "oc:circuitChip1", nuggetGold]
- ["oc:materialTransistor", "oc:materialCircuitBoardPrinted", nuggetGold]]
-}
-terminal {
- input: [[iron_nugget, "oc:solarGeneratorUpgrade", iron_nugget]
- ["oc:circuitChip3", "oc:screen2", "oc:wlanCard2"]
- [iron_nugget, "oc:keyboard", iron_nugget]]
-}
-
-server1 {
- input: [["oc:circuitChip1", "oc:ram4", "oc:circuitChip1"]
- ["oc:circuitChip2", "oc:case1", "oc:circuitChip2"]
- ["oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted"]]
-}
-server2 {
- input: [["oc:circuitChip2", "oc:ram5", "oc:circuitChip2"]
- ["oc:circuitChip3", "oc:case2", "oc:circuitChip3"]
- ["oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted"]]
-}
-server3 {
- input: [["oc:circuitChip3", "oc:ram6", "oc:circuitChip3"]
- ["oc:circuitChip3", "oc:case3", "oc:circuitChip3"]
- ["oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted"]]
-}
-
-ram1 {
- input: [["oc:circuitChip1", "oc:circuitChip1", "oc:circuitChip1"]
- ["oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted"]]
-}
-ram2 {
- input: [["oc:circuitChip1", "oc:circuitChip1", "oc:circuitChip1"]
- ["oc:ram1", "oc:materialCircuitBoardPrinted", "oc:ram1"]]
-}
-ram3 {
- input: [["oc:circuitChip2", "oc:circuitChip2", "oc:circuitChip2"]
- ["oc:ram2", "oc:materialCircuitBoardPrinted", "oc:ram2"]]
-}
-ram4 {
- input: [["oc:circuitChip2", "oc:circuitChip2", "oc:circuitChip2"]
- ["oc:ram3", "oc:materialCircuitBoardPrinted", "oc:ram3"]]
-}
-ram5 {
- input: [["oc:circuitChip3", "oc:circuitChip3", "oc:circuitChip3"]
- ["oc:ram4", "oc:materialCircuitBoardPrinted", "oc:ram4"]]
-}
-ram6 {
- input: [["oc:circuitChip3", "oc:circuitChip3", "oc:circuitChip3"]
- ["oc:ram5", "oc:materialCircuitBoardPrinted", "oc:ram5"]]
-}
-
-floppy {
- input: [[iron_nugget, lever, iron_nugget]
- ["oc:materialCircuitBoard", "oc:materialDisk", "oc:materialCircuitBoard"]
- [iron_nugget, paper, iron_nugget]]
-}
-hdd1 {
- input: [["oc:circuitChip1", "oc:materialDisk", ingotIron]
- ["oc:materialCircuitBoardPrinted", "oc:materialDisk", craftingPiston]
- ["oc:circuitChip1", "oc:materialDisk", ingotIron]]
-}
-hdd2 {
- input: [[ingotGold, "oc:hdd1", ingotGold]
- ["oc:circuitChip2", "oc:materialCircuitBoardPrinted", "oc:circuitChip2"]
- [ingotGold, "oc:hdd1", ingotGold]]
-}
-hdd3 {
- input: [["oc:circuitChip3", "oc:hdd2", "oc:circuitChip3"]
- ["oc:ram1", "oc:materialCircuitBoardPrinted", "oc:ram1"]
- ["oc:circuitChip3", "oc:hdd2", "oc:circuitChip3"]]
-}
-
-abstractbuscard {
- input: [[{block="StargateTech2:block.busCable"}, {item="StargateTech2:naquadah", subID=3}, ""]
- ["", "oc:materialCard", ""]]
-}
-datacard2 {
- input: [[nuggetGold, "oc:cpu1", "oc:circuitChip3"]
- ["", "oc:dataCard1", ""]]
-}
-datacard3 {
- input: [[gemDiamond, "oc:cpu2", "oc:ram5"]
- ["", "oc:dataCard2", ""]]
-}
-graphicscard1 {
- input: [["oc:circuitChip1", "oc:materialALU", "oc:ram1"]
- ["", "oc:materialCard", ""]]
-}
-graphicscard2 {
- input: [["oc:circuitChip2", "oc:circuitChip2", "oc:ram3"]
- ["", "oc:graphicsCard1", ""]]
-}
-graphicscard3 {
- input: [["oc:circuitChip3", "oc:circuitChip3", "oc:ram5"]
- ["", "oc:graphicsCard2", ""]]
-}
-internetcard {
- input: [["oc:materialInterweb", "oc:circuitChip3", torchRedstoneActive]
- ["", "oc:wlanCard2", obsidian]]
-}
-redstonecard1 {
- input: [[torchRedstoneActive, "oc:circuitChip1", ""]
- ["", "oc:materialCard", ""]]
-}
-redstonecard2 {
- input: [[blockRedstone, "oc:circuitChip2", materialEnderPearl]
- ["", "oc:redstoneCard1", ""]]
-}
-lancard {
- input: [["oc:cable", "oc:circuitChip1", ""]
- ["", "oc:materialCard", ""]]
-}
-wlancard1 {
- input: [[torchRedstoneActive, "oc:circuitChip1", torchRedstoneActive]
- ["", "oc:lanCard", ""]]
-}
-wlancard2 {
- input: [[materialEnderPearl, "oc:circuitChip2", ""]
- ["", "oc:lanCard", ""]]
-}
-linkedcard {
- input: [[eyeOfEnder, "", eyeOfEnder]
- ["oc:wlanCard2", "oc:materialInterweb", "oc:wlanCard2"]
- ["oc:circuitChip3", "", "oc:circuitChip3"]]
- output: 2 # Note: all resulting cards are linked to each other.
-}
-
-batteryupgrade1 {
- input: [[ingotIron, nuggetGold, ingotIron]
- ["oc:materialTransistor", "oc:capacitor", "oc:materialTransistor"]
- [ingotIron, nuggetGold, ingotIron]]
-}
-batteryupgrade2 {
- input: [[ingotGold, "oc:capacitor", ingotGold]
- ["oc:materialTransistor", nuggetGold, "oc:materialTransistor"]
- [ingotGold, "oc:capacitor", ingotGold]]
-}
-batteryupgrade3 {
- input: [[gemDiamond, "oc:capacitor", gemDiamond]
- ["oc:materialTransistor", "oc:capacitor", "oc:materialTransistor"]
- [gemDiamond, "oc:capacitor", gemDiamond]]
-}
-craftingupgrade {
- input: [[ingotIron, craftingPiston, ingotIron]
- ["oc:circuitChip1", workbench, "oc:circuitChip1"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-experienceupgrade {
- input: [[ingotGold, "oc:analyzer", ingotGold]
- ["oc:circuitChip3", emerald, "oc:circuitChip3"]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-generatorupgrade {
- input: [[ingotIron, "", ingotIron]
- ["oc:circuitChip1", craftingPiston, "oc:circuitChip1"]
- ["oc:materialCircuitBoardPrinted", ingotIron, "oc:materialCircuitBoardPrinted"]]
-}
-inventoryupgrade {
- input: [[ingotIron, hopper, ingotIron]
- [dispenser, chest, craftingPiston]
- [ingotIron, "oc:circuitChip1", ingotIron]]
-}
-inventorycontrollerupgrade {
- input: [[ingotGold, "oc:circuitChip2", ingotGold]
- [dispenser, "oc:inventoryUpgrade", craftingPiston]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-navigationupgrade {
- input: [[ingotGold, compass, ingotGold]
- ["oc:circuitChip3", {item=filled_map, subID=any}, "oc:circuitChip3"]
- [ingotGold, potion, ingotGold]]
-}
-signupgrade {
- input: [[ingotIron, dyeBlack, ingotIron]
- ["oc:circuitChip1", stickWood, "oc:circuitChip1"]
- [ingotIron, pistonStickyBase, ingotIron]]
-}
-solargeneratorupgrade {
- input: [[blockGlass, blockGlass, blockGlass]
- ["oc:circuitChip3", "oc:generatorUpgrade", "oc:circuitChip3"]]
-}
-tradingupgrade {
- input: [["oc:circuitChip2", chest, "oc:circuitChip2"]
- [emerald, "oc:circuitChip2", emerald]
- [dropper, "oc:materialCircuitBoardPrinted", craftingPiston]]
-}
-
-cuttingwire {
- input: [[stickWood, iron_nugget, stickWood]]
-}
-disk {
- input: [["", iron_nugget, ""]
- [iron_nugget, "", iron_nugget]
- ["", iron_nugget, ""]]
-}
-
-buttongroup {
- input: [[button, button, button]
- [button, button, button]]
-}
-arrowkeys {
- input: [["", button, ""]
- [button, button, button]]
-}
-numpad {
- input: [[button, button, button]
- [button, button, button]
- [button, button, button]]
-}
-
-transistor {
- input: [[iron_nugget, iron_nugget, iron_nugget]
- [nuggetGold, paper, nuggetGold]
- ["", redstone, ""]]
-}
-chip1 {
- input: [[iron_nugget, "", iron_nugget]
- ["oc:materialTransistor", nuggetGold, "oc:materialTransistor"]
- [iron_nugget, "", iron_nugget]]
-}
-chip2 {
- input: [[nuggetGold, {item=dyePowder, subID=4} , nuggetGold]
- ["oc:circuitChip1", netherquartz, "oc:circuitChip1"]
- [nuggetGold, {item=dyePowder, subID=4}, nuggetGold]]
-}
-chip3 {
- input: [[yellowDust, comparator, yellowDust]
- ["oc:circuitChip2", gemDiamond, "oc:circuitChip2"]
- [yellowDust, comparator, yellowDust]]
-}
-alu {
- input: [[diode, torchRedstoneActive, diode]
- ["oc:materialTransistor", "oc:materialTransistor", "oc:materialTransistor"]
- [iron_nugget, redstone, iron_nugget]]
-}
-apu2 {
- input: [[gemDiamond, "oc:circuitChip2", gemDiamond]
- ["oc:cpu3", "oc:componentBus2", "oc:graphicsCard2"]
- [gemDiamond, "oc:circuitChip2", gemDiamond]]
-}
-componentbus1 {
- input: [[iron_nugget, redstone, iron_nugget]
- ["oc:circuitChip1", "oc:materialCU", ""]
- [iron_nugget, "oc:materialCircuitBoardPrinted", iron_nugget]]
-}
-componentbus2 {
- input: [[nuggetGold, "oc:ram3", nuggetGold]
- ["oc:circuitChip2", "oc:componentBus1", ""]
- [nuggetGold, "oc:materialCircuitBoardPrinted", nuggetGold]]
-}
-componentbus3 {
- input: [[gemDiamond, "oc:ram5", gemDiamond]
- ["oc:circuitChip3", "oc:componentBus2", ""]
- [gemDiamond, "oc:materialCircuitBoardPrinted", gemDiamond]]
-}
-cpu1 {
- input: [[iron_nugget, redstone, iron_nugget]
- ["oc:circuitChip1", "oc:materialCU", "oc:circuitChip1"]
- [iron_nugget, "oc:materialALU", iron_nugget]]
-}
-cpu2 {
- input: [[nuggetGold, "oc:ram3", nuggetGold]
- ["oc:circuitChip2", "oc:cpu1", "oc:circuitChip2"]
- [nuggetGold, "oc:ram3", nuggetGold]]
-}
-cpu3 {
- input: [[gemDiamond, "oc:ram5", gemDiamond]
- ["oc:circuitChip3", "oc:cpu2", "oc:circuitChip3"]
- [gemDiamond, "oc:ram5", gemDiamond]]
-}
-cu {
- input: [[nuggetGold, torchRedstoneActive, nuggetGold]
- ["oc:materialTransistor", clock, "oc:materialTransistor"]
- [nuggetGold, redstone, nuggetGold]]
-}
-
-rawcircuitboard {
- type: shapeless
- input: ["oc:materialCuttingWire", clay, dyeGreen]
-}
-circuitboard {
- type: furnace
- input: "oc:materialCircuitBoardRaw"
-}
-printedcircuitboard {
- type: shapeless
- input: ["oc:materialCircuitBoard", nuggetGold, "oc:materialAcid"]
- output: 1
-}
-card {
- input: [[iron_nugget, "oc:circuitChip1", "oc:materialTransistor"]
- [iron_nugget, "oc:materialCircuitBoardPrinted", "oc:materialCircuitBoardPrinted"]
- [iron_nugget, nuggetGold, nuggetGold]]
-}
-
-interweb {
- input: [[string, materialEnderPearl, string]
- [materialEnderPearl, string, materialEnderPearl]
- [string, materialEnderPearl, string]]
-}
-
-adapter {
- input: [[ingotIron, "oc:cable", ingotIron]
- ["oc:cable", "oc:circuitChip1", "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-cable {
- input: [["", iron_nugget, ""]
- [iron_nugget, redstone, iron_nugget]
- ["", iron_nugget, ""]]
- output: 4
-}
-carpetedcapacitor {
- type: shapeless
- input: [carpet, "oc:capacitor"]
-}
-capacitor {
- input: [[ingotIron, "oc:materialTransistor", ingotIron]
- [nuggetGold, paper, nuggetGold]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-charger {
- input: [[ingotIron, ingotGold, ingotIron]
- ["oc:capacitor", "oc:circuitChip2", "oc:capacitor"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-case1 {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- [fenceIron, chest, fenceIron]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-case2 {
- input: [[ingotGold, "oc:circuitChip2", ingotGold]
- ["oc:circuitChip2", "oc:case1", "oc:circuitChip2"]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-case3 {
- input: [[gemDiamond, "oc:circuitChip3", gemDiamond]
- ["oc:circuitChip3", "oc:case2", "oc:circuitChip3"]
- [gemDiamond, "oc:materialCircuitBoardPrinted", gemDiamond]]
-}
-diskdrive {
- input: [[ingotIron, "oc:circuitChip1", ingotIron]
- [craftingPiston, stickWood, ""]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-geolyzer {
- input: [[ingotGold, "oc:analyzer", ingotGold]
- [eyeOfEnder, "oc:circuitChip2", eyeOfEnder]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-hologram1 {
- input: [["oc:circuitChip2", paneGlass, "oc:circuitChip2"]
- ["oc:materialCircuitBoardPrinted", gemDiamond, "oc:materialCircuitBoardPrinted"]
- [obsidian, yellowDust, obsidian]]
-}
-hologram2 {
- input: [["oc:circuitChip3", blockGlass, "oc:circuitChip3"]
- ["oc:materialCircuitBoardPrinted", blockDiamond, "oc:materialCircuitBoardPrinted"]
- [obsidian, blazePowder, obsidian]]
-}
-keyboard {
- input: [["oc:materialButtonGroup", "oc:materialButtonGroup", "oc:materialButtonGroup"]
- ["oc:materialButtonGroup", "oc:materialArrowKey", "oc:materialNumPad"]]
-}
-powerconverter {
- input: [[ingotIron, "oc:cable", ingotIron]
- [ingotGold, "oc:circuitChip1", ingotGold]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-powerdistributor {
- input: [[ingotIron, ingotGold, ingotIron]
- ["oc:cable", "oc:circuitChip1", "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-rack {
- input: [["oc:circuitChip3", "oc:wlanCard2", "oc:circuitChip3"]
- [fenceIron, chest, fenceIron]
- ["oc:relay", "oc:materialCircuitBoardPrinted","oc:powerDistributor"]]
-}
-redstone {
- input: [[ingotIron, "oc:circuitChip3", ingotIron]
- [blockRedstone, "oc:redstoneCard1", blockRedstone]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-relay {
- input: [[ingotIron, "oc:cable", ingotIron]
- ["oc:cable", "oc:lanCard", "oc:cable"]
- [ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
-}
-screen1 {
- input: [[ingotIron, ingotIron, blockGlass]
- [redstone, "oc:materialTransistor", blockGlass]
- [ingotIron, ingotIron, blockGlass]]
-}
-screen2 {
- input: [[ingotGold, dyeRed, ingotGold]
- ["oc:circuitChip2", dyeGreen, "oc:screen1"]
- [ingotGold, dyeBlue, ingotGold]]
-}
-screen3 {
- input: [[obsidian, "oc:materialCircuitBoardPrinted", "oc:circuitChip3"]
- [blazeRod, netherquartz, "oc:screen2"]
- [obsidian, "oc:materialCircuitBoardPrinted", "oc:circuitChip3"]]
-}
diff --git a/src/main/resources/assets/opencomputers/recipes/peaceful.recipes b/src/main/resources/assets/opencomputers/recipes/peaceful.recipes
deleted file mode 100644
index 83b57cd219..0000000000
--- a/src/main/resources/assets/opencomputers/recipes/peaceful.recipes
+++ /dev/null
@@ -1,79 +0,0 @@
-include file("default.recipes")
-
-redstonecard2 {
- input: [[blockRedstone, "oc:circuitChip2", gemDiamond]
- ["", "oc:materialCard", ""]]
-}
-wlancard1 {
- input: [[torchRedstoneActive, "oc:circuitChip1", torchRedstoneActive]
- ["", "oc:materialCard", ""]]
-}
-wlancard2 {
- input: [[gemDiamond, "oc:circuitChip2", ""]
- ["", "oc:materialCard", ""]]
-}
-linkedcard {
- input: [[gemDiamond, "", gemDiamond]
- ["oc:lanCard", "oc:materialInterweb", "oc:lanCard"]
- ["oc:circuitChip3", "", "oc:circuitChip3"]]
- output: 2 # Note: all resulting cards are linked to each other.
-}
-
-angelupgrade {
- input: [[ingotIron, gemDiamond, ingotIron]
- ["oc:circuitChip1", pistonStickyBase, "oc:circuitChip1"]
- [ingotIron, gemDiamond, ingotIron]]
-}
-chunkloaderupgrade {
- input: [[ingotGold, blockGlass, ingotGold]
- ["oc:circuitChip3", gemDiamond, "oc:circuitChip3"]
- [obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
-}
-inventoryupgrade {
- input: [[plankWood, hopper, plankWood]
- [dropper, chest, craftingPiston]
- [plankWood, "oc:circuitChip1", plankWood]]
-}
-inventorycontrollerupgrade {
- input: [[ingotGold, "oc:analyzer", ingotGold]
- [dropper, "oc:circuitChip2", craftingPiston]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-signupgrade {
- input: [[ingotIron, dyeBlack, ingotIron]
- ["oc:circuitChip1", stickWood, "oc:circuitChip1"]
- [ingotIron, craftingPiston, ingotIron]]
-}
-tankupgrade {
- input: [[plankWood, fenceIron, plankWood]
- [dropper, cauldron, craftingPiston]
- [plankWood, "oc:circuitChip1", plankWood]]
-}
-tankcontrollerupgrade {
- input: [[ingotGold, glassBottle, ingotGold]
- [dropper, "oc:circuitChip2", craftingPiston]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-
-inkcartridgeempty {
- input: [[iron_nugget, dropper, iron_nugget],
- ["oc:materialTransistor", bucket, "oc:materialTransistor"],
- [iron_nugget, "oc:materialCircuitBoardPrinted", iron_nugget]]
-}
-
-interweb {
- input: [[redstone, {block="minecraft:wool", subID=9}, redstone]
- [{block="minecraft:wool", subID=9}, gemDiamond, {block="minecraft:wool", subID=9}]
- [redstone, {block="minecraft:wool", subID=9}, redstone]]
-}
-
-geolyzer {
- input: [[ingotGold, compass, ingotGold]
- [gemDiamond, "oc:circuitChip2", gemDiamond]
- [ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
-}
-hologram2 {
- input: [["oc:circuitChip3", blockGlass, "oc:circuitChip3"]
- ["oc:materialCircuitBoardPrinted", blockDiamond, "oc:materialCircuitBoardPrinted"]
- [obsidian, yellowDust, obsidian]]
-}
diff --git a/src/main/resources/assets/opencomputers/recipes/user.recipes b/src/main/resources/assets/opencomputers/recipes/user.recipes
deleted file mode 100644
index 69c4632ba0..0000000000
--- a/src/main/resources/assets/opencomputers/recipes/user.recipes
+++ /dev/null
@@ -1,20 +0,0 @@
-# To use different sets of recipes, include other recipe files in the order of
-# priority to use the recipes defined in them. The last include has the highest
-# priority (i.e. included recipes simply replace the current definition for all
-# already known recipes).
-
-# To disable a recipe, assign a boolean value to it. For example, to disable
-# the recipe for the transistor: `transistor = false`. This will disable the
-# recipe and hide the item in the creative tab and NEI. If you assign `true`,
-# the recipe will still be disabled, but not hidden in the creative tab/NEI.
-
-include file("default.recipes")
-#include file("hardmode.recipes")
-#include file("gregtech.recipes")
-#include file("peaceful.recipes")
-#include file("your_custom.recipes")
-
-# You can also specify custom recipes in this file directly. Have a look at the
-# default.recipes file to get an idea how recipes have to be structured. You'll
-# want to define your recipes after all includes, to avoid those overwriting
-# your recipes.
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/sounds.json b/src/main/resources/assets/opencomputers/sounds.json
index 9b81c13694..727dadf9b5 100644
--- a/src/main/resources/assets/opencomputers/sounds.json
+++ b/src/main/resources/assets/opencomputers/sounds.json
@@ -8,36 +8,36 @@
"floppy_access": {
"category": "block",
"sounds": [
- "opencomputers:floppy_access1",
- "opencomputers:floppy_access2",
- "opencomputers:floppy_access3",
- "opencomputers:floppy_access4",
- "opencomputers:floppy_access5",
- "opencomputers:floppy_access6"
+ {"name": "opencomputers:floppy_access1", "preload": true},
+ {"name": "opencomputers:floppy_access2", "preload": true},
+ {"name": "opencomputers:floppy_access3", "preload": true},
+ {"name": "opencomputers:floppy_access4", "preload": true},
+ {"name": "opencomputers:floppy_access5", "preload": true},
+ {"name": "opencomputers:floppy_access6", "preload": true}
]
},
"floppy_eject": {
"category": "block",
"sounds": [
- "opencomputers:floppy_eject"
+ {"name": "opencomputers:floppy_eject", "preload": true}
]
},
"floppy_insert": {
"category": "block",
"sounds": [
- "opencomputers:floppy_insert"
+ {"name": "opencomputers:floppy_insert", "preload": true}
]
},
"hdd_access": {
"category": "block",
"sounds": [
- "opencomputers:hdd_access1",
- "opencomputers:hdd_access2",
- "opencomputers:hdd_access3",
- "opencomputers:hdd_access4",
- "opencomputers:hdd_access5",
- "opencomputers:hdd_access6",
- "opencomputers:hdd_access7"
+ {"name": "opencomputers:hdd_access1", "preload": true},
+ {"name": "opencomputers:hdd_access2", "preload": true},
+ {"name": "opencomputers:hdd_access3", "preload": true},
+ {"name": "opencomputers:hdd_access4", "preload": true},
+ {"name": "opencomputers:hdd_access5", "preload": true},
+ {"name": "opencomputers:hdd_access6", "preload": true},
+ {"name": "opencomputers:hdd_access7", "preload": true}
]
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/sounds/preload.cfg b/src/main/resources/assets/opencomputers/sounds/preload.cfg
deleted file mode 100644
index e7334d6c89..0000000000
--- a/src/main/resources/assets/opencomputers/sounds/preload.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-assets/opencomputers/sounds/computer_running.ogg
-assets/opencomputers/sounds/floppy_access1.ogg
-assets/opencomputers/sounds/floppy_access2.ogg
-assets/opencomputers/sounds/floppy_access3.ogg
-assets/opencomputers/sounds/floppy_access4.ogg
-assets/opencomputers/sounds/floppy_access5.ogg
-assets/opencomputers/sounds/floppy_access6.ogg
-assets/opencomputers/sounds/floppy_eject.ogg
-assets/opencomputers/sounds/floppy_insert.ogg
-assets/opencomputers/sounds/hdd_access1.ogg
-assets/opencomputers/sounds/hdd_access2.ogg
-assets/opencomputers/sounds/hdd_access3.ogg
-assets/opencomputers/sounds/hdd_access4.ogg
-assets/opencomputers/sounds/hdd_access5.ogg
-assets/opencomputers/sounds/hdd_access6.ogg
-assets/opencomputers/sounds/hdd_access7.ogg
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyeblack.png b/src/main/resources/assets/opencomputers/textures/items/floppy_black.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyeblack.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_black.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyeblue.png b/src/main/resources/assets/opencomputers/textures/items/floppy_blue.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyeblue.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_blue.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyebrown.png b/src/main/resources/assets/opencomputers/textures/items/floppy_brown.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyebrown.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_brown.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyecyan.png b/src/main/resources/assets/opencomputers/textures/items/floppy_cyan.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyecyan.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_cyan.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyegray.png b/src/main/resources/assets/opencomputers/textures/items/floppy_gray.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyegray.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_gray.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyegreen.png b/src/main/resources/assets/opencomputers/textures/items/floppy_green.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyegreen.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_green.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyelightblue.png b/src/main/resources/assets/opencomputers/textures/items/floppy_light_blue.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyelightblue.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_light_blue.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyelightgray.png b/src/main/resources/assets/opencomputers/textures/items/floppy_light_gray.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyelightgray.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_light_gray.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyelime.png b/src/main/resources/assets/opencomputers/textures/items/floppy_lime.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyelime.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_lime.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyemagenta.png b/src/main/resources/assets/opencomputers/textures/items/floppy_magenta.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyemagenta.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_magenta.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyeorange.png b/src/main/resources/assets/opencomputers/textures/items/floppy_orange.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyeorange.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_orange.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyepink.png b/src/main/resources/assets/opencomputers/textures/items/floppy_pink.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyepink.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_pink.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyepurple.png b/src/main/resources/assets/opencomputers/textures/items/floppy_purple.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyepurple.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_purple.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyered.png b/src/main/resources/assets/opencomputers/textures/items/floppy_red.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyered.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_red.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyewhite.png b/src/main/resources/assets/opencomputers/textures/items/floppy_white.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyewhite.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_white.png
diff --git a/src/main/resources/assets/opencomputers/textures/items/floppy_dyeyellow.png b/src/main/resources/assets/opencomputers/textures/items/floppy_yellow.png
similarity index 100%
rename from src/main/resources/assets/opencomputers/textures/items/floppy_dyeyellow.png
rename to src/main/resources/assets/opencomputers/textures/items/floppy_yellow.png
diff --git a/src/main/resources/data/forge/tags/blocks/end_stones.json b/src/main/resources/data/forge/tags/blocks/end_stones.json
new file mode 100644
index 0000000000..55c89af86e
--- /dev/null
+++ b/src/main/resources/data/forge/tags/blocks/end_stones.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:endstone"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/forge/tags/blocks/pistons.json b/src/main/resources/data/forge/tags/blocks/pistons.json
new file mode 100644
index 0000000000..1fb4a6d786
--- /dev/null
+++ b/src/main/resources/data/forge/tags/blocks/pistons.json
@@ -0,0 +1,7 @@
+{
+ "replace": false,
+ "values": [
+ "minecraft:piston",
+ "minecraft:sticky_piston"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/forge/tags/items/beacon_base_blocks.json b/src/main/resources/data/forge/tags/items/beacon_base_blocks.json
new file mode 100644
index 0000000000..a368aa50b6
--- /dev/null
+++ b/src/main/resources/data/forge/tags/items/beacon_base_blocks.json
@@ -0,0 +1,10 @@
+{
+ "replace": false,
+ "values": [
+ "minecraft:netherite_block",
+ "minecraft:emerald_block",
+ "minecraft:diamond_block",
+ "minecraft:gold_block",
+ "minecraft:iron_block"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/forge/tags/items/end_stones.json b/src/main/resources/data/forge/tags/items/end_stones.json
new file mode 100644
index 0000000000..55c89af86e
--- /dev/null
+++ b/src/main/resources/data/forge/tags/items/end_stones.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:endstone"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/forge/tags/items/pistons.json b/src/main/resources/data/forge/tags/items/pistons.json
new file mode 100644
index 0000000000..1fb4a6d786
--- /dev/null
+++ b/src/main/resources/data/forge/tags/items/pistons.json
@@ -0,0 +1,7 @@
+{
+ "replace": false,
+ "values": [
+ "minecraft:piston",
+ "minecraft:sticky_piston"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/adapter.json b/src/main/resources/data/opencomputers/loot_tables/blocks/adapter.json
new file mode 100644
index 0000000000..31c6823d58
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/adapter.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:adapter"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/assembler.json b/src/main/resources/data/opencomputers/loot_tables/blocks/assembler.json
new file mode 100644
index 0000000000..3a2337bd51
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/assembler.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:assembler"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/cable.json b/src/main/resources/data/opencomputers/loot_tables/blocks/cable.json
new file mode 100644
index 0000000000..86950b69dd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/cable.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ],
+ "functions": [
+ {
+ "function": "opencomputers:copy_color"
+ }
+ ],
+ "name": "opencomputers:cable"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/capacitor.json b/src/main/resources/data/opencomputers/loot_tables/blocks/capacitor.json
new file mode 100644
index 0000000000..4a12dee16b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/capacitor.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:capacitor"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/carpetedcapacitor.json b/src/main/resources/data/opencomputers/loot_tables/blocks/carpetedcapacitor.json
new file mode 100644
index 0000000000..6e9658bbcd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/carpetedcapacitor.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:carpetedcapacitor"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/case1.json b/src/main/resources/data/opencomputers/loot_tables/blocks/case1.json
new file mode 100644
index 0000000000..0c75840b1c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/case1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:case1"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/case2.json b/src/main/resources/data/opencomputers/loot_tables/blocks/case2.json
new file mode 100644
index 0000000000..0b176c7fff
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/case2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:case2"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/case3.json b/src/main/resources/data/opencomputers/loot_tables/blocks/case3.json
new file mode 100644
index 0000000000..8124f0267f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/case3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:case3"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/chameliumblock.json b/src/main/resources/data/opencomputers/loot_tables/blocks/chameliumblock.json
new file mode 100644
index 0000000000..efec4024f1
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/chameliumblock.json
@@ -0,0 +1,315 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:alternatives",
+ "children": [
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "white"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 0}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "orange"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 1}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "magenta"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 2}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "light_blue"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 3}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "yellow"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 4}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "lime"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 5}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "pink"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 6}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "gray"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 7}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "light_gray"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 8}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "cyan"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 9}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "purple"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 10}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "blue"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 11}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "brown"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 12}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "green"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 13}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "conditions": [
+ {
+ "condition": "block_state_property",
+ "block": "opencomputers:chameliumblock",
+ "properties": {
+ "color": "red"
+ }
+ }
+ ],
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 14}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ },
+ {
+ "type": "minecraft:item",
+ "functions": [
+ {
+ "function": "set_nbt",
+ "tag": "{\"Damage\": 15}"
+ }
+ ],
+ "name": "opencomputers:chameliumblock"
+ }
+ ]
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/charger.json b/src/main/resources/data/opencomputers/loot_tables/blocks/charger.json
new file mode 100644
index 0000000000..160cb66781
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/charger.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:charger"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/disassembler.json b/src/main/resources/data/opencomputers/loot_tables/blocks/disassembler.json
new file mode 100644
index 0000000000..3f8705d01b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/disassembler.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:disassembler"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/diskdrive.json b/src/main/resources/data/opencomputers/loot_tables/blocks/diskdrive.json
new file mode 100644
index 0000000000..ba6a6807ca
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/diskdrive.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:diskdrive"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/endstone.json b/src/main/resources/data/opencomputers/loot_tables/blocks/endstone.json
new file mode 100644
index 0000000000..839f84ffef
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/endstone.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:endstone"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/geolyzer.json b/src/main/resources/data/opencomputers/loot_tables/blocks/geolyzer.json
new file mode 100644
index 0000000000..f011e9b434
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/geolyzer.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:geolyzer"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/hologram1.json b/src/main/resources/data/opencomputers/loot_tables/blocks/hologram1.json
new file mode 100644
index 0000000000..8e5d34e7f2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/hologram1.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:hologram1"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/hologram2.json b/src/main/resources/data/opencomputers/loot_tables/blocks/hologram2.json
new file mode 100644
index 0000000000..0e0f30749d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/hologram2.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:hologram2"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/keyboard.json b/src/main/resources/data/opencomputers/loot_tables/blocks/keyboard.json
new file mode 100644
index 0000000000..df15874146
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/keyboard.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:keyboard"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/microcontroller.json b/src/main/resources/data/opencomputers/loot_tables/blocks/microcontroller.json
new file mode 100644
index 0000000000..1749fc2bfb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/microcontroller.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:item_data"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/motionsensor.json b/src/main/resources/data/opencomputers/loot_tables/blocks/motionsensor.json
new file mode 100644
index 0000000000..baa71c8b2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/motionsensor.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:motionsensor"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/netsplitter.json b/src/main/resources/data/opencomputers/loot_tables/blocks/netsplitter.json
new file mode 100644
index 0000000000..66b2d6404d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/netsplitter.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:netsplitter"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/powerconverter.json b/src/main/resources/data/opencomputers/loot_tables/blocks/powerconverter.json
new file mode 100644
index 0000000000..867418f5f1
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/powerconverter.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:powerconverter"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/powerdistributor.json b/src/main/resources/data/opencomputers/loot_tables/blocks/powerdistributor.json
new file mode 100644
index 0000000000..ba25535d42
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/powerdistributor.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:powerdistributor"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/print.json b/src/main/resources/data/opencomputers/loot_tables/blocks/print.json
new file mode 100644
index 0000000000..1749fc2bfb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/print.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:item_data"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/printer.json b/src/main/resources/data/opencomputers/loot_tables/blocks/printer.json
new file mode 100644
index 0000000000..81a05e0e6b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/printer.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:printer"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/rack.json b/src/main/resources/data/opencomputers/loot_tables/blocks/rack.json
new file mode 100644
index 0000000000..1fa79578fb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/rack.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:rack"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/raid.json b/src/main/resources/data/opencomputers/loot_tables/blocks/raid.json
new file mode 100644
index 0000000000..1749fc2bfb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/raid.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:item_data"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/redstone.json b/src/main/resources/data/opencomputers/loot_tables/blocks/redstone.json
new file mode 100644
index 0000000000..5bfd376475
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/redstone.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:redstone"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/relay.json b/src/main/resources/data/opencomputers/loot_tables/blocks/relay.json
new file mode 100644
index 0000000000..47e2fe3750
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/relay.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:relay"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/robot.json b/src/main/resources/data/opencomputers/loot_tables/blocks/robot.json
new file mode 100644
index 0000000000..e6847c1658
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/robot.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:item_data"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ },
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:dynamic",
+ "name": "opencomputers:volatile_contents"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/screen1.json b/src/main/resources/data/opencomputers/loot_tables/blocks/screen1.json
new file mode 100644
index 0000000000..eea4e8dbe7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/screen1.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:screen1"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/screen2.json b/src/main/resources/data/opencomputers/loot_tables/blocks/screen2.json
new file mode 100644
index 0000000000..7be03aa442
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/screen2.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:screen2"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/screen3.json b/src/main/resources/data/opencomputers/loot_tables/blocks/screen3.json
new file mode 100644
index 0000000000..97e952e40c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/screen3.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:screen3"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/transposer.json b/src/main/resources/data/opencomputers/loot_tables/blocks/transposer.json
new file mode 100644
index 0000000000..891fce4664
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/transposer.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:transposer"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/loot_tables/blocks/waypoint.json b/src/main/resources/data/opencomputers/loot_tables/blocks/waypoint.json
new file mode 100644
index 0000000000..e80460addc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/loot_tables/blocks/waypoint.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "opencomputers:waypoint"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/acid.json b/src/main/resources/data/opencomputers/recipes/acid.json
new file mode 100644
index 0000000000..15b1167adf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/acid.json
@@ -0,0 +1,23 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "minecraft:water_bucket"
+ },
+ {
+ "item": "minecraft:sugar"
+ },
+ {
+ "tag": "forge:slimeballs"
+ },
+ {
+ "item": "minecraft:fermented_spider_eye"
+ },
+ {
+ "item": "minecraft:bone"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:acid"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/adapter.json b/src/main/resources/data/opencomputers/recipes/adapter.json
new file mode 100644
index 0000000000..3f6d502d52
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/adapter.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ici",
+ "cCc",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "c": {
+ "tag": "opencomputers:cable"
+ }
+ },
+ "result": {
+ "item": "opencomputers:adapter"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/alu.json b/src/main/resources/data/opencomputers/recipes/alu.json
new file mode 100644
index 0000000000..d288e261e8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/alu.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iri",
+ "TCT",
+ "iTi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:alu"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/analyzer.json b/src/main/resources/data/opencomputers/recipes/analyzer.json
new file mode 100644
index 0000000000..a904121de9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/analyzer.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "r ",
+ "Tg",
+ "Pg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "item": "minecraft:redstone_torch"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:analyzer"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/angelupgrade.json b/src/main/resources/data/opencomputers/recipes/angelupgrade.json
new file mode 100644
index 0000000000..5e04b328ad
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/angelupgrade.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iei",
+ "CpC",
+ "iei"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "e": {
+ "tag": "forge:ender_pearls"
+ },
+ "p": {
+ "item": "minecraft:sticky_piston"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:angelupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/apu1.json b/src/main/resources/data/opencomputers/recipes/apu1.json
new file mode 100644
index 0000000000..46a281d246
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/apu1.json
@@ -0,0 +1,28 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "gCg",
+ "PBG",
+ "gCg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus1"
+ },
+ "P": {
+ "tag": "opencomputers:cpu2"
+ },
+ "G": {
+ "tag": "opencomputers:graphicscard1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:apu1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/apu2.json b/src/main/resources/data/opencomputers/recipes/apu2.json
new file mode 100644
index 0000000000..0c8aca229f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/apu2.json
@@ -0,0 +1,28 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "dCd",
+ "PBG",
+ "dCd"
+ ],
+ "key": {
+ "d": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus2"
+ },
+ "P": {
+ "tag": "opencomputers:cpu3"
+ },
+ "G": {
+ "tag": "opencomputers:graphicscard2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:apu2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/arrowkeys.json b/src/main/resources/data/opencomputers/recipes/arrowkeys.json
new file mode 100644
index 0000000000..0001b732a2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/arrowkeys.json
@@ -0,0 +1,15 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ " b ",
+ "bbb"
+ ],
+ "key": {
+ "b": {
+ "item": "minecraft:stone_button"
+ }
+ },
+ "result": {
+ "item": "opencomputers:arrowkeys"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/assembler.json b/src/main/resources/data/opencomputers/recipes/assembler.json
new file mode 100644
index 0000000000..05e98a2a5f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/assembler.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iwi",
+ "pCp",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "w": {
+ "item": "minecraft:crafting_table"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:assembler"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/batteryupgrade1.json b/src/main/resources/data/opencomputers/recipes/batteryupgrade1.json
new file mode 100644
index 0000000000..54a468451e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/batteryupgrade1.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "igi",
+ "fCf",
+ "igi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "f": {
+ "item": "minecraft:iron_bars"
+ },
+ "C": {
+ "tag": "opencomputers:capacitor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:batteryupgrade1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/batteryupgrade2.json b/src/main/resources/data/opencomputers/recipes/batteryupgrade2.json
new file mode 100644
index 0000000000..a3fa203fa6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/batteryupgrade2.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "fgf",
+ "iCi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "f": {
+ "item": "minecraft:iron_bars"
+ },
+ "C": {
+ "tag": "opencomputers:capacitor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:batteryupgrade2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/batteryupgrade3.json b/src/main/resources/data/opencomputers/recipes/batteryupgrade3.json
new file mode 100644
index 0000000000..2c8175b7d8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/batteryupgrade3.json
@@ -0,0 +1,22 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "CDC",
+ "iCi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "D": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "C": {
+ "tag": "opencomputers:capacitor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:batteryupgrade3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/buttongroup.json b/src/main/resources/data/opencomputers/recipes/buttongroup.json
new file mode 100644
index 0000000000..e362e8e1b7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/buttongroup.json
@@ -0,0 +1,15 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "bbb",
+ "bbb"
+ ],
+ "key": {
+ "b": {
+ "item": "minecraft:stone_button"
+ }
+ },
+ "result": {
+ "item": "opencomputers:buttongroup"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cable.json b/src/main/resources/data/opencomputers/recipes/cable.json
new file mode 100644
index 0000000000..69ac62b492
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cable.json
@@ -0,0 +1,20 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ " i ",
+ "iri",
+ " i "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cable",
+ "count": 4
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/capacitor.json b/src/main/resources/data/opencomputers/recipes/capacitor.json
new file mode 100644
index 0000000000..da8b6f41dc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/capacitor.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iTi",
+ "gpg",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "p": {
+ "item": "minecraft:paper"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:capacitor"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/card.json b/src/main/resources/data/opencomputers/recipes/card.json
new file mode 100644
index 0000000000..e2c6cbf75b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/card.json
@@ -0,0 +1,22 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "i ",
+ "iP",
+ "ig"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:card"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cardcontainer1.json b/src/main/resources/data/opencomputers/recipes/cardcontainer1.json
new file mode 100644
index 0000000000..22af6e535d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cardcontainer1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "pc ",
+ "iBi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cardcontainer1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cardcontainer2.json b/src/main/resources/data/opencomputers/recipes/cardcontainer2.json
new file mode 100644
index 0000000000..d19606d58d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cardcontainer2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "pc ",
+ "iBi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cardcontainer2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cardcontainer3.json b/src/main/resources/data/opencomputers/recipes/cardcontainer3.json
new file mode 100644
index 0000000000..5b64f2e233
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cardcontainer3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gCg",
+ "pc ",
+ "gBg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cardcontainer3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/carpetedcapacitor.json b/src/main/resources/data/opencomputers/recipes/carpetedcapacitor.json
new file mode 100644
index 0000000000..f5558ecca6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/carpetedcapacitor.json
@@ -0,0 +1,14 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "opencomputers:capacitor"
+ },
+ {
+ "item": "minecraft:white_carpet"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:carpetedcapacitor"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/case1.json b/src/main/resources/data/opencomputers/recipes/case1.json
new file mode 100644
index 0000000000..5a6a1e8403
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/case1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "bcb",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "b": {
+ "item": "minecraft:iron_bars"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:case1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/case2.json b/src/main/resources/data/opencomputers/recipes/case2.json
new file mode 100644
index 0000000000..7b7a5d8375
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/case2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gCg",
+ "bcb",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "b": {
+ "item": "minecraft:iron_bars"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:case2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/case3.json b/src/main/resources/data/opencomputers/recipes/case3.json
new file mode 100644
index 0000000000..19977cf8c3
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/case3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "dCd",
+ "bcb",
+ "dPd"
+ ],
+ "key": {
+ "d": {
+ "tag": "forge:gems/diamond"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "b": {
+ "item": "minecraft:iron_bars"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:case3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium.json b/src/main/resources/data/opencomputers/recipes/chamelium.json
new file mode 100644
index 0000000000..142061bcca
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium.json
@@ -0,0 +1,26 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "grg",
+ "rcr",
+ "gwg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:gravel"
+ },
+ "c": {
+ "item": "minecraft:coal"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "w": {
+ "item": "minecraft:water_bucket"
+ }
+ },
+ "result": {
+ "item": "opencomputers:chamelium",
+ "count": 16
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/black.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/black.json
new file mode 100644
index 0000000000..97407ee4d2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/black.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/black"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 15}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/blue.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/blue.json
new file mode 100644
index 0000000000..80bd6b7d2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/blue.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/blue"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 11}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/brown.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/brown.json
new file mode 100644
index 0000000000..ab3af44cc7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/brown.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/brown"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 12}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/cyan.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/cyan.json
new file mode 100644
index 0000000000..20743e1196
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/cyan.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/cyan"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 9}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/gray.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/gray.json
new file mode 100644
index 0000000000..b21b3381f4
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/gray.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/gray"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 7}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/green.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/green.json
new file mode 100644
index 0000000000..346eb6f2e9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/green.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/green"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 13}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/light_blue.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/light_blue.json
new file mode 100644
index 0000000000..ab76c12891
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/light_blue.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/light_blue"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 3}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/light_gray.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/light_gray.json
new file mode 100644
index 0000000000..34773f95e8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/light_gray.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/light_gray"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 8}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/lime.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/lime.json
new file mode 100644
index 0000000000..fa53032ac2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/lime.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/lime"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 5}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/magenta.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/magenta.json
new file mode 100644
index 0000000000..511d06dd7c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/magenta.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/magenta"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 2}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/orange.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/orange.json
new file mode 100644
index 0000000000..ef2f9f1acf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/orange.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/orange"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 1}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/pink.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/pink.json
new file mode 100644
index 0000000000..bc08ba163d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/pink.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/pink"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 6}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/purple.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/purple.json
new file mode 100644
index 0000000000..c1e7dc7a1e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/purple.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/purple"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 10}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/red.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/red.json
new file mode 100644
index 0000000000..531e3fea2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/red.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/red"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 14}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/white.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/white.json
new file mode 100644
index 0000000000..c3a17fad8a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/white.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/white"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 0}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/coloring/yellow.json b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/yellow.json
new file mode 100644
index 0000000000..db4d68f66c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/coloring/yellow.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ },
+ {
+ "tag": "forge:dyes/yellow"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": "{\"Damage\": 4}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chamelium/splitting.json b/src/main/resources/data/opencomputers/recipes/chamelium/splitting.json
new file mode 100644
index 0000000000..f482d07bf0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chamelium/splitting.json
@@ -0,0 +1,12 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:chameliumblock"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chamelium",
+ "count": 9
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chameliumblock.json b/src/main/resources/data/opencomputers/recipes/chameliumblock.json
new file mode 100644
index 0000000000..26e10cdc9b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chameliumblock.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CCC",
+ "CCC",
+ "CCC"
+ ],
+ "key": {
+ "C": {
+ "tag": "opencomputers:chamelium"
+ }
+ },
+ "result": {
+ "item": "opencomputers:chameliumblock",
+ "nbt": {
+ "Damage": 15
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/charger.json b/src/main/resources/data/opencomputers/recipes/charger.json
new file mode 100644
index 0000000000..53e3bf9ff4
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/charger.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "igi",
+ "cCc",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "c": {
+ "tag": "opencomputers:capacitor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:charger"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chip1.json b/src/main/resources/data/opencomputers/recipes/chip1.json
new file mode 100644
index 0000000000..bc19e69fb7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chip1.json
@@ -0,0 +1,23 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iii",
+ "rTr",
+ "iii"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:chip1",
+ "count": 8
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chip2.json b/src/main/resources/data/opencomputers/recipes/chip2.json
new file mode 100644
index 0000000000..46e02f835f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chip2.json
@@ -0,0 +1,23 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ggg",
+ "rTr",
+ "ggg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:chip2",
+ "count": 4
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chip3.json b/src/main/resources/data/opencomputers/recipes/chip3.json
new file mode 100644
index 0000000000..4175689448
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chip3.json
@@ -0,0 +1,23 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ddd",
+ "rTr",
+ "ddd"
+ ],
+ "key": {
+ "d": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:chip3",
+ "count": 2
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chipdiamond.json b/src/main/resources/data/opencomputers/recipes/chipdiamond.json
new file mode 100644
index 0000000000..1154a176d3
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chipdiamond.json
@@ -0,0 +1,15 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "opencomputers:materialcuttingwire"
+ },
+ {
+ "tag": "forge:gems/diamond"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:chipdiamond",
+ "count": 6
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/chunkloaderupgrade.json b/src/main/resources/data/opencomputers/recipes/chunkloaderupgrade.json
new file mode 100644
index 0000000000..79f50e7d5b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/chunkloaderupgrade.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gsg",
+ "CeC",
+ "oPo"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "s": {
+ "tag": "forge:glass"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "e": {
+ "item": "minecraft:ender_eye"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:chunkloaderupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/colorize/cable.json b/src/main/resources/data/opencomputers/recipes/colorize/cable.json
new file mode 100644
index 0000000000..ea91e59f72
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/colorize/cable.json
@@ -0,0 +1,4 @@
+{
+ "type": "opencomputers:crafting_colorize",
+ "item": "opencomputers:cable"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/colorize/hoverboots.json b/src/main/resources/data/opencomputers/recipes/colorize/hoverboots.json
new file mode 100644
index 0000000000..973455979f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/colorize/hoverboots.json
@@ -0,0 +1,4 @@
+{
+ "type": "opencomputers:crafting_colorize",
+ "item": "opencomputers:hoverboots"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/componentbus1.json b/src/main/resources/data/opencomputers/recipes/componentbus1.json
new file mode 100644
index 0000000000..d1dd337f6f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/componentbus1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iri",
+ "CU ",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:componentbus1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/componentbus2.json b/src/main/resources/data/opencomputers/recipes/componentbus2.json
new file mode 100644
index 0000000000..9170c64a42
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/componentbus2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "grg",
+ "CU ",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:componentbus2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/componentbus3.json b/src/main/resources/data/opencomputers/recipes/componentbus3.json
new file mode 100644
index 0000000000..d66b7019fc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/componentbus3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "drd",
+ "CU ",
+ "dPd"
+ ],
+ "key": {
+ "d": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:componentbus3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cpu1.json b/src/main/resources/data/opencomputers/recipes/cpu1.json
new file mode 100644
index 0000000000..ff8fce0e20
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cpu1.json
@@ -0,0 +1,28 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "iri",
+ "CUC",
+ "iAi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cpu1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cpu2.json b/src/main/resources/data/opencomputers/recipes/cpu2.json
new file mode 100644
index 0000000000..b829c63c3a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cpu2.json
@@ -0,0 +1,28 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "grg",
+ "CUC",
+ "gAg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cpu2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cpu3.json b/src/main/resources/data/opencomputers/recipes/cpu3.json
new file mode 100644
index 0000000000..20c11e9956
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cpu3.json
@@ -0,0 +1,28 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "drd",
+ "CUC",
+ "dAd"
+ ],
+ "key": {
+ "d": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cpu3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/craftingupgrade.json b/src/main/resources/data/opencomputers/recipes/craftingupgrade.json
new file mode 100644
index 0000000000..cafa5ae156
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/craftingupgrade.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "i i",
+ "CwC",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "w": {
+ "item": "minecraft:crafting_table"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:craftingupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cu.json b/src/main/resources/data/opencomputers/recipes/cu.json
new file mode 100644
index 0000000000..d12240688b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cu.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "grg",
+ "TcT",
+ "gTg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "c": {
+ "item": "minecraft:clock"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cu"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/cuttingwire.json b/src/main/resources/data/opencomputers/recipes/cuttingwire.json
new file mode 100644
index 0000000000..343093c2e9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/cuttingwire.json
@@ -0,0 +1,17 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "sis"
+ ],
+ "key": {
+ "s": {
+ "tag": "forge:rods/wooden"
+ },
+ "i": {
+ "tag": "forge:nuggets/iron"
+ }
+ },
+ "result": {
+ "item": "opencomputers:cuttingwire"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/databaseupgrade1.json b/src/main/resources/data/opencomputers/recipes/databaseupgrade1.json
new file mode 100644
index 0000000000..f23b93b915
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/databaseupgrade1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iAi",
+ "CHC",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "A": {
+ "tag": "opencomputers:analyzer"
+ },
+ "H": {
+ "tag": "opencomputers:hdd1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:databaseupgrade1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/databaseupgrade2.json b/src/main/resources/data/opencomputers/recipes/databaseupgrade2.json
new file mode 100644
index 0000000000..c6576ea95d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/databaseupgrade2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iAi",
+ "CHC",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "A": {
+ "tag": "opencomputers:analyzer"
+ },
+ "H": {
+ "tag": "opencomputers:hdd2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:databaseupgrade2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/databaseupgrade3.json b/src/main/resources/data/opencomputers/recipes/databaseupgrade3.json
new file mode 100644
index 0000000000..4a194ba8dc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/databaseupgrade3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iAi",
+ "CHC",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "A": {
+ "tag": "opencomputers:analyzer"
+ },
+ "H": {
+ "tag": "opencomputers:hdd3"
+ }
+ },
+ "result": {
+ "item": "opencomputers:databaseupgrade3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/datacard1.json b/src/main/resources/data/opencomputers/recipes/datacard1.json
new file mode 100644
index 0000000000..9c3eb403ef
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/datacard1.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iAC",
+ " B "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ }
+ },
+ "result": {
+ "item": "opencomputers:datacard1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/datacard2.json b/src/main/resources/data/opencomputers/recipes/datacard2.json
new file mode 100644
index 0000000000..f76d6038ff
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/datacard2.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gPC",
+ " B "
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "P": {
+ "tag": "opencomputers:cpu1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:datacard2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/datacard3.json b/src/main/resources/data/opencomputers/recipes/datacard3.json
new file mode 100644
index 0000000000..f6cda2b60f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/datacard3.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "dPM",
+ " B "
+ ],
+ "key": {
+ "d": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "M": {
+ "tag": "opencomputers:ram5"
+ },
+ "P": {
+ "tag": "opencomputers:cpu2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:datacard3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/decolorize/cable.json b/src/main/resources/data/opencomputers/recipes/decolorize/cable.json
new file mode 100644
index 0000000000..61a33288e6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/decolorize/cable.json
@@ -0,0 +1,4 @@
+{
+ "type": "opencomputers:crafting_decolorize",
+ "item": "opencomputers:cable"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/decolorize/hoverboots.json b/src/main/resources/data/opencomputers/recipes/decolorize/hoverboots.json
new file mode 100644
index 0000000000..ba63396e0b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/decolorize/hoverboots.json
@@ -0,0 +1,4 @@
+{
+ "type": "opencomputers:crafting_decolorize",
+ "item": "opencomputers:hoverboots"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/disassembler.json b/src/main/resources/data/opencomputers/recipes/disassembler.json
new file mode 100644
index 0000000000..41d0a8e3cc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/disassembler.json
@@ -0,0 +1,34 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "UgA",
+ "p o",
+ "ili"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:glass_panes"
+ },
+ "l": {
+ "item": "minecraft:lava_bucket"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "U": {
+ "tag": "opencomputers:materialcu"
+ },
+ "A": {
+ "tag": "opencomputers:analyzer"
+ }
+ },
+ "result": {
+ "item": "opencomputers:disassembler"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/disk.json b/src/main/resources/data/opencomputers/recipes/disk.json
new file mode 100644
index 0000000000..ae74390769
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/disk.json
@@ -0,0 +1,16 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ " i ",
+ "i i",
+ " i "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ }
+ },
+ "result": {
+ "item": "opencomputers:disk"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/diskdrive.json b/src/main/resources/data/opencomputers/recipes/diskdrive.json
new file mode 100644
index 0000000000..4049801bab
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/diskdrive.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "ps ",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "s": {
+ "tag": "forge:rods/wooden"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:diskdrive"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/diskdrivemountable.json b/src/main/resources/data/opencomputers/recipes/diskdrivemountable.json
new file mode 100644
index 0000000000..58689b43bb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/diskdrivemountable.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "oCo",
+ "fDf",
+ "oPo"
+ ],
+ "key": {
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "f": {
+ "item": "minecraft:iron_bars"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "D": {
+ "tag": "opencomputers:diskdrive"
+ }
+ },
+ "result": {
+ "item": "opencomputers:diskdrivemountable"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/dronecase1.json b/src/main/resources/data/opencomputers/recipes/dronecase1.json
new file mode 100644
index 0000000000..bd37834b2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/dronecase1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "EcE",
+ "CMC",
+ "EBE"
+ ],
+ "key": {
+ "c": {
+ "item": "minecraft:compass"
+ },
+ "E": {
+ "tag": "forge:end_stones"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus2"
+ },
+ "M": {
+ "tag": "opencomputers:microcontrollercase1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:dronecase1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/dronecase2.json b/src/main/resources/data/opencomputers/recipes/dronecase2.json
new file mode 100644
index 0000000000..47e5ed298e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/dronecase2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "EcE",
+ "CMC",
+ "EBE"
+ ],
+ "key": {
+ "c": {
+ "item": "minecraft:compass"
+ },
+ "E": {
+ "tag": "forge:end_stones"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus3"
+ },
+ "M": {
+ "tag": "opencomputers:microcontrollercase2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:dronecase2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/eeprom.json b/src/main/resources/data/opencomputers/recipes/eeprom.json
new file mode 100644
index 0000000000..9b8572103a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/eeprom.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gTg",
+ "pCp",
+ "grg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "p": {
+ "item": "minecraft:paper"
+ },
+ "r": {
+ "item": "minecraft:redstone_torch"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:eeprom"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/eeprom/copying.json b/src/main/resources/data/opencomputers/recipes/eeprom/copying.json
new file mode 100644
index 0000000000..18df60cb9c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/eeprom/copying.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:eeprom"
+ },
+ {
+ "item": "opencomputers:eeprom"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:eeprom",
+ "count": 2
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/eeprom/formatting.json b/src/main/resources/data/opencomputers/recipes/eeprom/formatting.json
new file mode 100644
index 0000000000..9753bd3e30
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/eeprom/formatting.json
@@ -0,0 +1,11 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:eeprom"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:eeprom"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/endstone.json b/src/main/resources/data/opencomputers/recipes/endstone.json
new file mode 100644
index 0000000000..0d872c3c48
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/endstone.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "eCe",
+ "CeC",
+ "eCe"
+ ],
+ "key": {
+ "e": {
+ "tag": "forge:ender_pearls"
+ },
+ "C": {
+ "tag": "opencomputers:chameliumblock"
+ }
+ },
+ "result": {
+ "item": "opencomputers:endstone"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/experienceupgrade.json b/src/main/resources/data/opencomputers/recipes/experienceupgrade.json
new file mode 100644
index 0000000000..136f7e3030
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/experienceupgrade.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "g g",
+ "CeC",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "e": {
+ "tag": "forge:gems/emerald"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:experienceupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy.json b/src/main/resources/data/opencomputers/recipes/floppy.json
new file mode 100644
index 0000000000..72c332f673
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ili",
+ "pDp",
+ "ipi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "p": {
+ "item": "minecraft:paper"
+ },
+ "l": {
+ "item": "minecraft:lever"
+ },
+ "D": {
+ "tag": "opencomputers:materialdisk"
+ }
+ },
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": {
+ "oc:color": 8
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/black.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/black.json
new file mode 100644
index 0000000000..53ef4be93d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/black.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/black"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 15}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/blue.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/blue.json
new file mode 100644
index 0000000000..bc56769cc8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/blue.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/blue"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 11}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/brown.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/brown.json
new file mode 100644
index 0000000000..dca6215ef2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/brown.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/brown"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 12}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/cyan.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/cyan.json
new file mode 100644
index 0000000000..03fe66029a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/cyan.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/cyan"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 9}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/gray.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/gray.json
new file mode 100644
index 0000000000..80749c1616
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/gray.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/gray"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 7}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/green.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/green.json
new file mode 100644
index 0000000000..c1923cde86
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/green.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/green"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 13}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/light_blue.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/light_blue.json
new file mode 100644
index 0000000000..d70ede156b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/light_blue.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/light_blue"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 3}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/light_gray.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/light_gray.json
new file mode 100644
index 0000000000..c754fbc926
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/light_gray.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/light_gray"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 8}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/lime.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/lime.json
new file mode 100644
index 0000000000..cc6234e310
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/lime.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/lime"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 5}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/magenta.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/magenta.json
new file mode 100644
index 0000000000..594f55833a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/magenta.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/magenta"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 2}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/orange.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/orange.json
new file mode 100644
index 0000000000..1f14c00dd8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/orange.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/orange"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 1}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/pink.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/pink.json
new file mode 100644
index 0000000000..b019825ebc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/pink.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/pink"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 6}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/purple.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/purple.json
new file mode 100644
index 0000000000..a6940ee66d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/purple.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/purple"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 10}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/red.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/red.json
new file mode 100644
index 0000000000..23680d120b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/red.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/red"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 14}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/white.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/white.json
new file mode 100644
index 0000000000..4040d59402
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/white.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/white"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 0}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/coloring/yellow.json b/src/main/resources/data/opencomputers/recipes/floppy/coloring/yellow.json
new file mode 100644
index 0000000000..5472ebd757
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/coloring/yellow.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ },
+ {
+ "tag": "forge:dyes/yellow"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": "{\"oc:color\": 4}"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/floppy/formatting.json b/src/main/resources/data/opencomputers/recipes/floppy/formatting.json
new file mode 100644
index 0000000000..0358f3a9d2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/floppy/formatting.json
@@ -0,0 +1,11 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:floppy"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/generatorupgrade.json b/src/main/resources/data/opencomputers/recipes/generatorupgrade.json
new file mode 100644
index 0000000000..d367d0d843
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/generatorupgrade.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "i i",
+ "CpC",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:generatorupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/geolyzer.json b/src/main/resources/data/opencomputers/recipes/geolyzer.json
new file mode 100644
index 0000000000..e7899a2e4f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/geolyzer.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gcg",
+ "eCe",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "c": {
+ "item": "minecraft:compass"
+ },
+ "e": {
+ "item": "minecraft:ender_eye"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:geolyzer"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/graphicscard1.json b/src/main/resources/data/opencomputers/recipes/graphicscard1.json
new file mode 100644
index 0000000000..9ca3f647f6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/graphicscard1.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CAM",
+ " B "
+ ],
+ "key": {
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ },
+ "M": {
+ "tag": "opencomputers:ram1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:graphicscard1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/graphicscard2.json b/src/main/resources/data/opencomputers/recipes/graphicscard2.json
new file mode 100644
index 0000000000..0689f0ee3e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/graphicscard2.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CAM",
+ " B "
+ ],
+ "key": {
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ },
+ "M": {
+ "tag": "opencomputers:ram3"
+ }
+ },
+ "result": {
+ "item": "opencomputers:graphicscard2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/graphicscard3.json b/src/main/resources/data/opencomputers/recipes/graphicscard3.json
new file mode 100644
index 0000000000..f47935e0db
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/graphicscard3.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CAM",
+ " B "
+ ],
+ "key": {
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "A": {
+ "tag": "opencomputers:materialalu"
+ },
+ "M": {
+ "tag": "opencomputers:ram5"
+ }
+ },
+ "result": {
+ "item": "opencomputers:graphicscard3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hdd/formatting1.json b/src/main/resources/data/opencomputers/recipes/hdd/formatting1.json
new file mode 100644
index 0000000000..42a71dbf08
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hdd/formatting1.json
@@ -0,0 +1,11 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:hdd1"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:hdd1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hdd/formatting2.json b/src/main/resources/data/opencomputers/recipes/hdd/formatting2.json
new file mode 100644
index 0000000000..647faaecfb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hdd/formatting2.json
@@ -0,0 +1,11 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:hdd2"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:hdd2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hdd/formatting3.json b/src/main/resources/data/opencomputers/recipes/hdd/formatting3.json
new file mode 100644
index 0000000000..6907530501
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hdd/formatting3.json
@@ -0,0 +1,11 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:hdd3"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:hdd3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hdd1.json b/src/main/resources/data/opencomputers/recipes/hdd1.json
new file mode 100644
index 0000000000..1a4848e4ed
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hdd1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CDi",
+ "PDp",
+ "CDi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "D": {
+ "tag": "opencomputers:materialdisk"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hdd1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hdd2.json b/src/main/resources/data/opencomputers/recipes/hdd2.json
new file mode 100644
index 0000000000..bb91754de5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hdd2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CDg",
+ "PDp",
+ "CDg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "D": {
+ "tag": "opencomputers:materialdisk"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hdd2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hdd3.json b/src/main/resources/data/opencomputers/recipes/hdd3.json
new file mode 100644
index 0000000000..2e552d2487
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hdd3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CDd",
+ "PDp",
+ "CDd"
+ ],
+ "key": {
+ "d": {
+ "tag": "forge:gems/diamond"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "D": {
+ "tag": "opencomputers:materialdisk"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hdd3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hologram1.json b/src/main/resources/data/opencomputers/recipes/hologram1.json
new file mode 100644
index 0000000000..051ad335e9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hologram1.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CgC",
+ "PdP",
+ "oGo"
+ ],
+ "key": {
+ "d": {
+ "tag": "opencomputers:chipdiamond"
+ },
+ "g": {
+ "tag": "forge:glass_panes"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "G": {
+ "tag": "forge:dusts/glowstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hologram1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hologram2.json b/src/main/resources/data/opencomputers/recipes/hologram2.json
new file mode 100644
index 0000000000..9874b8967b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hologram2.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CgC",
+ "PdP",
+ "obo"
+ ],
+ "key": {
+ "d": {
+ "tag": "forge:gems/diamond"
+ },
+ "g": {
+ "tag": "forge:glass"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "b": {
+ "item": "minecraft:blaze_powder"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hologram2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hoverboots.json b/src/main/resources/data/opencomputers/recipes/hoverboots.json
new file mode 100644
index 0000000000..5fe0b7addd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hoverboots.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iHi",
+ "LDL",
+ "iCi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "L": {
+ "tag": "forge:leather"
+ },
+ "C": {
+ "tag": "opencomputers:capacitor"
+ },
+ "D": {
+ "tag": "opencomputers:dronecase1"
+ },
+ "H": {
+ "tag": "opencomputers:hoverupgrade2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hoverboots"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hoverupgrade1.json b/src/main/resources/data/opencomputers/recipes/hoverupgrade1.json
new file mode 100644
index 0000000000..c38ca51e02
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hoverupgrade1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "fCf",
+ "ili",
+ "fPf"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "f": {
+ "tag": "forge:feathers"
+ },
+ "l": {
+ "tag": "forge:leather"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hoverupgrade1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/hoverupgrade2.json b/src/main/resources/data/opencomputers/recipes/hoverupgrade2.json
new file mode 100644
index 0000000000..4546f46371
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/hoverupgrade2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "eCe",
+ "gig",
+ "ePe"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "e": {
+ "tag": "forge:end_stones"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:hoverupgrade2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/inkcartridge.json b/src/main/resources/data/opencomputers/recipes/inkcartridge.json
new file mode 100644
index 0000000000..655c4a619a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/inkcartridge.json
@@ -0,0 +1,23 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "opencomputers:inkcartridgeempty"
+ },
+ {
+ "tag": "forge:dyes/cyan"
+ },
+ {
+ "tag": "forge:dyes/magenta"
+ },
+ {
+ "tag": "forge:dyes/yellow"
+ },
+ {
+ "tag": "forge:dyes/black"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:inkcartridge"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/inkcartridgeempty.json b/src/main/resources/data/opencomputers/recipes/inkcartridgeempty.json
new file mode 100644
index 0000000000..f05081ba5c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/inkcartridgeempty.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "idi",
+ "TbT",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "b": {
+ "item": "minecraft:bucket"
+ },
+ "d": {
+ "item": "minecraft:dispenser"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:inkcartridgeempty"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/internetcard.json b/src/main/resources/data/opencomputers/recipes/internetcard.json
new file mode 100644
index 0000000000..bc91064094
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/internetcard.json
@@ -0,0 +1,27 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ICr",
+ " Bo"
+ ],
+ "key": {
+ "r": {
+ "item": "minecraft:redstone_torch"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "I": {
+ "tag": "opencomputers:materialinterweb"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:internetcard"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/interweb.json b/src/main/resources/data/opencomputers/recipes/interweb.json
new file mode 100644
index 0000000000..75cd6112ff
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/interweb.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "sss",
+ "ses",
+ "sss"
+ ],
+ "key": {
+ "s": {
+ "tag": "forge:string"
+ },
+ "e": {
+ "tag": "forge:ender_pearls"
+ }
+ },
+ "result": {
+ "item": "opencomputers:interweb"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/inventorycontrollerupgrade.json b/src/main/resources/data/opencomputers/recipes/inventorycontrollerupgrade.json
new file mode 100644
index 0000000000..abc5d11cea
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/inventorycontrollerupgrade.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gAg",
+ "dCp",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "d": {
+ "item": "minecraft:dropper"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "A": {
+ "tag": "opencomputers:analyzer"
+ }
+ },
+ "result": {
+ "item": "opencomputers:inventorycontrollerupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/inventoryupgrade.json b/src/main/resources/data/opencomputers/recipes/inventoryupgrade.json
new file mode 100644
index 0000000000..89dac6713b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/inventoryupgrade.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "whw",
+ "dcp",
+ "wCw"
+ ],
+ "key": {
+ "w": {
+ "tag": "minecraft:planks"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "h": {
+ "item": "minecraft:hopper"
+ },
+ "d": {
+ "item": "minecraft:dropper"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:inventoryupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/keyboard.json b/src/main/resources/data/opencomputers/recipes/keyboard.json
new file mode 100644
index 0000000000..d84354246e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/keyboard.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "BBB",
+ "BAN"
+ ],
+ "key": {
+ "B": {
+ "tag": "opencomputers:materialbuttongroup"
+ },
+ "A": {
+ "tag": "opencomputers:materialarrowkey"
+ },
+ "N": {
+ "tag": "opencomputers:materialnumpad"
+ }
+ },
+ "result": {
+ "item": "opencomputers:keyboard"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/lancard.json b/src/main/resources/data/opencomputers/recipes/lancard.json
new file mode 100644
index 0000000000..c05ba47d6d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/lancard.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cC",
+ " B"
+ ],
+ "key": {
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ },
+ "c": {
+ "tag": "opencomputers:cable"
+ }
+ },
+ "result": {
+ "item": "opencomputers:lancard"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/leashupgrade.json b/src/main/resources/data/opencomputers/recipes/leashupgrade.json
new file mode 100644
index 0000000000..f6961c829a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/leashupgrade.json
@@ -0,0 +1,22 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ili",
+ "lCl",
+ "ili"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "l": {
+ "item": "minecraft:lead"
+ },
+ "C": {
+ "tag": "opencomputers:materialcu"
+ }
+ },
+ "result": {
+ "item": "opencomputers:leashupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/linkedcard.json b/src/main/resources/data/opencomputers/recipes/linkedcard.json
new file mode 100644
index 0000000000..4726421fb8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/linkedcard.json
@@ -0,0 +1,26 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "e e",
+ "LIL",
+ "C C"
+ ],
+ "key": {
+ "e": {
+ "item": "minecraft:ender_eye"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "I": {
+ "tag": "opencomputers:materialinterweb"
+ },
+ "L": {
+ "tag": "opencomputers:lancard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:linkedcard",
+ "count": 2
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/lootdisks/cycling.json b/src/main/resources/data/opencomputers/recipes/lootdisks/cycling.json
new file mode 100644
index 0000000000..61e59a9a0b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/lootdisks/cycling.json
@@ -0,0 +1,3 @@
+{
+ "type": "opencomputers:crafting_lootdisk_cycling"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/lootdisks/openos.json b/src/main/resources/data/opencomputers/recipes/lootdisks/openos.json
new file mode 100644
index 0000000000..5538f43146
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/lootdisks/openos.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "opencomputers:floppy"
+ },
+ {
+ "tag": "opencomputers:manual"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": {
+ "oc:data": {
+ "oc:fs.label": "openos"
+ },
+ "oc:lootFactory": "opencomputers:openos",
+ "oc:color": 13,
+ "display": {
+ "Name": "OpenOS (Operating System)"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/lootdisks/oppm.json b/src/main/resources/data/opencomputers/recipes/lootdisks/oppm.json
new file mode 100644
index 0000000000..cc90e6462d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/lootdisks/oppm.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "opencomputers:floppy"
+ },
+ {
+ "tag": "opencomputers:materialinterweb"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:floppy",
+ "nbt": {
+ "oc:data": {
+ "oc:fs.label": "oppm"
+ },
+ "oc:lootFactory": "opencomputers:oppm",
+ "oc:color": 9,
+ "display": {
+ "Name": "OPPM (Package Manager)"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/manual.json b/src/main/resources/data/opencomputers/recipes/manual.json
new file mode 100644
index 0000000000..0e9ace7902
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/manual.json
@@ -0,0 +1,14 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "minecraft:book"
+ },
+ {
+ "tag": "opencomputers:circuitchip1"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:manual"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/mfu.json b/src/main/resources/data/opencomputers/recipes/mfu.json
new file mode 100644
index 0000000000..38fc731b06
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/mfu.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "clc",
+ "LAL",
+ "clc"
+ ],
+ "key": {
+ "l": {
+ "tag": "forge:gems/lapis"
+ },
+ "c": {
+ "tag": "opencomputers:chamelium"
+ },
+ "A": {
+ "tag": "opencomputers:adapter"
+ },
+ "L": {
+ "tag": "opencomputers:linkedcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:mfu"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/microcontrollercase1.json b/src/main/resources/data/opencomputers/recipes/microcontrollercase1.json
new file mode 100644
index 0000000000..8677c74faf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/microcontrollercase1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "rcr",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:microcontrollercase1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/microcontrollercase2.json b/src/main/resources/data/opencomputers/recipes/microcontrollercase2.json
new file mode 100644
index 0000000000..48e014f315
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/microcontrollercase2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gCg",
+ "rcr",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "tag": "forge:storage_blocks/redstone"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:microcontrollercase2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/motionsensor.json b/src/main/resources/data/opencomputers/recipes/motionsensor.json
new file mode 100644
index 0000000000..213b73a3b1
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/motionsensor.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gdg",
+ "dCd",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "d": {
+ "item": "minecraft:daylight_detector"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "C": {
+ "tag": "opencomputers:cpu2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:motionsensor"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/nanomachines.json b/src/main/resources/data/opencomputers/recipes/nanomachines.json
new file mode 100644
index 0000000000..ab356d004d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/nanomachines.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "SRS",
+ "PAM",
+ "SCS"
+ ],
+ "key": {
+ "S": {
+ "tag": "opencomputers:chamelium"
+ },
+ "A": {
+ "tag": "opencomputers:materialacid"
+ },
+ "C": {
+ "tag": "opencomputers:capacitor"
+ },
+ "R": {
+ "tag": "opencomputers:wlancard2"
+ },
+ "M": {
+ "tag": "opencomputers:ram1"
+ },
+ "P": {
+ "tag": "opencomputers:cpu2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:nanomachines"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/navigationupgrade.json b/src/main/resources/data/opencomputers/recipes/navigationupgrade.json
new file mode 100644
index 0000000000..4281e79c26
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/navigationupgrade.json
@@ -0,0 +1,28 @@
+{
+ "type": "opencomputers:crafting_shaped_extended",
+ "pattern": [
+ "gcg",
+ "CmC",
+ "gpg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "c": {
+ "item": "minecraft:compass"
+ },
+ "m": {
+ "item": "minecraft:filled_map"
+ },
+ "p": {
+ "item": "minecraft:potion"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:navigationupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/netsplitter.json b/src/main/resources/data/opencomputers/recipes/netsplitter.json
new file mode 100644
index 0000000000..16e9330a7a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/netsplitter.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ici",
+ "cpc",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "c": {
+ "tag": "opencomputers:cable"
+ }
+ },
+ "result": {
+ "item": "opencomputers:netsplitter"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/numpad.json b/src/main/resources/data/opencomputers/recipes/numpad.json
new file mode 100644
index 0000000000..82aef08dcf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/numpad.json
@@ -0,0 +1,16 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "bbb",
+ "bbb",
+ "bbb"
+ ],
+ "key": {
+ "b": {
+ "item": "minecraft:stone_button"
+ }
+ },
+ "result": {
+ "item": "opencomputers:numpad"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/pistonupgrade.json b/src/main/resources/data/opencomputers/recipes/pistonupgrade.json
new file mode 100644
index 0000000000..84ef4b78de
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/pistonupgrade.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ipi",
+ "sCs",
+ "iPi"
+ ],
+ "key": {
+ "s": {
+ "tag": "forge:rods/wooden"
+ },
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:pistonupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/powerconverter.json b/src/main/resources/data/opencomputers/recipes/powerconverter.json
new file mode 100644
index 0000000000..4d8d4ebec2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/powerconverter.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ici",
+ "gCg",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "c": {
+ "tag": "opencomputers:cable"
+ }
+ },
+ "result": {
+ "item": "opencomputers:powerconverter"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/powerdistributor.json b/src/main/resources/data/opencomputers/recipes/powerdistributor.json
new file mode 100644
index 0000000000..eacc393044
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/powerdistributor.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "igi",
+ "cCc",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "c": {
+ "tag": "opencomputers:cable"
+ }
+ },
+ "result": {
+ "item": "opencomputers:powerdistributor"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/print/beacon.json b/src/main/resources/data/opencomputers/recipes/print/beacon.json
new file mode 100644
index 0000000000..e9ea88d3da
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/print/beacon.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:print"
+ },
+ {
+ "tag": "forge:beacon_base_blocks"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:print"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/print/glowstone.json b/src/main/resources/data/opencomputers/recipes/print/glowstone.json
new file mode 100644
index 0000000000..0e3d021bf0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/print/glowstone.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:print"
+ },
+ {
+ "item": "minecraft:glowstone"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:print"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/print/glowstone_dust.json b/src/main/resources/data/opencomputers/recipes/print/glowstone_dust.json
new file mode 100644
index 0000000000..70668225ed
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/print/glowstone_dust.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:print"
+ },
+ {
+ "tag": "forge:dusts/glowstone"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:print"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/printedcircuitboard.json b/src/main/resources/data/opencomputers/recipes/printedcircuitboard.json
new file mode 100644
index 0000000000..907b0d4052
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/printedcircuitboard.json
@@ -0,0 +1,9 @@
+{
+ "type": "minecraft:smelting",
+ "ingredient": {
+ "tag": "opencomputers:materialcircuitboardraw"
+ },
+ "result": "opencomputers:printedcircuitboard",
+ "experience": 0.1,
+ "cookingtime": 200
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/printer.json b/src/main/resources/data/opencomputers/recipes/printer.json
new file mode 100644
index 0000000000..8b689d686a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/printer.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ihi",
+ "pCp",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "h": {
+ "item": "minecraft:hopper"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:printer"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/rack.json b/src/main/resources/data/opencomputers/recipes/rack.json
new file mode 100644
index 0000000000..76759006ee
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/rack.json
@@ -0,0 +1,34 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "dWd",
+ "bcb",
+ "RPD"
+ ],
+ "key": {
+ "d": {
+ "tag": "forge:gems/diamond"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "b": {
+ "item": "minecraft:iron_bars"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "W": {
+ "tag": "opencomputers:wlancard2"
+ },
+ "R": {
+ "tag": "opencomputers:relay"
+ },
+ "D": {
+ "tag": "opencomputers:powerdistributor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:rack"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/raid.json b/src/main/resources/data/opencomputers/recipes/raid.json
new file mode 100644
index 0000000000..41cf6e7da7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/raid.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iPi",
+ "MDM",
+ "iCi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "M": {
+ "tag": "opencomputers:ram1"
+ },
+ "P": {
+ "tag": "opencomputers:cpu3"
+ },
+ "D": {
+ "tag": "opencomputers:diskdrive"
+ }
+ },
+ "result": {
+ "item": "opencomputers:raid"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/ram1.json b/src/main/resources/data/opencomputers/recipes/ram1.json
new file mode 100644
index 0000000000..86e31a3858
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/ram1.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cic",
+ " P "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "c": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:ram1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/ram2.json b/src/main/resources/data/opencomputers/recipes/ram2.json
new file mode 100644
index 0000000000..28bea65d17
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/ram2.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cCc",
+ " P "
+ ],
+ "key": {
+ "c": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:ram2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/ram3.json b/src/main/resources/data/opencomputers/recipes/ram3.json
new file mode 100644
index 0000000000..b13d00989b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/ram3.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cic",
+ " P "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "c": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:ram3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/ram4.json b/src/main/resources/data/opencomputers/recipes/ram4.json
new file mode 100644
index 0000000000..b7a25de2d3
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/ram4.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cCc",
+ " P "
+ ],
+ "key": {
+ "c": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:ram4"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/ram5.json b/src/main/resources/data/opencomputers/recipes/ram5.json
new file mode 100644
index 0000000000..11447a4a1e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/ram5.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cic",
+ " P "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "c": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:ram5"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/ram6.json b/src/main/resources/data/opencomputers/recipes/ram6.json
new file mode 100644
index 0000000000..dae767c322
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/ram6.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "CCC",
+ "cPc"
+ ],
+ "key": {
+ "c": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:ram6"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/rawcircuitboard.json b/src/main/resources/data/opencomputers/recipes/rawcircuitboard.json
new file mode 100644
index 0000000000..0d4c7e7ac5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/rawcircuitboard.json
@@ -0,0 +1,18 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "forge:ingots/gold"
+ },
+ {
+ "item": "minecraft:clay"
+ },
+ {
+ "tag": "forge:dyes/green"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:rawcircuitboard",
+ "count": 8
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/recrafting/drone.json b/src/main/resources/data/opencomputers/recipes/recrafting/drone.json
new file mode 100644
index 0000000000..a604c4e431
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/recrafting/drone.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:drone"
+ },
+ {
+ "item": "opencomputers:eeprom"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:drone"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/recrafting/linkedcard.json b/src/main/resources/data/opencomputers/recipes/recrafting/linkedcard.json
new file mode 100644
index 0000000000..b30816050d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/recrafting/linkedcard.json
@@ -0,0 +1,15 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:linkedcard"
+ },
+ {
+ "item": "opencomputers:linkedcard"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:linkedcard",
+ "count": 2
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/recrafting/microcontroller.json b/src/main/resources/data/opencomputers/recipes/recrafting/microcontroller.json
new file mode 100644
index 0000000000..bd0127450a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/recrafting/microcontroller.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:microcontroller"
+ },
+ {
+ "item": "opencomputers:eeprom"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:microcontroller"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/recrafting/navigationupgrade.json b/src/main/resources/data/opencomputers/recipes/recrafting/navigationupgrade.json
new file mode 100644
index 0000000000..d7cedbd10e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/recrafting/navigationupgrade.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:navigationupgrade"
+ },
+ {
+ "item": "minecraft:filled_map"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:navigationupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/recrafting/robot.json b/src/main/resources/data/opencomputers/recipes/recrafting/robot.json
new file mode 100644
index 0000000000..57d4928905
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/recrafting/robot.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:robot"
+ },
+ {
+ "item": "opencomputers:eeprom"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:robot"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/recrafting/tablet.json b/src/main/resources/data/opencomputers/recipes/recrafting/tablet.json
new file mode 100644
index 0000000000..e871988d2c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/recrafting/tablet.json
@@ -0,0 +1,14 @@
+{
+ "type": "opencomputers:crafting_shapeless_extended",
+ "ingredients": [
+ {
+ "item": "opencomputers:tablet"
+ },
+ {
+ "item": "opencomputers:eeprom"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:tablet"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/redstone.json b/src/main/resources/data/opencomputers/recipes/redstone.json
new file mode 100644
index 0000000000..9ef9f2986d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/redstone.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "rRr",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "r": {
+ "tag": "forge:storage_blocks/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "R": {
+ "tag": "opencomputers:redstonecard1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:redstone"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/redstonecard1.json b/src/main/resources/data/opencomputers/recipes/redstonecard1.json
new file mode 100644
index 0000000000..a22d86acd0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/redstonecard1.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "rC",
+ " B"
+ ],
+ "key": {
+ "r": {
+ "item": "minecraft:redstone_torch"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:redstonecard1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/redstonecard2.json b/src/main/resources/data/opencomputers/recipes/redstonecard2.json
new file mode 100644
index 0000000000..ac2e427a62
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/redstonecard2.json
@@ -0,0 +1,24 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "rCe",
+ " B "
+ ],
+ "key": {
+ "e": {
+ "tag": "forge:ender_pearls"
+ },
+ "r": {
+ "tag": "forge:storage_blocks/redstone"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:redstonecard2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/relay.json b/src/main/resources/data/opencomputers/recipes/relay.json
new file mode 100644
index 0000000000..566e5e56e3
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/relay.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ici",
+ "cLc",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "c": {
+ "tag": "opencomputers:cable"
+ },
+ "L": {
+ "tag": "opencomputers:lancard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:relay"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/screen1.json b/src/main/resources/data/opencomputers/recipes/screen1.json
new file mode 100644
index 0000000000..7157d7ce7e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/screen1.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iri",
+ "rCG",
+ "iri"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "G": {
+ "tag": "forge:glass"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:screen1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/screen2.json b/src/main/resources/data/opencomputers/recipes/screen2.json
new file mode 100644
index 0000000000..061b2621b2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/screen2.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gcg",
+ "pCG",
+ "gyg"
+ ],
+ "key": {
+ "c": {
+ "tag": "forge:dyes/red"
+ },
+ "p": {
+ "tag": "forge:dyes/green"
+ },
+ "y": {
+ "tag": "forge:dyes/blue"
+ },
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "G": {
+ "tag": "forge:glass"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:screen2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/screen3.json b/src/main/resources/data/opencomputers/recipes/screen3.json
new file mode 100644
index 0000000000..285bc5058a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/screen3.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ogo",
+ "gCG",
+ "ogo"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:dusts/glowstone"
+ },
+ "G": {
+ "tag": "forge:glass"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ }
+ },
+ "result": {
+ "item": "opencomputers:screen3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/server1.json b/src/main/resources/data/opencomputers/recipes/server1.json
new file mode 100644
index 0000000000..cc5f366766
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/server1.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iRi",
+ "CBC",
+ "oPo"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus1"
+ },
+ "R": {
+ "tag": "opencomputers:ram2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:server1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/server2.json b/src/main/resources/data/opencomputers/recipes/server2.json
new file mode 100644
index 0000000000..6e19104647
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/server2.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gRg",
+ "CBC",
+ "oPo"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus2"
+ },
+ "R": {
+ "tag": "opencomputers:ram4"
+ }
+ },
+ "result": {
+ "item": "opencomputers:server2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/server3.json b/src/main/resources/data/opencomputers/recipes/server3.json
new file mode 100644
index 0000000000..3c8651e26e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/server3.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "dRd",
+ "CBC",
+ "oPo"
+ ],
+ "key": {
+ "d": {
+ "tag": "forge:gems/diamond"
+ },
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus3"
+ },
+ "R": {
+ "tag": "opencomputers:ram6"
+ }
+ },
+ "result": {
+ "item": "opencomputers:server3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/signupgrade.json b/src/main/resources/data/opencomputers/recipes/signupgrade.json
new file mode 100644
index 0000000000..a9ff81200e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/signupgrade.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ibi",
+ "CsC",
+ "ipi"
+ ],
+ "key": {
+ "s": {
+ "tag": "forge:rods/wooden"
+ },
+ "b": {
+ "tag": "forge:dyes/black"
+ },
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "p": {
+ "item": "minecraft:sticky_piston"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:signupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/solargeneratorupgrade.json b/src/main/resources/data/opencomputers/recipes/solargeneratorupgrade.json
new file mode 100644
index 0000000000..92f5643f16
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/solargeneratorupgrade.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "ggg",
+ "ClC",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:glass"
+ },
+ "l": {
+ "tag": "forge:storage_blocks/lapis"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:solargeneratorupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/stickypistonupgrade.json b/src/main/resources/data/opencomputers/recipes/stickypistonupgrade.json
new file mode 100644
index 0000000000..0316de4caa
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/stickypistonupgrade.json
@@ -0,0 +1,14 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "tag": "opencomputers:pistonupgrade"
+ },
+ {
+ "tag": "forge:slimeballs"
+ }
+ ],
+ "result": {
+ "item": "opencomputers:stickypistonupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/tabletcase1.json b/src/main/resources/data/opencomputers/recipes/tabletcase1.json
new file mode 100644
index 0000000000..df3725413c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/tabletcase1.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gbg",
+ "BMC",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "b": {
+ "item": "minecraft:stone_button"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus1"
+ },
+ "M": {
+ "tag": "opencomputers:screen2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:tabletcase1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/tabletcase2.json b/src/main/resources/data/opencomputers/recipes/tabletcase2.json
new file mode 100644
index 0000000000..7c8aec84d6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/tabletcase2.json
@@ -0,0 +1,34 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "cbg",
+ "BMC",
+ "cPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "b": {
+ "item": "minecraft:stone_button"
+ },
+ "c": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "B": {
+ "tag": "opencomputers:componentbus3"
+ },
+ "M": {
+ "tag": "opencomputers:screen2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:tabletcase2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/tankcontrollerupgrade.json b/src/main/resources/data/opencomputers/recipes/tankcontrollerupgrade.json
new file mode 100644
index 0000000000..959ab130e7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/tankcontrollerupgrade.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gbg",
+ "dCp",
+ "gPg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "b": {
+ "item": "minecraft:glass_bottle"
+ },
+ "d": {
+ "item": "minecraft:dispenser"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:tankcontrollerupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/tankupgrade.json b/src/main/resources/data/opencomputers/recipes/tankupgrade.json
new file mode 100644
index 0000000000..d3418ba101
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/tankupgrade.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "wbw",
+ "dcp",
+ "wCw"
+ ],
+ "key": {
+ "w": {
+ "tag": "minecraft:planks"
+ },
+ "c": {
+ "item": "minecraft:cauldron"
+ },
+ "b": {
+ "item": "minecraft:iron_bars"
+ },
+ "d": {
+ "item": "minecraft:dispenser"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ }
+ },
+ "result": {
+ "item": "opencomputers:tankupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/terminal.json b/src/main/resources/data/opencomputers/recipes/terminal.json
new file mode 100644
index 0000000000..da5b905cbf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/terminal.json
@@ -0,0 +1,31 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iSi",
+ "CMR",
+ "iKi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:nuggets/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "M": {
+ "tag": "opencomputers:screen2"
+ },
+ "K": {
+ "tag": "opencomputers:keyboard"
+ },
+ "R": {
+ "tag": "opencomputers:wlancard2"
+ },
+ "S": {
+ "tag": "opencomputers:solargeneratorupgrade"
+ }
+ },
+ "result": {
+ "item": "opencomputers:terminal"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/terminalserver.json b/src/main/resources/data/opencomputers/recipes/terminalserver.json
new file mode 100644
index 0000000000..34c4050148
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/terminalserver.json
@@ -0,0 +1,25 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "oRo",
+ "RCR",
+ "oPo"
+ ],
+ "key": {
+ "o": {
+ "tag": "forge:obsidian"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "R": {
+ "tag": "opencomputers:wlancard2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:terminalserver"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/texturepicker.json b/src/main/resources/data/opencomputers/recipes/texturepicker.json
new file mode 100644
index 0000000000..c8523a4ba0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/texturepicker.json
@@ -0,0 +1,40 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "DRG",
+ "BAP",
+ "YMW"
+ ],
+ "key": {
+ "D": {
+ "tag": "forge:dyes/black"
+ },
+ "R": {
+ "tag": "forge:dyes/red"
+ },
+ "G": {
+ "tag": "forge:dyes/green"
+ },
+ "B": {
+ "tag": "forge:dyes/blue"
+ },
+ "P": {
+ "tag": "forge:dyes/purple"
+ },
+ "Y": {
+ "tag": "forge:dyes/yellow"
+ },
+ "M": {
+ "tag": "forge:dyes/magenta"
+ },
+ "W": {
+ "tag": "forge:dyes/white"
+ },
+ "A": {
+ "tag": "opencomputers:analyzer"
+ }
+ },
+ "result": {
+ "item": "opencomputers:texturepicker"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/tractorbeamupgrade.json b/src/main/resources/data/opencomputers/recipes/tractorbeamupgrade.json
new file mode 100644
index 0000000000..1d541f8e33
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/tractorbeamupgrade.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gpg",
+ "iBi",
+ "gCg"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip3"
+ },
+ "B": {
+ "tag": "opencomputers:capacitor"
+ }
+ },
+ "result": {
+ "item": "opencomputers:tractorbeamupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/tradingupgrade.json b/src/main/resources/data/opencomputers/recipes/tradingupgrade.json
new file mode 100644
index 0000000000..741371de22
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/tradingupgrade.json
@@ -0,0 +1,34 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gcg",
+ "eCe",
+ "dPp"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "e": {
+ "tag": "forge:gems/emerald"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "d": {
+ "item": "minecraft:dropper"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:tradingupgrade"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/transistor.json b/src/main/resources/data/opencomputers/recipes/transistor.json
new file mode 100644
index 0000000000..92ab21d0c6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/transistor.json
@@ -0,0 +1,26 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iii",
+ "gpg",
+ " r "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "g": {
+ "tag": "forge:nuggets/gold"
+ },
+ "r": {
+ "tag": "forge:dusts/redstone"
+ },
+ "p": {
+ "item": "minecraft:paper"
+ }
+ },
+ "result": {
+ "item": "opencomputers:transistor",
+ "count": 8
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/transposer.json b/src/main/resources/data/opencomputers/recipes/transposer.json
new file mode 100644
index 0000000000..0bd83c4c43
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/transposer.json
@@ -0,0 +1,29 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iIi",
+ "hbh",
+ "iTi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "b": {
+ "item": "minecraft:bucket"
+ },
+ "h": {
+ "item": "minecraft:hopper"
+ },
+ "I": {
+ "tag": "opencomputers:inventorycontrollerupgrade"
+ },
+ "T": {
+ "tag": "opencomputers:tankcontrollerupgrade"
+ }
+ },
+ "result": {
+ "item": "opencomputers:transposer",
+ "count": 4
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/upgradecontainer1.json b/src/main/resources/data/opencomputers/recipes/upgradecontainer1.json
new file mode 100644
index 0000000000..e6bc47e0f1
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/upgradecontainer1.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "pc ",
+ "iBi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:upgradecontainer1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/upgradecontainer2.json b/src/main/resources/data/opencomputers/recipes/upgradecontainer2.json
new file mode 100644
index 0000000000..c097e3fcb5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/upgradecontainer2.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "pc ",
+ "iBi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:upgradecontainer2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/upgradecontainer3.json b/src/main/resources/data/opencomputers/recipes/upgradecontainer3.json
new file mode 100644
index 0000000000..47c980d932
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/upgradecontainer3.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "gCg",
+ "pc ",
+ "gBg"
+ ],
+ "key": {
+ "g": {
+ "tag": "forge:ingots/gold"
+ },
+ "c": {
+ "tag": "forge:chests"
+ },
+ "p": {
+ "tag": "forge:pistons"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ }
+ },
+ "result": {
+ "item": "opencomputers:upgradecontainer3"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/waypoint.json b/src/main/resources/data/opencomputers/recipes/waypoint.json
new file mode 100644
index 0000000000..a8998b1a69
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/waypoint.json
@@ -0,0 +1,28 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "iCi",
+ "TIT",
+ "iPi"
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "T": {
+ "tag": "opencomputers:materialtransistor"
+ },
+ "P": {
+ "tag": "opencomputers:materialcircuitboardprinted"
+ },
+ "I": {
+ "tag": "opencomputers:materialinterweb"
+ }
+ },
+ "result": {
+ "item": "opencomputers:waypoint"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/wlancard1.json b/src/main/resources/data/opencomputers/recipes/wlancard1.json
new file mode 100644
index 0000000000..0d728e324f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/wlancard1.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "rCr",
+ " B "
+ ],
+ "key": {
+ "r": {
+ "item": "minecraft:redstone_torch"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip1"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:wlancard1"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/wlancard2.json b/src/main/resources/data/opencomputers/recipes/wlancard2.json
new file mode 100644
index 0000000000..42e2c20ed6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/wlancard2.json
@@ -0,0 +1,21 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "eC",
+ " B"
+ ],
+ "key": {
+ "e": {
+ "tag": "forge:ender_pearls"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ },
+ "B": {
+ "tag": "opencomputers:materialcard"
+ }
+ },
+ "result": {
+ "item": "opencomputers:wlancard2"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/recipes/wrench.json b/src/main/resources/data/opencomputers/recipes/wrench.json
new file mode 100644
index 0000000000..1d1ee14115
--- /dev/null
+++ b/src/main/resources/data/opencomputers/recipes/wrench.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "i i",
+ " C ",
+ " i "
+ ],
+ "key": {
+ "i": {
+ "tag": "forge:ingots/iron"
+ },
+ "C": {
+ "tag": "opencomputers:circuitchip2"
+ }
+ },
+ "result": {
+ "item": "opencomputers:wrench"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/adapter.json b/src/main/resources/data/opencomputers/tags/blocks/adapter.json
new file mode 100644
index 0000000000..40ea055820
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/adapter.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:adapter"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/assembler.json b/src/main/resources/data/opencomputers/tags/blocks/assembler.json
new file mode 100644
index 0000000000..ce253c7d63
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/assembler.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:assembler"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/cable.json b/src/main/resources/data/opencomputers/tags/blocks/cable.json
new file mode 100644
index 0000000000..ddf88f324c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/cable.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cable"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/capacitor.json b/src/main/resources/data/opencomputers/tags/blocks/capacitor.json
new file mode 100644
index 0000000000..d5c5604646
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/capacitor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:capacitor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/carpetedcapacitor.json b/src/main/resources/data/opencomputers/tags/blocks/carpetedcapacitor.json
new file mode 100644
index 0000000000..3b0f159796
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/carpetedcapacitor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:carpetedcapacitor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/case1.json b/src/main/resources/data/opencomputers/tags/blocks/case1.json
new file mode 100644
index 0000000000..36fe770a86
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/case1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:case1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/case2.json b/src/main/resources/data/opencomputers/tags/blocks/case2.json
new file mode 100644
index 0000000000..731dfce4f6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/case2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:case2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/case3.json b/src/main/resources/data/opencomputers/tags/blocks/case3.json
new file mode 100644
index 0000000000..81cf6d2e6f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/case3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:case3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/chameliumblock.json b/src/main/resources/data/opencomputers/tags/blocks/chameliumblock.json
new file mode 100644
index 0000000000..96191a5dfa
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/chameliumblock.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chameliumblock"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/charger.json b/src/main/resources/data/opencomputers/tags/blocks/charger.json
new file mode 100644
index 0000000000..1d72aca9d4
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/charger.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:charger"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/disassembler.json b/src/main/resources/data/opencomputers/tags/blocks/disassembler.json
new file mode 100644
index 0000000000..b8edc0505a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/disassembler.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:disassembler"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/diskdrive.json b/src/main/resources/data/opencomputers/tags/blocks/diskdrive.json
new file mode 100644
index 0000000000..c672b364d5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/diskdrive.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:diskdrive"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/geolyzer.json b/src/main/resources/data/opencomputers/tags/blocks/geolyzer.json
new file mode 100644
index 0000000000..b5dee04f2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/geolyzer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:geolyzer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/hologram1.json b/src/main/resources/data/opencomputers/tags/blocks/hologram1.json
new file mode 100644
index 0000000000..f86e9ea22f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/hologram1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hologram1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/hologram2.json b/src/main/resources/data/opencomputers/tags/blocks/hologram2.json
new file mode 100644
index 0000000000..8cd7c2c5fa
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/hologram2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hologram2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/keyboard.json b/src/main/resources/data/opencomputers/tags/blocks/keyboard.json
new file mode 100644
index 0000000000..46c3a95875
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/keyboard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:keyboard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/motionsensor.json b/src/main/resources/data/opencomputers/tags/blocks/motionsensor.json
new file mode 100644
index 0000000000..5bedd10526
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/motionsensor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:motionsensor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/netsplitter.json b/src/main/resources/data/opencomputers/tags/blocks/netsplitter.json
new file mode 100644
index 0000000000..1a34747e99
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/netsplitter.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:netsplitter"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/powerconverter.json b/src/main/resources/data/opencomputers/tags/blocks/powerconverter.json
new file mode 100644
index 0000000000..f1c25c0541
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/powerconverter.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:powerconverter"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/powerdistributor.json b/src/main/resources/data/opencomputers/tags/blocks/powerdistributor.json
new file mode 100644
index 0000000000..327ec64106
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/powerdistributor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:powerdistributor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/printer.json b/src/main/resources/data/opencomputers/tags/blocks/printer.json
new file mode 100644
index 0000000000..e519cbe8b0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/printer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:printer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/rack.json b/src/main/resources/data/opencomputers/tags/blocks/rack.json
new file mode 100644
index 0000000000..5c21c51ef2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/rack.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:rack"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/raid.json b/src/main/resources/data/opencomputers/tags/blocks/raid.json
new file mode 100644
index 0000000000..94d790f968
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/raid.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:raid"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/redstone.json b/src/main/resources/data/opencomputers/tags/blocks/redstone.json
new file mode 100644
index 0000000000..b02efc6970
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/redstone.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:redstone"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/relay.json b/src/main/resources/data/opencomputers/tags/blocks/relay.json
new file mode 100644
index 0000000000..8777de68ce
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/relay.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:relay"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/screen1.json b/src/main/resources/data/opencomputers/tags/blocks/screen1.json
new file mode 100644
index 0000000000..3715f2df5a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/screen1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:screen1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/screen2.json b/src/main/resources/data/opencomputers/tags/blocks/screen2.json
new file mode 100644
index 0000000000..43611f12cc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/screen2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:screen2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/screen3.json b/src/main/resources/data/opencomputers/tags/blocks/screen3.json
new file mode 100644
index 0000000000..7747d82efb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/screen3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:screen3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/transposer.json b/src/main/resources/data/opencomputers/tags/blocks/transposer.json
new file mode 100644
index 0000000000..b27df92e33
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/transposer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:transposer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/blocks/waypoint.json b/src/main/resources/data/opencomputers/tags/blocks/waypoint.json
new file mode 100644
index 0000000000..9096c6243d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/blocks/waypoint.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:waypoint"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/adapter.json b/src/main/resources/data/opencomputers/tags/items/adapter.json
new file mode 100644
index 0000000000..40ea055820
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/adapter.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:adapter"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/analyzer.json b/src/main/resources/data/opencomputers/tags/items/analyzer.json
new file mode 100644
index 0000000000..af2238c3ec
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/analyzer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:analyzer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/angelupgrade.json b/src/main/resources/data/opencomputers/tags/items/angelupgrade.json
new file mode 100644
index 0000000000..e8875be1e9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/angelupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:angelupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/apu1.json b/src/main/resources/data/opencomputers/tags/items/apu1.json
new file mode 100644
index 0000000000..f358b9b068
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/apu1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:apu1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/apu2.json b/src/main/resources/data/opencomputers/tags/items/apu2.json
new file mode 100644
index 0000000000..5b2bd1e547
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/apu2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:apu2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/assembler.json b/src/main/resources/data/opencomputers/tags/items/assembler.json
new file mode 100644
index 0000000000..ce253c7d63
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/assembler.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:assembler"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/batteryupgrade1.json b/src/main/resources/data/opencomputers/tags/items/batteryupgrade1.json
new file mode 100644
index 0000000000..dd85c6333f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/batteryupgrade1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:batteryupgrade1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/batteryupgrade2.json b/src/main/resources/data/opencomputers/tags/items/batteryupgrade2.json
new file mode 100644
index 0000000000..68f6cf92e7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/batteryupgrade2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:batteryupgrade2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/batteryupgrade3.json b/src/main/resources/data/opencomputers/tags/items/batteryupgrade3.json
new file mode 100644
index 0000000000..3ede5aa156
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/batteryupgrade3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:batteryupgrade3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cable.json b/src/main/resources/data/opencomputers/tags/items/cable.json
new file mode 100644
index 0000000000..ddf88f324c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cable.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cable"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/capacitor.json b/src/main/resources/data/opencomputers/tags/items/capacitor.json
new file mode 100644
index 0000000000..d5c5604646
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/capacitor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:capacitor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cardcontainer1.json b/src/main/resources/data/opencomputers/tags/items/cardcontainer1.json
new file mode 100644
index 0000000000..66725d2e88
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cardcontainer1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cardcontainer1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cardcontainer2.json b/src/main/resources/data/opencomputers/tags/items/cardcontainer2.json
new file mode 100644
index 0000000000..ee5802a3fe
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cardcontainer2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cardcontainer2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cardcontainer3.json b/src/main/resources/data/opencomputers/tags/items/cardcontainer3.json
new file mode 100644
index 0000000000..5448319176
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cardcontainer3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cardcontainer3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/carpetedcapacitor.json b/src/main/resources/data/opencomputers/tags/items/carpetedcapacitor.json
new file mode 100644
index 0000000000..3b0f159796
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/carpetedcapacitor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:carpetedcapacitor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/case1.json b/src/main/resources/data/opencomputers/tags/items/case1.json
new file mode 100644
index 0000000000..36fe770a86
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/case1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:case1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/case2.json b/src/main/resources/data/opencomputers/tags/items/case2.json
new file mode 100644
index 0000000000..731dfce4f6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/case2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:case2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/case3.json b/src/main/resources/data/opencomputers/tags/items/case3.json
new file mode 100644
index 0000000000..81cf6d2e6f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/case3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:case3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/chamelium.json b/src/main/resources/data/opencomputers/tags/items/chamelium.json
new file mode 100644
index 0000000000..c01615e648
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/chamelium.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chamelium"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/chameliumblock.json b/src/main/resources/data/opencomputers/tags/items/chameliumblock.json
new file mode 100644
index 0000000000..96191a5dfa
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/chameliumblock.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chameliumblock"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/charger.json b/src/main/resources/data/opencomputers/tags/items/charger.json
new file mode 100644
index 0000000000..1d72aca9d4
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/charger.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:charger"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/chipdiamond.json b/src/main/resources/data/opencomputers/tags/items/chipdiamond.json
new file mode 100644
index 0000000000..87db4e1169
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/chipdiamond.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chipdiamond"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/chunkloaderupgrade.json b/src/main/resources/data/opencomputers/tags/items/chunkloaderupgrade.json
new file mode 100644
index 0000000000..d430fc32dd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/chunkloaderupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chunkloaderupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/circuitchip1.json b/src/main/resources/data/opencomputers/tags/items/circuitchip1.json
new file mode 100644
index 0000000000..9dccfbae3f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/circuitchip1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chip1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/circuitchip2.json b/src/main/resources/data/opencomputers/tags/items/circuitchip2.json
new file mode 100644
index 0000000000..c897187abb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/circuitchip2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chip2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/circuitchip3.json b/src/main/resources/data/opencomputers/tags/items/circuitchip3.json
new file mode 100644
index 0000000000..f5ba9efd4a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/circuitchip3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:chip3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/componentbus1.json b/src/main/resources/data/opencomputers/tags/items/componentbus1.json
new file mode 100644
index 0000000000..7f2ca6f071
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/componentbus1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:componentbus1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/componentbus2.json b/src/main/resources/data/opencomputers/tags/items/componentbus2.json
new file mode 100644
index 0000000000..90a40eafa3
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/componentbus2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:componentbus2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/componentbus3.json b/src/main/resources/data/opencomputers/tags/items/componentbus3.json
new file mode 100644
index 0000000000..098b9f43f1
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/componentbus3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:componentbus3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cpu1.json b/src/main/resources/data/opencomputers/tags/items/cpu1.json
new file mode 100644
index 0000000000..a05cbf708f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cpu1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cpu1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cpu2.json b/src/main/resources/data/opencomputers/tags/items/cpu2.json
new file mode 100644
index 0000000000..3d4e829a36
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cpu2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cpu2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/cpu3.json b/src/main/resources/data/opencomputers/tags/items/cpu3.json
new file mode 100644
index 0000000000..5205e031a2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/cpu3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cpu3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/craftingupgrade.json b/src/main/resources/data/opencomputers/tags/items/craftingupgrade.json
new file mode 100644
index 0000000000..d830ebe4f9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/craftingupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:craftingupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/databaseupgrade1.json b/src/main/resources/data/opencomputers/tags/items/databaseupgrade1.json
new file mode 100644
index 0000000000..be39cac481
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/databaseupgrade1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:databaseupgrade1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/databaseupgrade2.json b/src/main/resources/data/opencomputers/tags/items/databaseupgrade2.json
new file mode 100644
index 0000000000..96e6e155bb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/databaseupgrade2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:databaseupgrade2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/databaseupgrade3.json b/src/main/resources/data/opencomputers/tags/items/databaseupgrade3.json
new file mode 100644
index 0000000000..b58c34e9d2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/databaseupgrade3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:databaseupgrade3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/datacard1.json b/src/main/resources/data/opencomputers/tags/items/datacard1.json
new file mode 100644
index 0000000000..8eab0f3c6f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/datacard1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:datacard1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/datacard2.json b/src/main/resources/data/opencomputers/tags/items/datacard2.json
new file mode 100644
index 0000000000..d654568b40
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/datacard2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:datacard2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/datacard3.json b/src/main/resources/data/opencomputers/tags/items/datacard3.json
new file mode 100644
index 0000000000..7d458b23c6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/datacard3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:datacard3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/disassembler.json b/src/main/resources/data/opencomputers/tags/items/disassembler.json
new file mode 100644
index 0000000000..b8edc0505a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/disassembler.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:disassembler"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/diskdrive.json b/src/main/resources/data/opencomputers/tags/items/diskdrive.json
new file mode 100644
index 0000000000..c672b364d5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/diskdrive.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:diskdrive"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/diskdrivemountable.json b/src/main/resources/data/opencomputers/tags/items/diskdrivemountable.json
new file mode 100644
index 0000000000..8fff553ef6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/diskdrivemountable.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:diskdrivemountable"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/dronecase1.json b/src/main/resources/data/opencomputers/tags/items/dronecase1.json
new file mode 100644
index 0000000000..7c190a7b5d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/dronecase1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:dronecase1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/dronecase2.json b/src/main/resources/data/opencomputers/tags/items/dronecase2.json
new file mode 100644
index 0000000000..aa73252c2e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/dronecase2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:dronecase2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/eeprom.json b/src/main/resources/data/opencomputers/tags/items/eeprom.json
new file mode 100644
index 0000000000..047c279d2b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/eeprom.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:eeprom"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/experienceupgrade.json b/src/main/resources/data/opencomputers/tags/items/experienceupgrade.json
new file mode 100644
index 0000000000..5a1b53a755
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/experienceupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:experienceupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/floppy.json b/src/main/resources/data/opencomputers/tags/items/floppy.json
new file mode 100644
index 0000000000..b8a10369a6
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/floppy.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:floppy"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/generatorupgrade.json b/src/main/resources/data/opencomputers/tags/items/generatorupgrade.json
new file mode 100644
index 0000000000..97bb3d82dd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/generatorupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:generatorupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/geolyzer.json b/src/main/resources/data/opencomputers/tags/items/geolyzer.json
new file mode 100644
index 0000000000..b5dee04f2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/geolyzer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:geolyzer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/graphicscard1.json b/src/main/resources/data/opencomputers/tags/items/graphicscard1.json
new file mode 100644
index 0000000000..26d1c3e174
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/graphicscard1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:graphicscard1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/graphicscard2.json b/src/main/resources/data/opencomputers/tags/items/graphicscard2.json
new file mode 100644
index 0000000000..b5ea28761a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/graphicscard2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:graphicscard2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/graphicscard3.json b/src/main/resources/data/opencomputers/tags/items/graphicscard3.json
new file mode 100644
index 0000000000..30137a5fd7
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/graphicscard3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:graphicscard3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hdd1.json b/src/main/resources/data/opencomputers/tags/items/hdd1.json
new file mode 100644
index 0000000000..d1ecab3167
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hdd1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hdd1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hdd2.json b/src/main/resources/data/opencomputers/tags/items/hdd2.json
new file mode 100644
index 0000000000..817933c135
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hdd2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hdd2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hdd3.json b/src/main/resources/data/opencomputers/tags/items/hdd3.json
new file mode 100644
index 0000000000..5330fcb450
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hdd3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hdd3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hologram1.json b/src/main/resources/data/opencomputers/tags/items/hologram1.json
new file mode 100644
index 0000000000..f86e9ea22f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hologram1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hologram1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hologram2.json b/src/main/resources/data/opencomputers/tags/items/hologram2.json
new file mode 100644
index 0000000000..8cd7c2c5fa
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hologram2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hologram2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hoverboots.json b/src/main/resources/data/opencomputers/tags/items/hoverboots.json
new file mode 100644
index 0000000000..838b71f60c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hoverboots.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hoverboots"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hoverupgrade1.json b/src/main/resources/data/opencomputers/tags/items/hoverupgrade1.json
new file mode 100644
index 0000000000..8473c87e8f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hoverupgrade1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hoverupgrade1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/hoverupgrade2.json b/src/main/resources/data/opencomputers/tags/items/hoverupgrade2.json
new file mode 100644
index 0000000000..c801020560
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/hoverupgrade2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:hoverupgrade2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/inkcartridge.json b/src/main/resources/data/opencomputers/tags/items/inkcartridge.json
new file mode 100644
index 0000000000..9d3dd3a212
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/inkcartridge.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:inkcartridge"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/inkcartridgeempty.json b/src/main/resources/data/opencomputers/tags/items/inkcartridgeempty.json
new file mode 100644
index 0000000000..d67e451ba5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/inkcartridgeempty.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:inkcartridgeempty"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/internetcard.json b/src/main/resources/data/opencomputers/tags/items/internetcard.json
new file mode 100644
index 0000000000..29a889c3f3
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/internetcard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:internetcard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/inventorycontrollerupgrade.json b/src/main/resources/data/opencomputers/tags/items/inventorycontrollerupgrade.json
new file mode 100644
index 0000000000..7f9fd69e43
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/inventorycontrollerupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:inventorycontrollerupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/inventoryupgrade.json b/src/main/resources/data/opencomputers/tags/items/inventoryupgrade.json
new file mode 100644
index 0000000000..b9fdb194fb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/inventoryupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:inventoryupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/keyboard.json b/src/main/resources/data/opencomputers/tags/items/keyboard.json
new file mode 100644
index 0000000000..46c3a95875
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/keyboard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:keyboard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/lancard.json b/src/main/resources/data/opencomputers/tags/items/lancard.json
new file mode 100644
index 0000000000..9562ae20d9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/lancard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:lancard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/leashupgrade.json b/src/main/resources/data/opencomputers/tags/items/leashupgrade.json
new file mode 100644
index 0000000000..a83ef51852
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/leashupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:leashupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/linkedcard.json b/src/main/resources/data/opencomputers/tags/items/linkedcard.json
new file mode 100644
index 0000000000..1066cce0d2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/linkedcard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:linkedcard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/manual.json b/src/main/resources/data/opencomputers/tags/items/manual.json
new file mode 100644
index 0000000000..d9b481c608
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/manual.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:manual"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialacid.json b/src/main/resources/data/opencomputers/tags/items/materialacid.json
new file mode 100644
index 0000000000..e8ccf9c9fd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialacid.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:acid"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialalu.json b/src/main/resources/data/opencomputers/tags/items/materialalu.json
new file mode 100644
index 0000000000..5685dd87f8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialalu.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:alu"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialarrowkey.json b/src/main/resources/data/opencomputers/tags/items/materialarrowkey.json
new file mode 100644
index 0000000000..3f5f54fbed
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialarrowkey.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:arrowkeys"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialbuttongroup.json b/src/main/resources/data/opencomputers/tags/items/materialbuttongroup.json
new file mode 100644
index 0000000000..e94376c866
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialbuttongroup.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:buttongroup"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialcard.json b/src/main/resources/data/opencomputers/tags/items/materialcard.json
new file mode 100644
index 0000000000..d3ebfaeb8a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialcard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:card"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialcircuitboard.json b/src/main/resources/data/opencomputers/tags/items/materialcircuitboard.json
new file mode 100644
index 0000000000..88fb275eaa
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialcircuitboard.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:circuitboard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialcircuitboardprinted.json b/src/main/resources/data/opencomputers/tags/items/materialcircuitboardprinted.json
new file mode 100644
index 0000000000..4c9fe89560
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialcircuitboardprinted.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:printedcircuitboard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialcircuitboardraw.json b/src/main/resources/data/opencomputers/tags/items/materialcircuitboardraw.json
new file mode 100644
index 0000000000..f14a4adfce
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialcircuitboardraw.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:rawcircuitboard"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialcu.json b/src/main/resources/data/opencomputers/tags/items/materialcu.json
new file mode 100644
index 0000000000..91d0fbdca8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialcu.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cu"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialcuttingwire.json b/src/main/resources/data/opencomputers/tags/items/materialcuttingwire.json
new file mode 100644
index 0000000000..4eb1e57db2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialcuttingwire.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:cuttingwire"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialdisk.json b/src/main/resources/data/opencomputers/tags/items/materialdisk.json
new file mode 100644
index 0000000000..3e078d2187
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialdisk.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:disk"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialinterweb.json b/src/main/resources/data/opencomputers/tags/items/materialinterweb.json
new file mode 100644
index 0000000000..fc870e7668
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialinterweb.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:interweb"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialnumpad.json b/src/main/resources/data/opencomputers/tags/items/materialnumpad.json
new file mode 100644
index 0000000000..086fe84d12
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialnumpad.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:numpad"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/materialtransistor.json b/src/main/resources/data/opencomputers/tags/items/materialtransistor.json
new file mode 100644
index 0000000000..7c9a852165
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/materialtransistor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:transistor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/mfu.json b/src/main/resources/data/opencomputers/tags/items/mfu.json
new file mode 100644
index 0000000000..b50de136d8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/mfu.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:mfu"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/microcontrollercase1.json b/src/main/resources/data/opencomputers/tags/items/microcontrollercase1.json
new file mode 100644
index 0000000000..43f32db8c9
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/microcontrollercase1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:microcontrollercase1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/microcontrollercase2.json b/src/main/resources/data/opencomputers/tags/items/microcontrollercase2.json
new file mode 100644
index 0000000000..b153013c2c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/microcontrollercase2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:microcontrollercase2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/motionsensor.json b/src/main/resources/data/opencomputers/tags/items/motionsensor.json
new file mode 100644
index 0000000000..5bedd10526
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/motionsensor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:motionsensor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/nanomachines.json b/src/main/resources/data/opencomputers/tags/items/nanomachines.json
new file mode 100644
index 0000000000..a332667aa0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/nanomachines.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:nanomachines"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/navigationupgrade.json b/src/main/resources/data/opencomputers/tags/items/navigationupgrade.json
new file mode 100644
index 0000000000..7ac0d12787
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/navigationupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:navigationupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/netsplitter.json b/src/main/resources/data/opencomputers/tags/items/netsplitter.json
new file mode 100644
index 0000000000..1a34747e99
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/netsplitter.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:netsplitter"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/pistonupgrade.json b/src/main/resources/data/opencomputers/tags/items/pistonupgrade.json
new file mode 100644
index 0000000000..20eda93a1c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/pistonupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:pistonupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/powerconverter.json b/src/main/resources/data/opencomputers/tags/items/powerconverter.json
new file mode 100644
index 0000000000..f1c25c0541
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/powerconverter.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:powerconverter"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/powerdistributor.json b/src/main/resources/data/opencomputers/tags/items/powerdistributor.json
new file mode 100644
index 0000000000..327ec64106
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/powerdistributor.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:powerdistributor"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/printer.json b/src/main/resources/data/opencomputers/tags/items/printer.json
new file mode 100644
index 0000000000..e519cbe8b0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/printer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:printer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/rack.json b/src/main/resources/data/opencomputers/tags/items/rack.json
new file mode 100644
index 0000000000..5c21c51ef2
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/rack.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:rack"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/raid.json b/src/main/resources/data/opencomputers/tags/items/raid.json
new file mode 100644
index 0000000000..94d790f968
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/raid.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:raid"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/ram1.json b/src/main/resources/data/opencomputers/tags/items/ram1.json
new file mode 100644
index 0000000000..a4dcf07983
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/ram1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:ram1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/ram2.json b/src/main/resources/data/opencomputers/tags/items/ram2.json
new file mode 100644
index 0000000000..6c87031c7b
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/ram2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:ram2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/ram3.json b/src/main/resources/data/opencomputers/tags/items/ram3.json
new file mode 100644
index 0000000000..7f610e2893
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/ram3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:ram3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/ram4.json b/src/main/resources/data/opencomputers/tags/items/ram4.json
new file mode 100644
index 0000000000..a51a2f174a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/ram4.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:ram4"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/ram5.json b/src/main/resources/data/opencomputers/tags/items/ram5.json
new file mode 100644
index 0000000000..f9db65e3d0
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/ram5.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:ram5"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/ram6.json b/src/main/resources/data/opencomputers/tags/items/ram6.json
new file mode 100644
index 0000000000..fdc3a46ab4
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/ram6.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:ram6"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/redstone.json b/src/main/resources/data/opencomputers/tags/items/redstone.json
new file mode 100644
index 0000000000..b02efc6970
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/redstone.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:redstone"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/redstonecard1.json b/src/main/resources/data/opencomputers/tags/items/redstonecard1.json
new file mode 100644
index 0000000000..f3b377bdcf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/redstonecard1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:redstonecard1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/redstonecard2.json b/src/main/resources/data/opencomputers/tags/items/redstonecard2.json
new file mode 100644
index 0000000000..99f07d8657
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/redstonecard2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:redstonecard2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/relay.json b/src/main/resources/data/opencomputers/tags/items/relay.json
new file mode 100644
index 0000000000..8777de68ce
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/relay.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:relay"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/screen1.json b/src/main/resources/data/opencomputers/tags/items/screen1.json
new file mode 100644
index 0000000000..3715f2df5a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/screen1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:screen1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/screen2.json b/src/main/resources/data/opencomputers/tags/items/screen2.json
new file mode 100644
index 0000000000..43611f12cc
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/screen2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:screen2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/screen3.json b/src/main/resources/data/opencomputers/tags/items/screen3.json
new file mode 100644
index 0000000000..7747d82efb
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/screen3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:screen3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/server1.json b/src/main/resources/data/opencomputers/tags/items/server1.json
new file mode 100644
index 0000000000..4d02054e2f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/server1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:server1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/server2.json b/src/main/resources/data/opencomputers/tags/items/server2.json
new file mode 100644
index 0000000000..bec50adc68
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/server2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:server2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/server3.json b/src/main/resources/data/opencomputers/tags/items/server3.json
new file mode 100644
index 0000000000..513579991a
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/server3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:server3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/signupgrade.json b/src/main/resources/data/opencomputers/tags/items/signupgrade.json
new file mode 100644
index 0000000000..a23e2aa3dd
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/signupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:signupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/solargeneratorupgrade.json b/src/main/resources/data/opencomputers/tags/items/solargeneratorupgrade.json
new file mode 100644
index 0000000000..10b9e99dca
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/solargeneratorupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:solargeneratorupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/stickypistonupgrade.json b/src/main/resources/data/opencomputers/tags/items/stickypistonupgrade.json
new file mode 100644
index 0000000000..4c5f04cff8
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/stickypistonupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:stickypistonupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/tabletcase1.json b/src/main/resources/data/opencomputers/tags/items/tabletcase1.json
new file mode 100644
index 0000000000..5e42ce3d02
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/tabletcase1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:tabletcase1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/tabletcase2.json b/src/main/resources/data/opencomputers/tags/items/tabletcase2.json
new file mode 100644
index 0000000000..d971384a20
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/tabletcase2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:tabletcase2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/tankcontrollerupgrade.json b/src/main/resources/data/opencomputers/tags/items/tankcontrollerupgrade.json
new file mode 100644
index 0000000000..31fd709c36
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/tankcontrollerupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:tankcontrollerupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/tankupgrade.json b/src/main/resources/data/opencomputers/tags/items/tankupgrade.json
new file mode 100644
index 0000000000..29f0047b03
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/tankupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:tankupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/terminal.json b/src/main/resources/data/opencomputers/tags/items/terminal.json
new file mode 100644
index 0000000000..aa9109ac64
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/terminal.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:terminal"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/terminalserver.json b/src/main/resources/data/opencomputers/tags/items/terminalserver.json
new file mode 100644
index 0000000000..ce1e0bd0cf
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/terminalserver.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:terminalserver"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/texturepicker.json b/src/main/resources/data/opencomputers/tags/items/texturepicker.json
new file mode 100644
index 0000000000..12d8e59604
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/texturepicker.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:texturepicker"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/tractorbeamupgrade.json b/src/main/resources/data/opencomputers/tags/items/tractorbeamupgrade.json
new file mode 100644
index 0000000000..2d1d93a476
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/tractorbeamupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:tractorbeamupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/tradingupgrade.json b/src/main/resources/data/opencomputers/tags/items/tradingupgrade.json
new file mode 100644
index 0000000000..5fc253cc65
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/tradingupgrade.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:tradingupgrade"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/transposer.json b/src/main/resources/data/opencomputers/tags/items/transposer.json
new file mode 100644
index 0000000000..b27df92e33
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/transposer.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:transposer"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/upgradecontainer1.json b/src/main/resources/data/opencomputers/tags/items/upgradecontainer1.json
new file mode 100644
index 0000000000..d4d4f8100c
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/upgradecontainer1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:upgradecontainer1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/upgradecontainer2.json b/src/main/resources/data/opencomputers/tags/items/upgradecontainer2.json
new file mode 100644
index 0000000000..ed7a840a9e
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/upgradecontainer2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:upgradecontainer2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/upgradecontainer3.json b/src/main/resources/data/opencomputers/tags/items/upgradecontainer3.json
new file mode 100644
index 0000000000..50a255cca5
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/upgradecontainer3.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:upgradecontainer3"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/waypoint.json b/src/main/resources/data/opencomputers/tags/items/waypoint.json
new file mode 100644
index 0000000000..9096c6243d
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/waypoint.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:waypoint"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/wlancard1.json b/src/main/resources/data/opencomputers/tags/items/wlancard1.json
new file mode 100644
index 0000000000..50b4f85d5f
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/wlancard1.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:wlancard1"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/wlancard2.json b/src/main/resources/data/opencomputers/tags/items/wlancard2.json
new file mode 100644
index 0000000000..df25029370
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/wlancard2.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:wlancard2"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/data/opencomputers/tags/items/wrench.json b/src/main/resources/data/opencomputers/tags/items/wrench.json
new file mode 100644
index 0000000000..af355bef28
--- /dev/null
+++ b/src/main/resources/data/opencomputers/tags/items/wrench.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "opencomputers:wrench"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
deleted file mode 100644
index 15b6e128f8..0000000000
--- a/src/main/resources/mcmod.info
+++ /dev/null
@@ -1,17 +0,0 @@
-[{
- "modid": "opencomputers",
- "name": "OpenComputers",
- "description": "This mod adds modular computers and robots that can be programmed in Lua.",
- "version": "${version}",
- "mcversion": "${mcversion}",
- "url": "http://oc.cil.li/",
- "authorList": ["Sangar", "Vexatos", "payonel", "magik6k", "Lord Joda", "Github Contributors"],
- "credits" : "Inspired by a couple of other mods, most notably ComputerCraft.",
- "logoFile" : "assets/opencomputers/textures/gui/logo.png",
- "requiredMods": [],
- "dependencies": [
- "JEI@[4.2.7.240,)"
- ],
- "dependants": [],
- "useDependencyInformation": "true"
-}]
diff --git a/src/main/resources/oc_at.cfg b/src/main/resources/oc_at.cfg
deleted file mode 100644
index 1c841fa0fb..0000000000
--- a/src/main/resources/oc_at.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
- # OpenComputers access transformer config
-public net.minecraft.client.gui.inventory.GuiContainer field_146999_f #xSize
-public net.minecraft.client.gui.inventory.GuiContainer field_147000_g #ySize
-public net.minecraft.client.gui.inventory.GuiContainer field_147003_i #guiLeft
-public net.minecraft.client.gui.inventory.GuiContainer field_147009_r #guiTop
-public net.minecraft.block.BlockPistonBase func_176319_a(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;Z)Z # doMove
-public net.minecraft.client.audio.SoundManager field_148620_e #sndSystem
-public net.minecraft.client.audio.SoundManager$SoundSystemStarterThread
-#public net.minecraft.enchantment.Enchantment field_180311_a # enchantmentsList
-public net.minecraft.tileentity.MobSpawnerBaseLogic func_190895_g()Lnet/minecraft/util/ResourceLocation; # getEntityId
-public net.minecraft.entity.Entity func_180432_n(Lnet/minecraft/entity/Entity;)V # copyDataFromOld
diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta
new file mode 100644
index 0000000000..4a3edd6ccb
--- /dev/null
+++ b/src/main/resources/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "description": "OpenComputers resources",
+ "pack_format": 6
+ }
+}
diff --git a/src/main/resources/pack.png b/src/main/resources/pack.png
new file mode 100644
index 0000000000..65bb8c54e4
Binary files /dev/null and b/src/main/resources/pack.png differ
diff --git a/src/main/scala/li/cil/oc/CreativeTab.scala b/src/main/scala/li/cil/oc/CreativeTab.scala
index 1a54db307c..5ed9ef4431 100644
--- a/src/main/scala/li/cil/oc/CreativeTab.scala
+++ b/src/main/scala/li/cil/oc/CreativeTab.scala
@@ -1,11 +1,17 @@
package li.cil.oc
-import net.minecraft.creativetab.CreativeTabs
+import li.cil.oc.common.init.Items
+import net.minecraft.item.ItemGroup
+import net.minecraft.item.ItemStack
+import net.minecraft.util.NonNullList
-object CreativeTab extends CreativeTabs(CreativeTabs.getNextID, OpenComputers.Name) {
+object CreativeTab extends ItemGroup(OpenComputers.Name) {
private lazy val stack = api.Items.get(Constants.BlockName.CaseTier1).createItemStack(1)
- override def getTabIconItem = stack
+ override def makeIcon = stack
- override def getTranslatedTabLabel = getTabLabel
+ override def fillItemList(list: NonNullList[ItemStack]) {
+ super.fillItemList(list)
+ Items.decorateCreativeTab(list)
+ }
}
diff --git a/src/main/scala/li/cil/oc/Localization.scala b/src/main/scala/li/cil/oc/Localization.scala
index d66c0be78a..6d83b8977c 100644
--- a/src/main/scala/li/cil/oc/Localization.scala
+++ b/src/main/scala/li/cil/oc/Localization.scala
@@ -1,62 +1,65 @@
package li.cil.oc
-import li.cil.oc.client.CommandHandler.SetClipboardCommand
-import net.minecraft.util.text.ITextComponent
-import net.minecraft.util.text.TextComponentString
-import net.minecraft.util.text.TextComponentTranslation
+import net.minecraft.util.text._
import net.minecraft.util.text.event.ClickEvent
import net.minecraft.util.text.event.HoverEvent
-import net.minecraft.util.text.translation.I18n
-import net.minecraftforge.fml.common.event.FMLFingerprintViolationEvent
import scala.util.matching.Regex
object Localization {
- private val nl = Regex.quote("[nl]")
-
private def resolveKey(key: String) = if (canLocalize(Settings.namespace + key)) Settings.namespace + key else key
- def canLocalize(key: String): Boolean = I18n.canTranslate(key)
+ def canLocalize(key: String): Boolean = LanguageMap.getInstance.has(key)
- def localizeLater(formatKey: String, values: AnyRef*) = new TextComponentTranslation(resolveKey(formatKey), values: _*)
+ def localizeLater(formatKey: String, values: AnyRef*) = new TranslationTextComponent(resolveKey(formatKey), values: _*)
- def localizeLater(key: String) = new TextComponentTranslation(resolveKey(key))
+ def localizeLater(key: String) = new TranslationTextComponent(resolveKey(key))
- def localizeImmediately(formatKey: String, values: AnyRef*): String = I18n.translateToLocalFormatted(resolveKey(formatKey), values: _*).split(nl).map(_.trim).mkString("\n")
+ def localizeImmediately(formatKey: String, values: AnyRef*): String = {
+ val k = resolveKey(formatKey)
+ var lm = LanguageMap.getInstance
+ if (!lm.has(k)) return k
+ String.format(lm.getOrDefault(k), values: _*).lines.map(_.trim).mkString("\n")
+ }
- def localizeImmediately(key: String): String = I18n.translateToLocal(resolveKey(key)).split(nl).map(_.trim).mkString("\n")
+ def localizeImmediately(key: String): String = {
+ val k = resolveKey(key)
+ var lm = LanguageMap.getInstance
+ if (!lm.has(k)) return k
+ lm.getOrDefault(k).lines.map(_.trim).mkString("\n")
+ }
object Analyzer {
- def Address(value: String): TextComponentTranslation = {
+ def Address(value: String): IFormattableTextComponent = {
val result = localizeLater("gui.Analyzer.Address", value)
- result.getStyle.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, s"/${SetClipboardCommand.name} $value"))
- result.getStyle.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, localizeLater("gui.Analyzer.CopyToClipboard")))
- result
+ result.setStyle(result.getStyle
+ .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, value))
+ .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, localizeLater("gui.Analyzer.CopyToClipboard"))))
}
- def AddressCopied: TextComponentTranslation = localizeLater("gui.Analyzer.AddressCopied")
+ def AddressCopied: TranslationTextComponent = localizeLater("gui.Analyzer.AddressCopied")
- def ChargerSpeed(value: Double): TextComponentTranslation = localizeLater("gui.Analyzer.ChargerSpeed", (value * 100).toInt + "%")
+ def ChargerSpeed(value: Double): TranslationTextComponent = localizeLater("gui.Analyzer.ChargerSpeed", (value * 100).toInt + "%")
- def ComponentName(value: String): TextComponentTranslation = localizeLater("gui.Analyzer.ComponentName", value)
+ def ComponentName(value: String): TranslationTextComponent = localizeLater("gui.Analyzer.ComponentName", value)
- def Components(count: Int, maxCount: Int): TextComponentTranslation = localizeLater("gui.Analyzer.Components", count + "/" + maxCount)
+ def Components(count: Int, maxCount: Int): TranslationTextComponent = localizeLater("gui.Analyzer.Components", count + "/" + maxCount)
- def LastError(value: String): TextComponentTranslation = localizeLater("gui.Analyzer.LastError", localizeLater(value))
+ def LastError(value: String): TranslationTextComponent = localizeLater("gui.Analyzer.LastError", localizeLater(value))
- def RobotOwner(owner: String): TextComponentTranslation = localizeLater("gui.Analyzer.RobotOwner", owner)
+ def RobotOwner(owner: String): TranslationTextComponent = localizeLater("gui.Analyzer.RobotOwner", owner)
- def RobotName(name: String): TextComponentTranslation = localizeLater("gui.Analyzer.RobotName", name)
+ def RobotName(name: String): TranslationTextComponent = localizeLater("gui.Analyzer.RobotName", name)
- def RobotXp(experience: Double, level: Int): TextComponentTranslation = localizeLater("gui.Analyzer.RobotXp", f"$experience%.2f", level.toString)
+ def RobotXp(experience: Double, level: Int): TranslationTextComponent = localizeLater("gui.Analyzer.RobotXp", f"$experience%.2f", level.toString)
- def StoredEnergy(value: String): TextComponentTranslation = localizeLater("gui.Analyzer.StoredEnergy", value)
+ def StoredEnergy(value: String): TranslationTextComponent = localizeLater("gui.Analyzer.StoredEnergy", value)
- def TotalEnergy(value: String): TextComponentTranslation = localizeLater("gui.Analyzer.TotalEnergy", value)
+ def TotalEnergy(value: String): TranslationTextComponent = localizeLater("gui.Analyzer.TotalEnergy", value)
- def Users(list: Iterable[String]): TextComponentTranslation = localizeLater("gui.Analyzer.Users", list.mkString(", "))
+ def Users(list: Iterable[String]): TranslationTextComponent = localizeLater("gui.Analyzer.Users", list.mkString(", "))
- def WirelessStrength(value: Double): TextComponentTranslation = localizeLater("gui.Analyzer.WirelessStrength", value.toInt.toString)
+ def WirelessStrength(value: Double): TranslationTextComponent = localizeLater("gui.Analyzer.WirelessStrength", value.toInt.toString)
}
object Assembler {
@@ -64,13 +67,13 @@ object Localization {
def CollectResult: String = localizeImmediately("gui.Assembler.Collect")
- def InsertCPU: TextComponentTranslation = localizeLater("gui.Assembler.InsertCPU")
+ def InsertCPU: TranslationTextComponent = localizeLater("gui.Assembler.InsertCPU")
- def InsertRAM: TextComponentTranslation = localizeLater("gui.Assembler.InsertRAM")
+ def InsertRAM: TranslationTextComponent = localizeLater("gui.Assembler.InsertRAM")
def Complexity(complexity: Int, maxComplexity: Int): ITextComponent = {
val message = localizeLater("gui.Assembler.Complexity", complexity.toString, maxComplexity.toString)
- if (complexity > maxComplexity) new TextComponentString("§4").appendSibling(message)
+ if (complexity > maxComplexity) new StringTextComponent("§4").append(message)
else message
}
@@ -78,29 +81,25 @@ object Localization {
def Progress(progress: Double, timeRemaining: String): String = localizeImmediately("gui.Assembler.Progress", progress.toInt.toString, timeRemaining)
- def Warning(name: String): ITextComponent = new TextComponentString("§7- ").appendSibling(localizeLater("gui.Assembler.Warning." + name))
+ def Warning(name: String): ITextComponent = new StringTextComponent("§7- ").append(localizeLater("gui.Assembler.Warning." + name))
- def Warnings: TextComponentTranslation = localizeLater("gui.Assembler.Warnings")
+ def Warnings: TranslationTextComponent = localizeLater("gui.Assembler.Warnings")
}
object Chat {
- def WarningLuaFallback: ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningLuaFallback"))
-
- def WarningProjectRed: ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningProjectRed"))
-
- def WarningFingerprint(event: FMLFingerprintViolationEvent): ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningFingerprint", event.getExpectedFingerprint, event.getFingerprints.toArray.mkString(", ")))
+ def WarningLuaFallback: ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.WarningLuaFallback"))
- def WarningRecipes: ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningRecipes"))
+ def WarningProjectRed: ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.WarningProjectRed"))
- def WarningClassTransformer: ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningClassTransformer"))
+ def WarningRecipes: ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.WarningRecipes"))
- def WarningSimpleComponent: ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningSimpleComponent"))
+ def WarningClassTransformer: ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.WarningClassTransformer"))
- def WarningLink(url: String): ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningLink", url))
+ def WarningLink(url: String): ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.WarningLink", url))
- def InfoNewVersion(version: String): ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.NewVersion", version))
+ def InfoNewVersion(version: String): ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.NewVersion", version))
- def TextureName(name: String): ITextComponent = new TextComponentString("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.TextureName", name))
+ def TextureName(name: String): ITextComponent = new StringTextComponent("§aOpenComputers§f: ").append(localizeLater("gui.Chat.TextureName", name))
}
object Computer {
@@ -156,9 +155,9 @@ object Localization {
}
object Terminal {
- def InvalidKey: TextComponentTranslation = localizeLater("gui.Terminal.InvalidKey")
+ def InvalidKey: TranslationTextComponent = localizeLater("gui.Terminal.InvalidKey")
- def OutOfRange: TextComponentTranslation = localizeLater("gui.Terminal.OutOfRange")
+ def OutOfRange: TranslationTextComponent = localizeLater("gui.Terminal.OutOfRange")
}
object Tooltip {
diff --git a/src/main/scala/li/cil/oc/OpenComputers.scala b/src/main/scala/li/cil/oc/OpenComputers.scala
index 668d1cf536..b6895b6c78 100644
--- a/src/main/scala/li/cil/oc/OpenComputers.scala
+++ b/src/main/scala/li/cil/oc/OpenComputers.scala
@@ -1,67 +1,89 @@
package li.cil.oc
+import java.nio.file.Paths
+
import li.cil.oc.common.IMC
import li.cil.oc.common.Proxy
-import li.cil.oc.server.command.CommandHandler
-import net.minecraftforge.fml.common.Mod
-import net.minecraftforge.fml.common.Mod.EventHandler
-import net.minecraftforge.fml.common.SidedProxy
-import net.minecraftforge.fml.common.event.FMLInterModComms.IMCEvent
-import net.minecraftforge.fml.common.event._
-import net.minecraftforge.fml.common.network.FMLEventChannel
+import li.cil.oc.common.init.Blocks
+import li.cil.oc.common.init.Items
+import li.cil.oc.integration.Mods
import li.cil.oc.util.ThreadPoolFactory
+import net.minecraft.block.Block
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.world.World
+import net.minecraftforge.event.RegistryEvent
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.common.MinecraftForge
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.forgespi.Environment
+import net.minecraftforge.fml.InterModComms
+import net.minecraftforge.fml.ModContainer
+import net.minecraftforge.fml.ModLoadingContext
+import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent
+import net.minecraftforge.fml.loading.FMLPaths
+import net.minecraftforge.fml.network.simple.SimpleChannel
+import net.minecraftforge.scorge.lang.ScorgeModLoadingContext
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
-@Mod(modid = OpenComputers.ID, name = OpenComputers.Name,
- version = OpenComputers.Version,
- modLanguage = "scala", useMetadata = true /*@MCVERSIONDEP@*/)
+import scala.collection.convert.ImplicitConversionsToScala._
+
object OpenComputers {
final val ID = "opencomputers"
final val Name = "OpenComputers"
- final val Version = "@VERSION@"
-
- def log: Logger = logger.getOrElse(LogManager.getLogger(Name))
+ final val log: Logger = LogManager.getLogger(Name)
- var logger: Option[Logger] = None
+ lazy val proxy: Proxy = {
+ val cls = Environment.get.getDist match {
+ case Dist.CLIENT => Class.forName("li.cil.oc.client.Proxy")
+ case _ => Class.forName("li.cil.oc.common.Proxy")
+ }
+ cls.getConstructor().newInstance().asInstanceOf[Proxy]
+ }
- @SidedProxy(clientSide = "li.cil.oc.client.Proxy", serverSide = "li.cil.oc.server.Proxy")
- var proxy: Proxy = null
+ var channel: SimpleChannel = null
- var channel: FMLEventChannel = _
+ private var instance: Option[OpenComputers] = None
- @EventHandler
- def preInit(e: FMLPreInitializationEvent) {
- logger = Option(e.getModLog)
- proxy.preInit(e)
- OpenComputers.log.info("Done with pre init phase.")
+ def get = instance match {
+ case Some(oc) => oc
+ case _ => throw new IllegalStateException("not initialized")
}
+}
- @EventHandler
- def init(e: FMLInitializationEvent): Unit = {
- proxy.init(e)
- OpenComputers.log.info("Done with init phase.")
- }
+class OpenComputers {
+ val modContainer: ModContainer = ModLoadingContext.get.getActiveContainer
- @EventHandler
- def postInit(e: FMLPostInitializationEvent): Unit = {
- proxy.postInit(e)
- OpenComputers.log.info("Done with post init phase.")
- }
+ val Version = modContainer.getModInfo.getVersion
+
+ ScorgeModLoadingContext.get.getModEventBus.register(this)
+ OpenComputers.instance = Some(this)
- @EventHandler
- def serverStart(e: FMLServerStartingEvent): Unit = {
- CommandHandler.register(e)
- ThreadPoolFactory.safePools.foreach(_.newThreadPool())
+ MinecraftForge.EVENT_BUS.register(OpenComputers.proxy)
+ ScorgeModLoadingContext.get.getModEventBus.register(OpenComputers.proxy)
+ Settings.load(FMLPaths.CONFIGDIR.get().resolve(Paths.get("opencomputers", "settings.conf")).toFile())
+ OpenComputers.proxy.preInit()
+ MinecraftForge.EVENT_BUS.register(ThreadPoolFactory)
+ Mods.preInit() // Must happen after loading Settings but before registry events are fired.
+
+ @SubscribeEvent
+ def registerBlocks(e: RegistryEvent.Register[Block]) {
+ Blocks.init()
}
- @EventHandler
- def serverStop(e: FMLServerStoppedEvent): Unit = {
- ThreadPoolFactory.safePools.foreach(_.waitForCompletion())
+ @SubscribeEvent
+ def registerItems(e: RegistryEvent.Register[Item]) {
+ Items.init()
}
- @EventHandler
- def imc(e: IMCEvent): Unit = IMC.handleEvent(e)
+ @SubscribeEvent
+ def imc(e: InterModProcessEvent): Unit = {
+ // Technically requires synchronization because IMC.sendTo doesn't check the loading stage.
+ e.enqueueWork((() => {
+ InterModComms.getMessages(OpenComputers.ID).sequential.iterator.foreach(IMC.handleMessage)
+ }): Runnable)
+ }
}
diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala
index d632a68283..93d043869b 100644
--- a/src/main/scala/li/cil/oc/Settings.scala
+++ b/src/main/scala/li/cil/oc/Settings.scala
@@ -4,6 +4,7 @@ import java.io._
import java.net.Inet4Address
import java.net.InetAddress
import java.nio.charset.StandardCharsets
+import java.nio.file.Paths
import java.security.SecureRandom
import java.util.UUID
@@ -14,16 +15,15 @@ import li.cil.oc.Settings.DebugCardAccess
import li.cil.oc.common.Tier
import li.cil.oc.server.component.DebugCard
import li.cil.oc.server.component.DebugCard.AccessContext
+import net.minecraftforge.fml.loading.FMLPaths
import org.apache.commons.codec.binary.Hex
-import net.minecraftforge.fml.common.Loader
-import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion
-import net.minecraftforge.fml.common.versioning.VersionRange
-import org.apache.commons.lang3.StringEscapeUtils
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion
+import org.apache.maven.artifact.versioning.VersionRange
-import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
import scala.io.Codec
import scala.io.Source
+import scala.jdk.CollectionConverters._
import scala.util.matching.Regex
class Settings(val config: Config) {
@@ -44,7 +44,7 @@ class Settings(val config: Config) {
val beepSampleRate = config.getInt("client.beepSampleRate")
val beepAmplitude = config.getInt("client.beepVolume") max 0 min Byte.MaxValue
val beepRadius = config.getDouble("client.beepRadius").toFloat max 1 min 32
- val nanomachineHudPos = Array(config.getDoubleList("client.nanomachineHudPos"): _*) match {
+ val nanomachineHudPos = config.getDoubleList("client.nanomachineHudPos").asScala.toArray match {
case Array(x, y) =>
(x: Double, y: Double)
case _ =>
@@ -60,14 +60,14 @@ class Settings(val config: Config) {
val startupDelay = config.getDouble("computer.startupDelay") max 0.05
val eepromSize = config.getInt("computer.eepromSize") max 0
val eepromDataSize = config.getInt("computer.eepromDataSize") max 0
- val cpuComponentSupport = Array(config.getIntList("computer.cpuComponentCount"): _*) match {
+ val cpuComponentSupport = config.getIntList("computer.cpuComponentCount").asScala.toArray match {
case Array(tier1, tier2, tier3, tierCreative) =>
Array(tier1: Int, tier2: Int, tier3: Int, tierCreative: Int)
case _ =>
OpenComputers.log.warn("Bad number of CPU component counts, ignoring.")
Array(8, 12, 16, 1024)
}
- val callBudgets = Array(config.getDoubleList("computer.callBudgets"): _*) match {
+ val callBudgets = config.getDoubleList("computer.callBudgets").asScala.toArray match {
case Array(tier1, tier2, tier3) =>
Array(tier1: Double, tier2: Double, tier3: Double)
case _ =>
@@ -85,7 +85,7 @@ class Settings(val config: Config) {
val allowGC = config.getBoolean("computer.lua.allowGC")
val enableLua53 = config.getBoolean("computer.lua.enableLua53")
val defaultLua53 = config.getBoolean("computer.lua.defaultLua53")
- val ramSizes = Array(config.getIntList("computer.lua.ramSizes"): _*) match {
+ val ramSizes = config.getIntList("computer.lua.ramSizes").asScala.toArray match {
case Array(tier1, tier2, tier3, tier4, tier5, tier6) =>
Array(tier1: Int, tier2: Int, tier3: Int, tier4: Int, tier5: Int, tier6: Int)
case _ =>
@@ -107,7 +107,7 @@ class Settings(val config: Config) {
val itemDamageRate = config.getDouble("robot.itemDamageRate") max 0 min 1
val nameFormat = config.getString("robot.nameFormat")
val uuidFormat = config.getString("robot.uuidFormat")
- val upgradeFlightHeight = Array(config.getIntList("robot.upgradeFlightHeight"): _*) match {
+ val upgradeFlightHeight = config.getIntList("robot.upgradeFlightHeight").asScala.toArray match {
case Array(tier1, tier2) =>
Array(tier1: Int, tier2: Int)
case _ =>
@@ -165,7 +165,7 @@ class Settings(val config: Config) {
val bufferRobot = config.getDouble("power.buffer.robot") max 0
val bufferConverter = config.getDouble("power.buffer.converter") max 0
val bufferDistributor = config.getDouble("power.buffer.distributor") max 0
- val bufferCapacitorUpgrades = Array(config.getDoubleList("power.buffer.batteryUpgrades"): _*) match {
+ val bufferCapacitorUpgrades = config.getDoubleList("power.buffer.batteryUpgrades").asScala.toArray match {
case Array(tier1, tier2, tier3) =>
Array(tier1: Double, tier2: Double, tier3: Double)
case _ =>
@@ -196,7 +196,7 @@ class Settings(val config: Config) {
val robotTurnCost = config.getDouble("power.cost.robotTurn") max 0
val robotMoveCost = config.getDouble("power.cost.robotMove") max 0
val robotExhaustionCost = config.getDouble("power.cost.robotExhaustion") max 0
- val wirelessCostPerRange = Array(config.getDoubleList("power.cost.wirelessCostPerRange"): _*) match {
+ val wirelessCostPerRange = config.getDoubleList("power.cost.wirelessCostPerRange").asScala.toArray match {
case Array(tier1, tier2) =>
Array((tier1: Double) max 0.0, (tier2: Double) max 0.0)
case _ =>
@@ -236,7 +236,7 @@ class Settings(val config: Config) {
// power.rate
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0
val assemblerRate = config.getDouble("power.rate.assembler") max 0
- val caseRate = (Array(config.getDoubleList("power.rate.case"): _*) match {
+ val caseRate = (config.getDoubleList("power.rate.case").asScala.toArray match {
case Array(tier1, tier2, tier3) =>
Array(tier1: Double, tier2: Double, tier3: Double)
case _ =>
@@ -276,14 +276,14 @@ class Settings(val config: Config) {
// filesystem
val fileCost = config.getInt("filesystem.fileCost") max 0
val bufferChanges = config.getBoolean("filesystem.bufferChanges")
- val hddSizes = Array(config.getIntList("filesystem.hddSizes"): _*) match {
+ val hddSizes = config.getIntList("filesystem.hddSizes").asScala.toArray match {
case Array(tier1, tier2, tier3) =>
Array(tier1: Int, tier2: Int, tier3: Int)
case _ =>
OpenComputers.log.warn("Bad number of HDD sizes, ignoring.")
Array(1024, 2048, 4096)
}
- val hddPlatterCounts = Array(config.getIntList("filesystem.hddPlatterCounts"): _*) match {
+ val hddPlatterCounts = config.getIntList("filesystem.hddPlatterCounts").asScala.toArray match {
case Array(tier1, tier2, tier3) =>
Array(tier1: Int, tier2: Int, tier3: Int)
case _ =>
@@ -302,8 +302,8 @@ class Settings(val config: Config) {
val httpEnabled = config.getBoolean("internet.enableHttp")
val httpHeadersEnabled = config.getBoolean("internet.enableHttpHeaders")
val tcpEnabled = config.getBoolean("internet.enableTcp")
- val httpHostBlacklist = Array(config.getStringList("internet.blacklist").map(new Settings.AddressValidator(_)): _*)
- val httpHostWhitelist = Array(config.getStringList("internet.whitelist").map(new Settings.AddressValidator(_)): _*)
+ val httpHostBlacklist = config.getStringList("internet.blacklist").asScala.map(new Settings.AddressValidator(_)).toArray
+ val httpHostWhitelist = config.getStringList("internet.whitelist").asScala.map(new Settings.AddressValidator(_)).toArray
val httpTimeout = (config.getInt("internet.requestTimeout") max 0) * 1000
val maxConnections = config.getInt("internet.maxTcpConnections") max 0
val internetThreads = config.getInt("internet.threads") max 1
@@ -319,14 +319,14 @@ class Settings(val config: Config) {
// ----------------------------------------------------------------------- //
// hologram
- val hologramMaxScaleByTier = Array(config.getDoubleList("hologram.maxScale"): _*) match {
+ val hologramMaxScaleByTier = config.getDoubleList("hologram.maxScale").asScala.toArray match {
case Array(tier1, tier2) =>
Array((tier1: Double) max 1.0, (tier2: Double) max 1.0)
case _ =>
OpenComputers.log.warn("Bad number of hologram max scales, ignoring.")
Array(3.0, 4.0)
}
- val hologramMaxTranslationByTier = Array(config.getDoubleList("hologram.maxTranslation"): _*) match {
+ val hologramMaxTranslationByTier = config.getDoubleList("hologram.maxTranslation").asScala.toArray match {
case Array(tier1, tier2) =>
Array((tier1: Double) max 0.0, (tier2: Double) max 0.0)
case _ =>
@@ -344,14 +344,14 @@ class Settings(val config: Config) {
val maxNetworkPacketSize = config.getInt("misc.maxNetworkPacketSize") max 0
// Need at least 4 for nanomachine protocol. Because I can!
val maxNetworkPacketParts = config.getInt("misc.maxNetworkPacketParts") max 4
- val maxOpenPorts = Array(config.getIntList("misc.maxOpenPorts"): _*) match {
+ val maxOpenPorts = config.getIntList("misc.maxOpenPorts").asScala.toArray match {
case Array(wired, tier1, tier2) =>
Array((wired: Int) max 0, (tier1: Int) max 0, (tier2: Int) max 0)
case _ =>
OpenComputers.log.warn("Bad number of max open ports, ignoring.")
Array(16, 1, 16)
}
- val maxWirelessRange = Array(config.getDoubleList("misc.maxWirelessRange"): _*) match {
+ val maxWirelessRange = config.getDoubleList("misc.maxWirelessRange").asScala.toArray match {
case Array(tier1, tier2) =>
Array((tier1: Double) max 0.0, (tier2: Double) max 0.0)
case _ =>
@@ -455,8 +455,7 @@ class Settings(val config: Config) {
case "true" | "allow" | java.lang.Boolean.TRUE => DebugCardAccess.Allowed
case "false" | "deny" | java.lang.Boolean.FALSE => DebugCardAccess.Forbidden
case "whitelist" =>
- val wlFile = new File(Loader.instance.getConfigDir + File.separator + "opencomputers" + File.separator +
- "debug_card_whitelist.txt")
+ val wlFile = FMLPaths.CONFIGDIR.get.resolve(Paths.get("opencomputers", "debug_card_whitelist.txt")).toFile()
DebugCardAccess.Whitelist(wlFile)
@@ -472,7 +471,7 @@ class Settings(val config: Config) {
val maxSignalQueueSize: Int = (if (config.hasPath("computer.maxSignalQueueSize")) config.getInt("computer.maxSignalQueueSize") else 256) min 256
// >= 1.7.6
- val vramSizes: Array[Double] = Array(config.getDoubleList("gpu.vramSizes"): _*) match {
+ val vramSizes: Array[Double] = config.getDoubleList("gpu.vramSizes").asScala.toArray match {
case Array(tier1, tier2, tier3) => Array(tier1: Double, tier2: Double, tier3: Double)
case _ =>
OpenComputers.log.warn("Bad number of VRAM sizes (expected 3), ignoring.")
@@ -483,7 +482,7 @@ class Settings(val config: Config) {
}
object Settings {
- val resourceDomain = "opencomputers"
+ val resourceDomain = OpenComputers.ID
val namespace = "oc:"
val savePath = "opencomputers/"
val scriptPath: String = "/assets/" + resourceDomain + "/lua/"
@@ -530,7 +529,6 @@ object Settings {
try {
val renderSettings = ConfigRenderOptions.defaults.setJson(false).setOriginComments(false)
val nl = sys.props("line.separator")
- val nle = StringEscapeUtils.escapeJava(nl)
file.getParentFile.mkdirs()
val out = new PrintWriter(file)
out.write(config.root.render(renderSettings).lines.
@@ -539,7 +537,7 @@ object Settings {
// Finalize the string.
filter(_ != "").mkString(nl).
// Newline after values.
- replaceAll(s"((?:\\s*#.*$nle)(?:\\s*[^#\\s].*$nle)+)", "$1" + nl))
+ replaceAll(s"((?:\\s*#.*$nl)(?:\\s*[^#\\s].*$nl)+)", "$1" + nl))
out.close()
}
catch {
@@ -572,12 +570,12 @@ object Settings {
// created by) against the current version to see if some hard changes
// were made. If so, the new default values are copied over.
private def patchConfig(config: Config, defaults: Config) = {
- val mod = Loader.instance.activeModContainer
+ val modVersion = OpenComputers.get.Version
val prefix = "opencomputers."
val configVersion = new DefaultArtifactVersion(if (config.hasPath(prefix + "version")) config.getString(prefix + "version") else "0.0.0")
var patched = config
- if (configVersion.compareTo(mod.getProcessedVersion) != 0) {
- OpenComputers.log.info(s"Updating config from version '${configVersion.getVersionString}' to '${defaults.getString(prefix + "version")}'.")
+ if (configVersion.compareTo(modVersion) != 0) {
+ OpenComputers.log.info(s"Updating config from version '${configVersion}' to '${defaults.getString(prefix + "version")}'.")
patched = patched.withValue(prefix + "version", defaults.getValue(prefix + "version"))
for ((version, paths) <- configPatches if version.containsVersion(configVersion)) {
for (path <- paths) {
diff --git a/src/main/scala/li/cil/oc/client/ColorHandler.scala b/src/main/scala/li/cil/oc/client/ColorHandler.scala
index 8430feda31..0ae6e82c10 100644
--- a/src/main/scala/li/cil/oc/client/ColorHandler.scala
+++ b/src/main/scala/li/cil/oc/client/ColorHandler.scala
@@ -8,15 +8,17 @@ import li.cil.oc.util.Color
import li.cil.oc.util.ItemColorizer
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.color.IBlockColor
import net.minecraft.client.renderer.color.IItemColor
-import net.minecraft.item.EnumDyeColor
+import net.minecraft.item.DyeColor
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
+import net.minecraft.util.IItemProvider
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.world.IBlockDisplayReader
+import net.minecraft.world.IBlockReader
object ColorHandler {
def init(): Unit = {
@@ -26,7 +28,7 @@ object ColorHandler {
},
api.Items.get(Constants.BlockName.Cable).block())
- register((state, world, pos, tintIndex) => if (pos == null) 0xFFFFFFFF else world.getTileEntity(pos) match {
+ register((state, world, pos, tintIndex) => if (pos == null) 0xFFFFFFFF else world.getBlockEntity(pos) match {
case colored: Colored => colored.getColor
case _ => state.getBlock match {
case block: block.Case => Color.rgbValues(Color.byTier(block.tier))
@@ -38,7 +40,7 @@ object ColorHandler {
api.Items.get(Constants.BlockName.CaseTier3).block(),
api.Items.get(Constants.BlockName.CaseCreative).block())
- register((state, world, pos, tintIndex) => Color.rgbValues(Color.byOreName(Color.dyes(state.getBlock.getMetaFromState(state) max 0 min Color.dyes.length))),
+ register((state, world, pos, tintIndex) => Color.rgbValues(state.getValue(block.ChameliumBlock.Color)),
api.Items.get(Constants.BlockName.ChameliumBlock).block())
register((state, world, pos, tintIndex) => tintIndex,
@@ -53,23 +55,23 @@ object ColorHandler {
api.Items.get(Constants.BlockName.ScreenTier3).block())
register((stack, tintIndex) => if (ItemColorizer.hasColor(stack)) ItemColorizer.getColor(stack) else tintIndex,
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.Cable).block()))
+ api.Items.get(Constants.BlockName.Cable).block())
register((stack, tintIndex) => Color.rgbValues(Color.byTier(ItemUtils.caseTier(stack))),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.CaseTier1).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.CaseTier2).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.CaseTier3).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.CaseCreative).block()))
+ api.Items.get(Constants.BlockName.CaseTier1).block(),
+ api.Items.get(Constants.BlockName.CaseTier2).block(),
+ api.Items.get(Constants.BlockName.CaseTier3).block(),
+ api.Items.get(Constants.BlockName.CaseCreative).block())
- register((stack, tintIndex) => Color.rgbValues(EnumDyeColor.byDyeDamage(stack.getItemDamage)),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.ChameliumBlock).block()))
+ register((stack, tintIndex) => Color.rgbValues(DyeColor.byId(stack.getDamageValue)),
+ api.Items.get(Constants.BlockName.ChameliumBlock).block())
register((stack, tintIndex) => tintIndex,
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.ScreenTier1).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.ScreenTier2).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.ScreenTier3).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.Print).block()),
- Item.getItemFromBlock(api.Items.get(Constants.BlockName.Robot).block()))
+ api.Items.get(Constants.BlockName.ScreenTier1).block(),
+ api.Items.get(Constants.BlockName.ScreenTier2).block(),
+ api.Items.get(Constants.BlockName.ScreenTier3).block(),
+ api.Items.get(Constants.BlockName.Print).block(),
+ api.Items.get(Constants.BlockName.Robot).block())
register((stack, tintIndex) =>
if (tintIndex == 1) {
@@ -78,15 +80,15 @@ object ColorHandler {
api.Items.get(Constants.ItemName.HoverBoots).item())
}
- def register(handler: (IBlockState, IBlockAccess, BlockPos, Int) => Int, blocks: Block*): Unit = {
- Minecraft.getMinecraft.getBlockColors.registerBlockColorHandler(new IBlockColor {
- override def colorMultiplier(state: IBlockState, world: IBlockAccess, pos: BlockPos, tintIndex: Int): Int = handler(state, world, pos, tintIndex)
+ def register(handler: (BlockState, IBlockReader, BlockPos, Int) => Int, blocks: Block*): Unit = {
+ Minecraft.getInstance.getBlockColors.register(new IBlockColor {
+ override def getColor(state: BlockState, world: IBlockDisplayReader, pos: BlockPos, tintIndex: Int): Int = handler(state, world, pos, tintIndex)
}, blocks: _*)
}
- def register(handler: (ItemStack, Int) => Int, items: Item*): Unit = {
- Minecraft.getMinecraft.getItemColors.registerItemColorHandler(new IItemColor {
- override def colorMultiplier(stack: ItemStack, tintIndex: Int): Int = handler(stack, tintIndex)
+ def register(handler: (ItemStack, Int) => Int, items: IItemProvider*): Unit = {
+ Minecraft.getInstance.getItemColors.register(new IItemColor {
+ override def getColor(stack: ItemStack, tintIndex: Int): Int = handler(stack, tintIndex)
}, items: _*)
}
}
diff --git a/src/main/scala/li/cil/oc/client/CommandHandler.scala b/src/main/scala/li/cil/oc/client/CommandHandler.scala
deleted file mode 100644
index 6ea1bfb835..0000000000
--- a/src/main/scala/li/cil/oc/client/CommandHandler.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package li.cil.oc.client
-
-import li.cil.oc.common.command.SimpleCommand
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.command.ICommandSender
-import net.minecraft.server.MinecraftServer
-import net.minecraftforge.client.ClientCommandHandler
-
-object CommandHandler {
- def register(): Unit = {
- ClientCommandHandler.instance.registerCommand(SetClipboardCommand)
- }
-
- object SetClipboardCommand extends SimpleCommand("oc_setclipboard") {
- override def getUsage(source: ICommandSender): String = name + " "
-
- override def execute(server: MinecraftServer, source: ICommandSender, command: Array[String]): Unit = {
- if (source.getEntityWorld.isRemote && command != null && command.length > 0) {
- GuiScreen.setClipboardString(command(0))
- }
- }
-
- // OP levels for reference:
- // 1 - Ops can bypass spawn protection.
- // 2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /summon, /setblock and /tp, and can edit command blocks.
- // 3 - Ops can use /ban, /deop, /kick, and /op.
- // 4 - Ops can use /stop.
-
- override def getRequiredPermissionLevel = 0
- }
-
-}
diff --git a/src/main/scala/li/cil/oc/client/ComponentTracker.scala b/src/main/scala/li/cil/oc/client/ComponentTracker.scala
index 42a6950794..6cc54342dc 100644
--- a/src/main/scala/li/cil/oc/client/ComponentTracker.scala
+++ b/src/main/scala/li/cil/oc/client/ComponentTracker.scala
@@ -4,5 +4,5 @@ import li.cil.oc.common
import net.minecraft.world.World
object ComponentTracker extends common.ComponentTracker {
- override protected def clear(world: World) = if (world.isRemote) super.clear(world)
+ override protected def clear(world: World) = if (world.isClientSide) super.clear(world)
}
diff --git a/src/main/scala/li/cil/oc/client/GuiHandler.scala b/src/main/scala/li/cil/oc/client/GuiHandler.scala
deleted file mode 100644
index bf9736f932..0000000000
--- a/src/main/scala/li/cil/oc/client/GuiHandler.scala
+++ /dev/null
@@ -1,156 +0,0 @@
-package li.cil.oc.client
-
-import com.google.common.base.Strings
-import li.cil.oc.Localization
-import li.cil.oc.Settings
-import li.cil.oc.api
-import li.cil.oc.common.GuiType
-import li.cil.oc.common.component
-import li.cil.oc.common.entity
-import li.cil.oc.common.inventory.{DatabaseInventory, DiskDriveMountableInventory, ServerInventory}
-import li.cil.oc.common.item
-import li.cil.oc.common.item.Delegator
-import li.cil.oc.common.tileentity
-import li.cil.oc.common.{GuiHandler => CommonGuiHandler}
-import li.cil.oc.util.BlockPosition
-import li.cil.oc.util.ExtendedWorld._
-import net.minecraft.client.Minecraft
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.tileentity.TileEntity
-import net.minecraft.world.World
-import net.minecraft.item.ItemStack
-
-object GuiHandler extends CommonGuiHandler {
- override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef = {
- GuiType.Categories.get(id) match {
- case Some(GuiType.Category.Block) =>
- world.getTileEntity(BlockPosition(x, GuiType.extractY(y), z)) match {
- case t: tileentity.Adapter if id == GuiType.Adapter.id =>
- new gui.Adapter(player.inventory, t)
- case t: tileentity.Assembler if id == GuiType.Assembler.id =>
- new gui.Assembler(player.inventory, t)
- case t: tileentity.Case if id == GuiType.Case.id =>
- new gui.Case(player.inventory, t)
- case t: tileentity.Charger if id == GuiType.Charger.id =>
- new gui.Charger(player.inventory, t)
- case t: tileentity.Disassembler if id == GuiType.Disassembler.id =>
- new gui.Disassembler(player.inventory, t)
- case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
- new gui.DiskDrive(player.inventory, t)
- case t: tileentity.Printer if id == GuiType.Printer.id =>
- new gui.Printer(player.inventory, t)
- case t: tileentity.Rack if id == GuiType.Rack.id =>
- new gui.Rack(player.inventory, t)
- case t: tileentity.Raid if id == GuiType.Raid.id =>
- new gui.Raid(player.inventory, t)
- case t: tileentity.Relay if id == GuiType.Relay.id =>
- new gui.Relay(player.inventory, t)
- case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
- new gui.Robot(player.inventory, t.robot)
- case t: tileentity.Screen if id == GuiType.Screen.id =>
- new gui.Screen(t.origin.buffer, t.tier > 0, () => t.origin.hasKeyboard, () => t.origin.buffer.isRenderingEnabled)
- case t: tileentity.Rack if id == GuiType.ServerInRack.id =>
- val slot = GuiType.extractSlot(y)
- new gui.Server(player.inventory, new ServerInventory {
- override def container = t.getStackInSlot(slot)
-
- override def isUsableByPlayer(player: EntityPlayer) = t.isUsableByPlayer(player)
- }, Option(t), slot)
- case t: tileentity.Rack if id == GuiType.DiskDriveMountableInRack.id =>
- val slot = GuiType.extractSlot(y)
- new gui.DiskDrive(player.inventory, new DiskDriveMountableInventory {
- override def container: ItemStack = t.getStackInSlot(slot)
-
- override def isUsableByPlayer(player: EntityPlayer): Boolean = t.isUsableByPlayer(player)
- })
- case t: tileentity.Waypoint if id == GuiType.Waypoint.id =>
- new gui.Waypoint(t)
- case _ => null
- }
- case Some(GuiType.Category.Entity) =>
- world.getEntityByID(x) match {
- case drone: entity.Drone if id == GuiType.Drone.id =>
- new gui.Drone(player.inventory, drone)
- case _ => null
- }
- case Some(GuiType.Category.Item) => {
- val itemStackInUse = getItemStackInUse(id, player)
- Delegator.subItem(itemStackInUse) match {
- case Some(drive: item.traits.FileSystemLike) if id == GuiType.Drive.id =>
- new gui.Drive(player.inventory, () => itemStackInUse)
- case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
- new gui.Database(player.inventory, new DatabaseInventory {
- override def container = itemStackInUse
-
- override def isUsableByPlayer(player: EntityPlayer) = player == player
- })
- case Some(server: item.Server) if id == GuiType.Server.id =>
- new gui.Server(player.inventory, new ServerInventory {
- override def container = itemStackInUse
-
- override def isUsableByPlayer(player: EntityPlayer) = player == player
- })
- case Some(tablet: item.Tablet) if id == GuiType.Tablet.id =>
- val stack = itemStackInUse
- if (stack.hasTagCompound) {
- item.Tablet.get(stack, player).components.collect {
- case Some(buffer: api.internal.TextBuffer) => buffer
- }.headOption match {
- case Some(buffer: api.internal.TextBuffer) => new gui.Screen(buffer, true, () => true, () => buffer.isRenderingEnabled)
- case _ => null
- }
- }
- else null
- case Some(tablet: item.Tablet) if id == GuiType.TabletInner.id =>
- val stack = itemStackInUse
- if (stack.hasTagCompound) {
- new gui.Tablet(player.inventory, item.Tablet.get(stack, player))
- }
- else null
- case Some(_: item.DiskDriveMountable) if id == GuiType.DiskDriveMountable.id =>
- new gui.DiskDrive(player.inventory, new DiskDriveMountableInventory {
- override def container = itemStackInUse
- override def isUsableByPlayer(activePlayer : EntityPlayer): Boolean = activePlayer == player
- })
- case Some(terminal: item.Terminal) if id == GuiType.Terminal.id =>
- val stack = itemStackInUse
- if (stack.hasTagCompound) {
- val address = stack.getTagCompound.getString(Settings.namespace + "server")
- val key = stack.getTagCompound.getString(Settings.namespace + "key")
- if (!Strings.isNullOrEmpty(key) && !Strings.isNullOrEmpty(address)) {
- component.TerminalServer.loaded.find(address) match {
- case Some(term) if term != null && term.rack != null => term.rack match {
- case rack: TileEntity with api.internal.Rack =>
- def inRange = player.isEntityAlive && !rack.isInvalid && rack.getDistanceSq(player.posX, player.posY, player.posZ) < term.range * term.range
- if (inRange) {
- if (term.sidedKeys.contains(key)) return new gui.Screen(term.buffer, true, () => true, () => {
- // Check if someone else bound a term to our server.
- if (stack.getTagCompound.getString(Settings.namespace + "key") != key) {
- Minecraft.getMinecraft.displayGuiScreen(null)
- }
- // Check whether we're still in range.
- if (!inRange) {
- Minecraft.getMinecraft.displayGuiScreen(null)
- }
- true
- })
- else player.sendMessage(Localization.Terminal.InvalidKey)
- }
- else player.sendMessage(Localization.Terminal.OutOfRange)
- case _ => // Eh?
- }
- case _ => player.sendMessage(Localization.Terminal.OutOfRange)
- }
- }
- }
- null
- case _ => null
- }
- }
- case Some(GuiType.Category.None) =>
- if (id == GuiType.Manual.id) new gui.Manual()
- else null
- case _ => null
- }
- }
-}
diff --git a/src/main/scala/li/cil/oc/client/KeyBindings.scala b/src/main/scala/li/cil/oc/client/KeyBindings.scala
index 688a1a9491..f357ff7cb1 100644
--- a/src/main/scala/li/cil/oc/client/KeyBindings.scala
+++ b/src/main/scala/li/cil/oc/client/KeyBindings.scala
@@ -1,44 +1,56 @@
package li.cil.oc.client
import li.cil.oc.OpenComputers
-import net.minecraft.client.settings.GameSettings
+import li.cil.oc.client.gui.traits.InputBuffer
+import net.minecraft.client.Minecraft
import net.minecraft.client.settings.KeyBinding
-import net.minecraftforge.fml.client.FMLClientHandler
-import org.lwjgl.input.Keyboard
-import org.lwjgl.input.Mouse
+import net.minecraft.client.util.InputMappings
+import net.minecraftforge.client.settings.IKeyConflictContext
+import net.minecraftforge.client.settings.KeyConflictContext
+import net.minecraftforge.client.settings.KeyModifier
+import org.lwjgl.glfw.GLFW
import scala.collection.mutable
object KeyBindings {
- val keyBindingChecks = mutable.ArrayBuffer(isKeyBindingPressedVanilla _)
-
- val keyBindingNameGetters = mutable.ArrayBuffer(getKeyBindingNameVanilla _)
+ private def isActive(input: InputMappings.Input): Boolean = {
+ val window = Minecraft.getInstance.getWindow.getWindow
+ input.getType match {
+ case InputMappings.Type.MOUSE => GLFW.glfwGetMouseButton(window, input.getValue) == GLFW.GLFW_PRESS
+ case InputMappings.Type.SCANCODE => false // GLFW doesn't have a glfwGetScancode method to test these.
+ case InputMappings.Type.KEYSYM => GLFW.glfwGetKey(window, input.getValue) == GLFW.GLFW_PRESS
+ }
+ }
- def showExtendedTooltips: Boolean = isKeyBindingPressed(extendedTooltip)
+ def showExtendedTooltips: Boolean = {
+ if (extendedTooltip.isDown) return true
+ // We have to know if the keybind is pressed even if the active screen doesn't pass events.
+ if (!extendedTooltip.getKeyConflictContext.isActive) return false
+ if (extendedTooltip.getKey == InputMappings.UNKNOWN) return false
+ extendedTooltip.getKeyModifier match {
+ // KeyModifier.NONE does not accept pure modifier keys by default, so check for that.
+ case KeyModifier.NONE if KeyModifier.isKeyCodeModifier(extendedTooltip.getKey) => isActive(extendedTooltip.getKey)
+ case mod if mod.isActive(extendedTooltip.getKeyConflictContext) => isActive(extendedTooltip.getKey)
+ case _ => false
+ }
+ }
- def isPastingClipboard: Boolean = isKeyBindingPressed(clipboardPaste)
+ def isAnalyzeCopyingAddress: Boolean = analyzeCopyAddr.isDown
- def getKeyBindingName(keyBinding: KeyBinding): String = keyBindingNameGetters.map(_ (keyBinding)).collectFirst {
- case Some(name) => name
- }.getOrElse("???")
+ def getKeyBindingName(keyBinding: KeyBinding) = keyBinding.getTranslatedKeyMessage.getString
- def isKeyBindingPressed(keyBinding: KeyBinding): Boolean = keyBindingChecks.forall(_ (keyBinding))
+ val textInputConflict = new IKeyConflictContext {
+ override def isActive: Boolean = Minecraft.getInstance.screen.isInstanceOf[InputBuffer]
- def getKeyBindingNameVanilla(keyBinding: KeyBinding): Option[String] = try Some(GameSettings.getKeyDisplayString(keyBinding.getKeyCode)) catch {
- case _: Throwable => None
+ override def conflicts(other: IKeyConflictContext): Boolean = this == other
}
- def isKeyBindingPressedVanilla(keyBinding: KeyBinding): Boolean = try {
- if (keyBinding.getKeyCode < 0)
- Mouse.isCreated && Mouse.isButtonDown(keyBinding.getKeyCode + 100)
- else
- Keyboard.isCreated && Keyboard.isKeyDown(keyBinding.getKeyCode)
- }
- catch {
- case _: Throwable => false
- }
+ val extendedTooltip = new KeyBinding("key.opencomputers.extendedTooltip", KeyConflictContext.GUI,
+ InputMappings.Type.KEYSYM, GLFW.GLFW_KEY_LEFT_SHIFT, OpenComputers.Name)
- def extendedTooltip: KeyBinding = FMLClientHandler.instance.getClient.gameSettings.keyBindSneak
+ val analyzeCopyAddr = new KeyBinding("key.opencomputers.analyzeCopyAddress", KeyConflictContext.IN_GAME,
+ InputMappings.Type.KEYSYM, GLFW.GLFW_KEY_LEFT_CONTROL, OpenComputers.Name)
- val clipboardPaste = new KeyBinding("key.clipboardPaste", Keyboard.KEY_INSERT, OpenComputers.Name)
+ val clipboardPaste = new KeyBinding("key.opencomputers.clipboardPaste", textInputConflict,
+ InputMappings.Type.KEYSYM, GLFW.GLFW_KEY_INSERT, OpenComputers.Name)
}
diff --git a/src/main/scala/li/cil/oc/client/Manual.scala b/src/main/scala/li/cil/oc/client/Manual.scala
index a0e81fb297..38644b5ec0 100644
--- a/src/main/scala/li/cil/oc/client/Manual.scala
+++ b/src/main/scala/li/cil/oc/client/Manual.scala
@@ -8,23 +8,22 @@ import li.cil.oc.api.manual.ImageProvider
import li.cil.oc.api.manual.ImageRenderer
import li.cil.oc.api.manual.PathProvider
import li.cil.oc.api.manual.TabIconRenderer
-import li.cil.oc.common.GuiType
import net.minecraft.client.Minecraft
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
-import net.minecraftforge.fml.common.FMLCommonHandler
import scala.annotation.tailrec
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
object Manual extends ManualAPI {
final val LanguageKey = "%LANGUAGE%"
- final val FallbackLanguage = "en_US"
+ final val FallbackLanguage = "en_us"
class History(val path: String, var offset: Int = 0)
@@ -38,7 +37,7 @@ object Manual extends ManualAPI {
val imageProviders = mutable.Buffer.empty[(String, ImageProvider)]
- val history = new mutable.Stack[History]
+ val history = new mutable.ArrayStack[History]
reset()
@@ -87,7 +86,7 @@ object Manual extends ManualAPI {
override def contentFor(path: String): java.lang.Iterable[String] = {
val cleanPath = com.google.common.io.Files.simplifyPath(path)
- val language = FMLCommonHandler.instance.getCurrentLanguage
+ val language = Minecraft.getInstance().getLanguageManager().getSelected().getCode()
contentForWithRedirects(cleanPath.replaceAll(LanguageKey, language)).
orElse(contentForWithRedirects(cleanPath.replaceAll(LanguageKey, FallbackLanguage))).
orNull
@@ -107,9 +106,10 @@ object Manual extends ManualAPI {
null
}
- override def openFor(player: EntityPlayer): Unit = {
- if (player.getEntityWorld.isRemote) {
- player.openGui(OpenComputers, GuiType.Manual.id, player.getEntityWorld, 0, 0, 0)
+ override def openFor(player: PlayerEntity): Unit = {
+ if (player.level.isClientSide) {
+ val mc = Minecraft.getInstance
+ if (player == mc.player) mc.pushGuiLayer(new gui.Manual())
}
}
@@ -119,7 +119,7 @@ object Manual extends ManualAPI {
}
override def navigate(path: String): Unit = {
- Minecraft.getMinecraft.currentScreen match {
+ Minecraft.getInstance.screen match {
case manual: gui.Manual => manual.pushPage(path)
case _ => history.push(new History(path))
}
diff --git a/src/main/scala/li/cil/oc/client/PacketHandler.scala b/src/main/scala/li/cil/oc/client/PacketHandler.scala
index 9cf0b967ab..327f0e1c9b 100644
--- a/src/main/scala/li/cil/oc/client/PacketHandler.scala
+++ b/src/main/scala/li/cil/oc/client/PacketHandler.scala
@@ -1,7 +1,10 @@
package li.cil.oc.client
import java.io.EOFException
+import java.io.InputStream
+import com.mojang.blaze3d.systems.IRenderCall
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
@@ -23,32 +26,25 @@ import li.cil.oc.integration.jei.ModJEI
import li.cil.oc.util.Audio
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompressedStreamTools
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumParticleTypes
+import net.minecraft.particles.IParticleData
+import net.minecraft.util.Direction
+import net.minecraft.util.Util
import net.minecraft.util.ResourceLocation
import net.minecraft.util.SoundCategory
import net.minecraft.util.SoundEvent
-import net.minecraft.util.math.Vec3d
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.util.text.ChatType
import net.minecraft.world.World
import net.minecraftforge.common.MinecraftForge
-import net.minecraftforge.fml.common.Optional
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent
-import org.lwjgl.input.Keyboard
+import net.minecraftforge.registries.ForgeRegistries
object PacketHandler extends CommonPacketHandler {
- @SubscribeEvent
- def onPacket(e: ClientCustomPacketEvent): Unit = {
- onPacketData(e.getManager.getNetHandler, e.getPacket.payload, Minecraft.getMinecraft.player)
- }
-
- protected override def world(player: EntityPlayer, dimension: Int): Option[World] = {
- val world = player.world
- if (world.provider.getDimension == dimension) Some(world)
+ protected override def world(player: PlayerEntity, dimension: ResourceLocation): Option[World] = {
+ val world = player.level
+ if (world.dimension.location.equals(dimension)) Some(world)
else None
}
@@ -115,23 +111,28 @@ object PacketHandler extends CommonPacketHandler {
}
def onAdapterState(p: PacketParser): Unit =
- p.readTileEntity[Adapter]() match {
+ p.readBlockEntity[Adapter]() match {
case Some(t) =>
t.openSides = t.uncompressSides(p.readByte())
- t.world.notifyBlockUpdate(t.getPos)
+ t.world.notifyBlockUpdate(t.getBlockPos)
case _ => // Invalid packet.
}
def onAnalyze(p: PacketParser) {
val address = p.readUTF()
- if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
- GuiScreen.setClipboardString(address)
- p.player.sendMessage(Localization.Analyzer.AddressCopied)
+ if (KeyBindings.isAnalyzeCopyingAddress) {
+ RenderSystem.recordRenderCall(new IRenderCall {
+ override def execute = {
+ val mc = Minecraft.getInstance
+ mc.keyboardHandler.setClipboard(address)
+ mc.gui.handleChat(ChatType.SYSTEM, Localization.Analyzer.AddressCopied, Util.NIL_UUID)
+ }
+ })
}
}
def onChargerState(p: PacketParser): Unit =
- p.readTileEntity[Charger]() match {
+ p.readBlockEntity[Charger]() match {
case Some(t) =>
t.chargeSpeed = p.readDouble()
t.hasPower = p.readBoolean()
@@ -144,14 +145,17 @@ object PacketHandler extends CommonPacketHandler {
}
def onClipboard(p: PacketParser) {
- GuiScreen.setClipboardString(p.readUTF())
+ val contents = p.readUTF()
+ RenderSystem.recordRenderCall(new IRenderCall {
+ override def execute = Minecraft.getInstance.keyboardHandler.setClipboard(contents)
+ })
}
def onColorChange(p: PacketParser): Unit =
- p.readTileEntity[Colored]() match {
+ p.readBlockEntity[Colored]() match {
case Some(t) =>
t.setColor(p.readInt())
- t.getWorld.notifyBlockUpdate(t.position)
+ t.getLevel.notifyBlockUpdate(t.position)
case _ => // Invalid packet.
}
@@ -165,7 +169,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onComputerState(p: PacketParser): Unit =
- p.readTileEntity[Computer]() match {
+ p.readBlockEntity[Computer]() match {
case Some(t) =>
t.setRunning(p.readBoolean())
t.hasErrored = p.readBoolean()
@@ -173,7 +177,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onComputerUserList(p: PacketParser): Unit =
- p.readTileEntity[Computer]() match {
+ p.readBlockEntity[Computer]() match {
case Some(t) =>
val count = p.readInt()
t.setUsers((0 until count).map(_ => p.readUTF()))
@@ -181,9 +185,9 @@ object PacketHandler extends CommonPacketHandler {
}
def onContainerUpdate(p: PacketParser): Unit = {
- val windowId = p.readUnsignedByte()
- if (p.player.openContainer != null && p.player.openContainer.windowId == windowId) {
- p.player.openContainer match {
+ val containerId = p.readInt()
+ if (p.player.containerMenu != null && p.player.containerMenu.containerId == containerId) {
+ p.player.containerMenu match {
case container: container.Player => container.updateCustomData(p.readNBT())
case _ => // Invalid packet.
}
@@ -191,7 +195,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onDisassemblerActiveChange(p: PacketParser): Unit =
- p.readTileEntity[Disassembler]() match {
+ p.readBlockEntity[Disassembler]() match {
case Some(t) => t.isActive = p.readBoolean()
case _ => // Invalid packet.
}
@@ -199,12 +203,12 @@ object PacketHandler extends CommonPacketHandler {
def onFileSystemActivity(p: PacketParser): AnyVal = {
val sound = p.readUTF()
val data = CompressedStreamTools.read(p)
- if (p.readBoolean()) p.readTileEntity[net.minecraft.tileentity.TileEntity]() match {
+ if (p.readBoolean()) p.readBlockEntity[net.minecraft.tileentity.TileEntity]() match {
case Some(t) =>
MinecraftForge.EVENT_BUS.post(new FileSystemAccessEvent.Client(sound, t, data))
case _ => // Invalid packet.
}
- else world(p.player, p.readInt()) match {
+ else world(p.player, new ResourceLocation(p.readUTF())) match {
case Some(world) =>
val x = p.readDouble()
val y = p.readDouble()
@@ -216,12 +220,12 @@ object PacketHandler extends CommonPacketHandler {
def onNetworkActivity(p: PacketParser): AnyVal = {
val data = CompressedStreamTools.read(p)
- if (p.readBoolean()) p.readTileEntity[net.minecraft.tileentity.TileEntity]() match {
+ if (p.readBoolean()) p.readBlockEntity[net.minecraft.tileentity.TileEntity]() match {
case Some(t) =>
MinecraftForge.EVENT_BUS.post(new NetworkActivityEvent.Client(t, data))
case _ => // Invalid packet.
}
- else world(p.player, p.readInt()) match {
+ else world(p.player, new ResourceLocation(p.readUTF())) match {
case Some(world) =>
val x = p.readDouble()
val y = p.readDouble()
@@ -232,13 +236,13 @@ object PacketHandler extends CommonPacketHandler {
}
def onFloppyChange(p: PacketParser): Unit =
- p.readTileEntity[DiskDrive]() match {
- case Some(t) => t.setInventorySlotContents(0, p.readItemStack())
+ p.readBlockEntity[DiskDrive]() match {
+ case Some(t) => t.setItem(0, p.readItemStack())
case _ => // Invalid packet.
}
def onHologramClear(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
for (i <- t.volume.indices) t.volume(i) = 0
t.needsRendering = true
@@ -246,7 +250,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onHologramColor(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
val index = p.readInt()
val value = p.readInt()
@@ -256,20 +260,20 @@ object PacketHandler extends CommonPacketHandler {
}
def onHologramPowerChange(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) => t.hasPower = p.readBoolean()
case _ => // Invalid packet.
}
def onHologramScale(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
t.scale = p.readDouble()
case _ => // Invalid packet.
}
def onHologramArea(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
val fromX = p.readByte(): Int
val untilX = p.readByte(): Int
@@ -286,7 +290,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onHologramValues(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
val count = p.readInt()
for (i <- 0 until count) {
@@ -301,17 +305,17 @@ object PacketHandler extends CommonPacketHandler {
}
def onHologramPositionOffsetY(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
val x = p.readDouble()
val y = p.readDouble()
val z = p.readDouble()
- t.translation = new Vec3d(x, y, z)
+ t.translation = new Vector3d(x, y, z)
case _ => // Invalid packet.
}
def onHologramRotation(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
t.rotationAngle = p.readFloat()
t.rotationX = p.readFloat()
@@ -321,7 +325,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onHologramRotationSpeed(p: PacketParser): Unit =
- p.readTileEntity[Hologram]() match {
+ p.readBlockEntity[Hologram]() match {
case Some(t) =>
t.rotationSpeed = p.readFloat()
t.rotationSpeedX = p.readFloat()
@@ -336,15 +340,10 @@ object PacketHandler extends CommonPacketHandler {
Loot.disksForClient += stack
}
if(Mods.JustEnoughItems.isModAvailable) {
- addDiskToJEI(stack)
+ ModJEI.addDiskAtRuntime(stack)
}
}
- @Optional.Method(modid = Mods.IDs.JustEnoughItems)
- private def addDiskToJEI(stack: ItemStack): Unit = {
- ModJEI.addDiskAtRuntime(stack)
- }
-
def onCyclingDisk(p: PacketParser): Any = {
val stack = p.readItemStack()
if (!stack.isEmpty) {
@@ -353,12 +352,12 @@ object PacketHandler extends CommonPacketHandler {
}
def onNanomachinesConfiguration(p: PacketParser): Unit = {
- p.readEntity[EntityPlayer]() match {
+ p.readEntity[PlayerEntity]() match {
case Some(player) =>
val hasController = p.readBoolean()
if (hasController) {
api.Nanomachines.installController(player) match {
- case controller: ControllerImpl => controller.load(p.readNBT())
+ case controller: ControllerImpl => controller.loadData(p.readNBT())
case _ => // Wat.
}
}
@@ -370,7 +369,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onNanomachinesInputs(p: PacketParser): Unit = {
- p.readEntity[EntityPlayer]() match {
+ p.readEntity[PlayerEntity]() match {
case Some(player) => api.Nanomachines.getController(player) match {
case controller: ControllerImpl =>
val inputs = new Array[Byte](p.readInt())
@@ -388,7 +387,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onNanomachinesPower(p: PacketParser): Unit = {
- p.readEntity[EntityPlayer]() match {
+ p.readEntity[PlayerEntity]() match {
case Some(player) => api.Nanomachines.getController(player) match {
case controller: ControllerImpl => controller.storedEnergy = p.readDouble()
case _ => // Wat.
@@ -398,45 +397,47 @@ object PacketHandler extends CommonPacketHandler {
}
def onNetSplitterState(p: PacketParser): Unit =
- p.readTileEntity[NetSplitter]() match {
+ p.readBlockEntity[NetSplitter]() match {
case Some(t) =>
t.isInverted = p.readBoolean()
t.openSides = t.uncompressSides(p.readByte())
- t.world.notifyBlockUpdate(t.getPos)
+ t.world.notifyBlockUpdate(t.getBlockPos)
case _ => // Invalid packet.
}
def onParticleEffect(p: PacketParser): Unit = {
- val dimension = p.readInt()
- world(p.player, dimension) match {
+ world(p.player, new ResourceLocation(p.readUTF())) match {
case Some(world) =>
val x = p.readInt()
val y = p.readInt()
val z = p.readInt()
val velocity = p.readDouble()
val direction = p.readDirection()
- val particleType = EnumParticleTypes.getParticleFromId(p.readInt())
- val count = p.readUnsignedByte()
-
- for (i <- 0 until count) {
- def rv(f: EnumFacing => Int) = direction match {
- case Some(d) => world.rand.nextFloat - 0.5 + f(d) * 0.5
- case _ => world.rand.nextFloat * 2.0 - 1
- }
-
- val vx = rv(_.getFrontOffsetX)
- val vy = rv(_.getFrontOffsetY)
- val vz = rv(_.getFrontOffsetZ)
- if (vx * vx + vy * vy + vz * vz < 1) {
- def rp(x: Int, v: Double, f: EnumFacing => Int) = direction match {
- case Some(d) => x + 0.5 + v * velocity * 0.5 + f(d) * velocity
- case _ => x + 0.5 + v * velocity
+ val particleType = p.readRegistryEntry(ForgeRegistries.PARTICLE_TYPES)
+ if (particleType.isInstanceOf[IParticleData]) {
+ val particle = particleType.asInstanceOf[IParticleData]
+ val count = p.readUnsignedByte()
+
+ for (i <- 0 until count) {
+ def rv(f: Direction => Int) = direction match {
+ case Some(d) => world.random.nextFloat - 0.5 + f(d) * 0.5
+ case _ => world.random.nextFloat * 2.0 - 1
}
- val px = rp(x, vx, _.getFrontOffsetX)
- val py = rp(y, vy, _.getFrontOffsetY)
- val pz = rp(z, vz, _.getFrontOffsetZ)
- world.spawnParticle(particleType, px, py, pz, vx, vy + velocity * 0.25, vz)
+ val vx = rv(_.getStepX)
+ val vy = rv(_.getStepY)
+ val vz = rv(_.getStepZ)
+ if (vx * vx + vy * vy + vz * vz < 1) {
+ def rp(x: Int, v: Double, f: Direction => Int) = direction match {
+ case Some(d) => x + 0.5 + v * velocity * 0.5 + f(d) * velocity
+ case _ => x + 0.5 + v * velocity
+ }
+
+ val px = rp(x, vx, _.getStepX)
+ val py = rp(y, vy, _.getStepY)
+ val pz = rp(z, vz, _.getStepZ)
+ world.addParticle(particle, px, py, pz, vx, vy + velocity * 0.25, vz)
+ }
}
}
case _ => // Invalid packet.
@@ -447,7 +448,7 @@ object PacketHandler extends CommonPacketHandler {
if (!PetRenderer.isInitialized) {
PetRenderer.isInitialized = true
if (Settings.get.hideOwnPet) {
- PetRenderer.hidden += Minecraft.getMinecraft.player.getName
+ PetRenderer.hidden += Minecraft.getInstance.player.getName.getString
}
PacketSender.sendPetVisibility()
}
@@ -465,7 +466,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onPowerState(p: PacketParser): Unit =
- p.readTileEntity[PowerInformation]() match {
+ p.readBlockEntity[PowerInformation]() match {
case Some(t) =>
t.globalBuffer = p.readDouble()
t.globalBufferSize = p.readDouble()
@@ -473,7 +474,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onPrinterState(p: PacketParser): Unit =
- p.readTileEntity[Printer]() match {
+ p.readBlockEntity[Printer]() match {
case Some(t) =>
if (p.readBoolean()) t.requiredEnergy = 9001
else t.requiredEnergy = 0
@@ -481,58 +482,58 @@ object PacketHandler extends CommonPacketHandler {
}
def onRackInventory(p: PacketParser): Unit =
- p.readTileEntity[Rack]() match {
+ p.readBlockEntity[Rack]() match {
case Some(t) =>
val count = p.readInt()
for (_ <- 0 until count) {
val slot = p.readInt()
- t.setInventorySlotContents(slot, p.readItemStack())
+ t.setItem(slot, p.readItemStack())
}
case _ => // Invalid packet.
}
def onRackMountableData(p: PacketParser): Unit =
- p.readTileEntity[Rack]() match {
+ p.readBlockEntity[Rack]() match {
case Some(t) =>
val mountableIndex = p.readInt()
t.lastData(mountableIndex) = p.readNBT()
- t.getWorld.notifyBlockUpdate(t.getPos)
+ t.getLevel.notifyBlockUpdate(t.getBlockPos)
case _ => // Invalid packet.
}
def onRaidStateChange(p: PacketParser): Unit =
- p.readTileEntity[Raid]() match {
+ p.readBlockEntity[Raid]() match {
case Some(t) =>
- for (slot <- 0 until t.getSizeInventory) {
+ for (slot <- 0 until t.getContainerSize) {
t.presence(slot) = p.readBoolean()
}
case _ => // Invalid packet.
}
def onRedstoneState(p: PacketParser): Unit =
- p.readTileEntity[RedstoneAware]() match {
+ p.readBlockEntity[RedstoneAware]() match {
case Some(t) =>
t.setOutputEnabled(p.readBoolean())
- for (d <- EnumFacing.values) {
+ for (d <- Direction.values) {
t.setOutput(d, p.readByte())
}
case _ => // Invalid packet.
}
def onRobotAnimateSwing(p: PacketParser): Unit =
- p.readTileEntity[RobotProxy]() match {
+ p.readBlockEntity[RobotProxy]() match {
case Some(t) => t.robot.setAnimateSwing(p.readInt())
case _ => // Invalid packet.
}
def onRobotAnimateTurn(p: PacketParser): Unit =
- p.readTileEntity[RobotProxy]() match {
+ p.readBlockEntity[RobotProxy]() match {
case Some(t) => t.robot.setAnimateTurn(p.readByte(), p.readInt())
case _ => // Invalid packet.
}
def onRobotAssemblingState(p: PacketParser): Unit =
- p.readTileEntity[Assembler]() match {
+ p.readBlockEntity[Assembler]() match {
case Some(t) =>
if (p.readBoolean()) t.requiredEnergy = 9001
else t.requiredEnergy = 0
@@ -540,26 +541,26 @@ object PacketHandler extends CommonPacketHandler {
}
def onRobotInventoryChange(p: PacketParser): Unit =
- p.readTileEntity[RobotProxy]() match {
+ p.readBlockEntity[RobotProxy]() match {
case Some(t) =>
val robot = t.robot
val slot = p.readInt()
val stack = p.readItemStack()
- if (slot >= robot.getSizeInventory - robot.componentCount) {
- robot.info.components(slot - (robot.getSizeInventory - robot.componentCount)) = stack
+ if (slot >= robot.getContainerSize - robot.componentCount) {
+ robot.info.components(slot - (robot.getContainerSize - robot.componentCount)) = stack
}
- else t.robot.setInventorySlotContents(slot, stack)
+ else t.robot.setItem(slot, stack)
case _ => // Invalid packet.
}
def onRobotLightChange(p: PacketParser): Unit =
- p.readTileEntity[RobotProxy]() match {
+ p.readBlockEntity[RobotProxy]() match {
case Some(t) => t.robot.info.lightColor = p.readInt()
case _ => // Invalid packet.
}
def onRobotNameChange(p: PacketParser) = {
- p.readTileEntity[RobotProxy]() match {
+ p.readBlockEntity[RobotProxy]() match {
case Some(t) => {
val len = p.readShort()
val name = new Array[Char](len)
@@ -573,28 +574,28 @@ object PacketHandler extends CommonPacketHandler {
}
def onRobotMove(p: PacketParser): AnyVal = {
- val dimension = p.readInt()
+ val dimension = new ResourceLocation(p.readUTF())
val x = p.readInt()
val y = p.readInt()
val z = p.readInt()
val direction = p.readDirection()
- (p.getTileEntity[RobotProxy](dimension, x, y, z), direction) match {
+ (p.getBlockEntity[RobotProxy](dimension, x, y, z), direction) match {
case (Some(t), Some(d)) => t.robot.move(d)
case (_, Some(d)) =>
// Invalid packet, robot may be coming from outside our loaded area.
- PacketSender.sendRobotStateRequest(dimension, x + d.getFrontOffsetX, y + d.getFrontOffsetY, z + d.getFrontOffsetZ)
+ PacketSender.sendRobotStateRequest(dimension, x + d.getStepX, y + d.getStepY, z + d.getStepZ)
case _ => // Invalid packet.
}
}
def onRobotSelectedSlotChange(p: PacketParser): Unit =
- p.readTileEntity[RobotProxy]() match {
+ p.readBlockEntity[RobotProxy]() match {
case Some(t) => t.robot.selectedSlot = p.readInt()
case _ => // Invalid packet.
}
def onRotatableState(p: PacketParser): Unit =
- p.readTileEntity[Rotatable]() match {
+ p.readBlockEntity[Rotatable]() match {
case Some(t) =>
t.pitch = p.readDirection().get
t.yaw = p.readDirection().get
@@ -602,41 +603,41 @@ object PacketHandler extends CommonPacketHandler {
}
def onSwitchActivity(p: PacketParser): Unit =
- p.readTileEntity[Relay]() match {
+ p.readBlockEntity[Relay]() match {
case Some(t) => t.lastMessage = System.currentTimeMillis()
case _ => // Invalid packet.
}
def onTextBufferPowerChange(p: PacketParser): Unit =
- ComponentTracker.get(p.player.getEntityWorld, p.readUTF()) match {
+ ComponentTracker.get(p.player.level, p.readUTF()) match {
case Some(buffer: api.internal.TextBuffer) =>
buffer.setRenderingEnabled(p.readBoolean())
case _ => // Invalid packet.
}
def onTextBufferInit(p: PacketParser) {
- ComponentTracker.get(p.player.getEntityWorld, p.readUTF()) match {
+ ComponentTracker.get(p.player.level, p.readUTF()) match {
case Some(buffer: li.cil.oc.common.component.TextBuffer) =>
val nbt = p.readNBT()
- if (nbt.hasKey("maxWidth")) {
- val maxWidth = nbt.getInteger("maxWidth")
- val maxHeight = nbt.getInteger("maxHeight")
+ if (nbt.contains("maxWidth")) {
+ val maxWidth = nbt.getInt("maxWidth")
+ val maxHeight = nbt.getInt("maxHeight")
buffer.setMaximumResolution(maxWidth, maxHeight)
}
- buffer.data.load(nbt)
- if (nbt.hasKey("viewportWidth")) {
- val viewportWidth = nbt.getInteger("viewportWidth")
- val viewportHeight = nbt.getInteger("viewportHeight")
+ buffer.data.loadData(nbt)
+ if (nbt.contains("viewportWidth")) {
+ val viewportWidth = nbt.getInt("viewportWidth")
+ val viewportHeight = nbt.getInt("viewportHeight")
buffer.setViewport(viewportWidth, viewportHeight)
}
- buffer.proxy.markDirty()
+ buffer.proxy.setChanged()
buffer.markInitialized()
case _ => // Invalid packet.
}
}
def onTextBufferMulti(p: PacketParser): Unit =
- if (p.player != null) ComponentTracker.get(p.player.getEntityWorld, p.readUTF()) match {
+ if (p.player != null) ComponentTracker.get(p.player.level, p.readUTF()) match {
case Some(buffer: api.internal.TextBuffer) =>
try while (true) {
p.readPacketType() match {
@@ -815,14 +816,13 @@ object PacketHandler extends CommonPacketHandler {
}
def onScreenTouchMode(p: PacketParser): Unit =
- p.readTileEntity[Screen]() match {
+ p.readBlockEntity[Screen]() match {
case Some(t) => t.invertTouchMode = p.readBoolean()
case _ => // Invalid packet.
}
def onSoundEffect(p: PacketParser) {
- val dimension = p.readInt()
- world(p.player, dimension) match {
+ world(p.player, new ResourceLocation(p.readUTF())) match {
case Some(world) =>
val x = p.readDouble()
val y = p.readDouble()
@@ -836,8 +836,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onSound(p: PacketParser) {
- val dimension = p.readInt()
- if (world(p.player, dimension).isDefined) {
+ if (world(p.player, new ResourceLocation(p.readUTF())).isDefined) {
val x = p.readInt()
val y = p.readInt()
val z = p.readInt()
@@ -848,8 +847,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onSoundPattern(p: PacketParser) {
- val dimension = p.readInt()
- if (world(p.player, dimension).isDefined) {
+ if (world(p.player, new ResourceLocation(p.readUTF())).isDefined) {
val x = p.readInt()
val y = p.readInt()
val z = p.readInt()
@@ -859,14 +857,16 @@ object PacketHandler extends CommonPacketHandler {
}
def onTransposerActivity(p: PacketParser): Unit =
- p.readTileEntity[Transposer]() match {
+ p.readBlockEntity[Transposer]() match {
case Some(transposer) => transposer.lastOperation = System.currentTimeMillis()
case _ => // Invalid packet.
}
def onWaypointLabel(p: PacketParser): Unit =
- p.readTileEntity[Waypoint]() match {
+ p.readBlockEntity[Waypoint]() match {
case Some(waypoint) => waypoint.label = p.readUTF()
case _ => // Invalid packet.
}
+
+ protected override def createParser(stream: InputStream, player: PlayerEntity) = new PacketParser(stream, Minecraft.getInstance.player)
}
diff --git a/src/main/scala/li/cil/oc/client/PacketSender.scala b/src/main/scala/li/cil/oc/client/PacketSender.scala
index 90f2351d6b..6e530ddb07 100644
--- a/src/main/scala/li/cil/oc/client/PacketSender.scala
+++ b/src/main/scala/li/cil/oc/client/PacketSender.scala
@@ -4,28 +4,37 @@ import li.cil.oc.Settings
import li.cil.oc.common.CompressedPacketBuilder
import li.cil.oc.common.PacketType
import li.cil.oc.common.SimplePacketBuilder
+import li.cil.oc.common.container
import li.cil.oc.common.entity.Drone
import li.cil.oc.common.tileentity._
import li.cil.oc.common.tileentity.traits.Computer
import net.minecraft.client.Minecraft
-import net.minecraft.client.audio.PositionedSoundRecord
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.init.SoundEvents
+import net.minecraft.client.audio.SimpleSound
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.util.SoundEvents
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
+import net.minecraft.util.ResourceLocation
import net.minecraft.util.SoundCategory
-import scala.tools.nsc.doc.model.Entity
-
object PacketSender {
// Timestamp after which the next clipboard message may be sent. Used to
// avoid spamming large packets on key repeat.
protected var clipboardCooldown = 0L
- def sendComputerPower(t: Computer, power: Boolean) {
+ def sendComputerPower(computer: container.Case, power: Boolean) {
val pb = new SimplePacketBuilder(PacketType.ComputerPower)
- pb.writeTileEntity(t)
+ pb.writeInt(computer.containerId)
+ pb.writeBoolean(power)
+
+ pb.sendToServer()
+ }
+
+ def sendRobotPower(robot: container.Robot, power: Boolean) {
+ val pb = new SimplePacketBuilder(PacketType.ComputerPower)
+
+ pb.writeInt(robot.containerId)
pb.writeBoolean(power)
pb.sendToServer()
@@ -45,10 +54,10 @@ object PacketSender {
pb.sendToServer()
}
- def sendDronePower(e: Drone, power: Boolean) {
+ def sendDronePower(drone: container.Drone, power: Boolean) {
val pb = new SimplePacketBuilder(PacketType.DronePower)
- pb.writeEntity(e)
+ pb.writeInt(drone.containerId)
pb.writeBoolean(power)
pb.sendToServer()
@@ -74,12 +83,20 @@ object PacketSender {
pb.sendToServer()
}
+ def sendTextInput(address: String, codePt: Int) {
+ val pb = new SimplePacketBuilder(PacketType.TextInput)
+
+ pb.writeUTF(address)
+ pb.writeInt(codePt)
+
+ pb.sendToServer()
+ }
+
def sendClipboard(address: String, value: String) {
if (value != null && !value.isEmpty) {
if (value.length > 64 * 1024 || System.currentTimeMillis() < clipboardCooldown) {
- val player = Minecraft.getMinecraft.player
- val handler = Minecraft.getMinecraft.getSoundHandler
- handler.playSound(new PositionedSoundRecord(SoundEvents.BLOCK_NOTE_HARP, SoundCategory.MASTER, 1, 1, player.posX.toFloat, player.posY.toFloat, player.posZ.toFloat))
+ val handler = Minecraft.getInstance.getSoundManager
+ handler.play(SimpleSound.forUI(SoundEvents.NOTE_BLOCK_HARP, 1, 1))
}
else {
clipboardCooldown = System.currentTimeMillis() + value.length / 10
@@ -159,10 +176,10 @@ object PacketSender {
pb.sendToServer()
}
- def sendRackMountableMapping(t: Rack, mountableIndex: Int, nodeIndex: Int, side: Option[EnumFacing]) {
+ def sendRackMountableMapping(rack: container.Rack, mountableIndex: Int, nodeIndex: Int, side: Option[Direction]) {
val pb = new SimplePacketBuilder(PacketType.RackMountableMapping)
- pb.writeTileEntity(t)
+ pb.writeInt(rack.containerId)
pb.writeInt(mountableIndex)
pb.writeInt(nodeIndex)
pb.writeDirection(side)
@@ -170,27 +187,27 @@ object PacketSender {
pb.sendToServer()
}
- def sendRackRelayState(t: Rack, enabled: Boolean) {
+ def sendRackRelayState(rack: container.Rack, enabled: Boolean) {
val pb = new SimplePacketBuilder(PacketType.RackRelayState)
- pb.writeTileEntity(t)
+ pb.writeInt(rack.containerId)
pb.writeBoolean(enabled)
pb.sendToServer()
}
- def sendRobotAssemblerStart(t: Assembler) {
+ def sendRobotAssemblerStart(assembler: container.Assembler) {
val pb = new SimplePacketBuilder(PacketType.RobotAssemblerStart)
- pb.writeTileEntity(t)
+ pb.writeInt(assembler.containerId)
pb.sendToServer()
}
- def sendRobotStateRequest(dimension: Int, x: Int, y: Int, z: Int) {
+ def sendRobotStateRequest(dimension: ResourceLocation, x: Int, y: Int, z: Int) {
val pb = new SimplePacketBuilder(PacketType.RobotStateRequest)
- pb.writeInt(dimension)
+ pb.writeUTF(dimension.toString)
pb.writeInt(x)
pb.writeInt(y)
pb.writeInt(z)
@@ -198,10 +215,10 @@ object PacketSender {
pb.sendToServer()
}
- def sendServerPower(t: Rack, mountableIndex: Int, power: Boolean) {
+ def sendServerPower(server: container.Server, mountableIndex: Int, power: Boolean) {
val pb = new SimplePacketBuilder(PacketType.ServerPower)
- pb.writeTileEntity(t)
+ pb.writeInt(server.containerId)
pb.writeInt(mountableIndex)
pb.writeBoolean(power)
diff --git a/src/main/scala/li/cil/oc/client/Proxy.scala b/src/main/scala/li/cil/oc/client/Proxy.scala
index c8a912dbeb..41a4cb75fc 100644
--- a/src/main/scala/li/cil/oc/client/Proxy.scala
+++ b/src/main/scala/li/cil/oc/client/Proxy.scala
@@ -1,8 +1,11 @@
package li.cil.oc.client
+import com.mojang.blaze3d.systems.IRenderCall
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.client
+import li.cil.oc.client.gui.GuiTypes
import li.cil.oc.client.renderer.HighlightRenderer
import li.cil.oc.client.renderer.MFUTargetRenderer
import li.cil.oc.client.renderer.PetRenderer
@@ -12,91 +15,91 @@ import li.cil.oc.client.renderer.block.ModelInitialization
import li.cil.oc.client.renderer.block.NetSplitterModel
import li.cil.oc.client.renderer.entity.DroneRenderer
import li.cil.oc.client.renderer.tileentity._
+import li.cil.oc.common
+import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
+import li.cil.oc.common.{Proxy => CommonProxy}
import li.cil.oc.common.component.TextBuffer
import li.cil.oc.common.entity.Drone
+import li.cil.oc.common.entity.EntityTypes
import li.cil.oc.common.event.NanomachinesHandler
import li.cil.oc.common.event.RackMountableRenderHandler
-import li.cil.oc.common.item.traits.Delegate
import li.cil.oc.common.tileentity
-import li.cil.oc.common.{Proxy => CommonProxy}
import li.cil.oc.util.Audio
import net.minecraft.block.Block
+import net.minecraft.client.Minecraft
+import net.minecraft.client.entity.player.ClientPlayerEntity
+import net.minecraft.client.gui.screen.Screen
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.Item
+import net.minecraft.world.World
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.client.registry.ClientRegistry
import net.minecraftforge.fml.client.registry.RenderingRegistry
-import net.minecraftforge.fml.common.event.FMLInitializationEvent
-import net.minecraftforge.fml.common.event.FMLPreInitializationEvent
-import net.minecraftforge.fml.common.network.NetworkRegistry
-import org.lwjgl.opengl.GLContext
+import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
+import net.minecraftforge.fml.network.NetworkRegistry
private[oc] class Proxy extends CommonProxy {
- override def preInit(e: FMLPreInitializationEvent) {
- super.preInit(e)
-
- api.API.manual = client.Manual
+ modBus.register(classOf[GuiTypes])
+ modBus.register(ModelInitialization)
+ modBus.register(NetSplitterModel)
+ modBus.register(Textures)
- CommandHandler.register()
+ override def preInit() {
+ super.preInit()
- MinecraftForge.EVENT_BUS.register(Textures)
- MinecraftForge.EVENT_BUS.register(NetSplitterModel)
-
- ModelInitialization.preInit()
+ api.API.manual = client.Manual
}
- override def init(e: FMLInitializationEvent) {
+ override def init(e: FMLCommonSetupEvent) {
super.init(e)
- OpenComputers.channel.register(client.PacketHandler)
-
- ColorHandler.init()
-
- RenderingRegistry.registerEntityRenderingHandler(classOf[Drone], DroneRenderer)
-
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Adapter], AdapterRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Assembler], AssemblerRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Case], CaseRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Charger], ChargerRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Disassembler], DisassemblerRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.DiskDrive], DiskDriveRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Geolyzer], GeolyzerRenderer)
- if (GLContext.getCapabilities.OpenGL15)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRenderer)
- else
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRendererFallback)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Microcontroller], MicrocontrollerRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.NetSplitter], NetSplitterRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Printer], PrinterRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Rack], RackRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Relay], RelayRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.RobotProxy], RobotRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer)
- ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Transposer], TransposerRenderer)
-
- ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)
-
- MinecraftForge.EVENT_BUS.register(HighlightRenderer)
- MinecraftForge.EVENT_BUS.register(NanomachinesHandler.Client)
- MinecraftForge.EVENT_BUS.register(PetRenderer)
- MinecraftForge.EVENT_BUS.register(RackMountableRenderHandler)
- MinecraftForge.EVENT_BUS.register(Sound)
- MinecraftForge.EVENT_BUS.register(TextBuffer)
- MinecraftForge.EVENT_BUS.register(MFUTargetRenderer)
- MinecraftForge.EVENT_BUS.register(WirelessNetworkDebugRenderer)
-
- NetworkRegistry.INSTANCE.registerGuiHandler(OpenComputers, GuiHandler)
-
- MinecraftForge.EVENT_BUS.register(Audio)
- MinecraftForge.EVENT_BUS.register(HologramRenderer)
- MinecraftForge.EVENT_BUS.register(PetRenderer)
- MinecraftForge.EVENT_BUS.register(Sound)
- MinecraftForge.EVENT_BUS.register(TextBufferRenderCache)
+ CommonPacketHandler.clientHandler = PacketHandler
+
+ e.enqueueWork((() => {
+ ModelInitialization.preInit()
+
+ ColorHandler.init()
+
+ RenderingRegistry.registerEntityRenderingHandler(EntityTypes.DRONE, DroneRenderer)
+
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.ADAPTER, AdapterRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.ASSEMBLER, AssemblerRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.CASE, CaseRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.CHARGER, ChargerRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.DISASSEMBLER, DisassemblerRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.DISK_DRIVE, DiskDriveRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.GEOLYZER, GeolyzerRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.HOLOGRAM, HologramRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.MICROCONTROLLER, MicrocontrollerRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.NET_SPLITTER, NetSplitterRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.POWER_DISTRIBUTOR, PowerDistributorRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.PRINTER, PrinterRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.RAID, RaidRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.RACK, RackRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.RELAY, RelayRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.ROBOT, RobotRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.SCREEN, ScreenRenderer)
+ ClientRegistry.bindTileEntityRenderer(tileentity.TileEntityTypes.TRANSPOSER, TransposerRenderer)
+
+ ClientRegistry.registerKeyBinding(KeyBindings.extendedTooltip)
+ ClientRegistry.registerKeyBinding(KeyBindings.analyzeCopyAddr)
+ ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)
+
+ MinecraftForge.EVENT_BUS.register(HighlightRenderer)
+ MinecraftForge.EVENT_BUS.register(NanomachinesHandler.Client)
+ MinecraftForge.EVENT_BUS.register(PetRenderer)
+ MinecraftForge.EVENT_BUS.register(RackMountableRenderHandler)
+ MinecraftForge.EVENT_BUS.register(Sound)
+ MinecraftForge.EVENT_BUS.register(TextBuffer)
+ MinecraftForge.EVENT_BUS.register(MFUTargetRenderer)
+ MinecraftForge.EVENT_BUS.register(WirelessNetworkDebugRenderer)
+ MinecraftForge.EVENT_BUS.register(Audio)
+ MinecraftForge.EVENT_BUS.register(HologramRenderer)
+ }): Runnable)
+
+ RenderSystem.recordRenderCall(() => MinecraftForge.EVENT_BUS.register(TextBufferRenderCache))
}
- override def registerModel(instance: Delegate, id: String): Unit = ModelInitialization.registerModel(instance, id)
-
override def registerModel(instance: Item, id: String): Unit = ModelInitialization.registerModel(instance, id)
override def registerModel(instance: Block, id: String): Unit = ModelInitialization.registerModel(instance, id)
diff --git a/src/main/scala/li/cil/oc/client/Sound.scala b/src/main/scala/li/cil/oc/client/Sound.scala
index e578d1cddb..8e123e9ce3 100644
--- a/src/main/scala/li/cil/oc/client/Sound.scala
+++ b/src/main/scala/li/cil/oc/client/Sound.scala
@@ -12,71 +12,34 @@ import com.google.common.base.Charsets
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import net.minecraft.client.Minecraft
-import net.minecraft.client.audio.SoundManager
-import net.minecraft.server.integrated.IntegratedServer
+import net.minecraft.client.audio.ITickableSound
+import net.minecraft.client.audio.LocatableSound
+import net.minecraft.client.audio.SoundEngine
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ResourceLocation
import net.minecraft.util.SoundCategory
-import net.minecraftforge.client.event.sound.SoundLoadEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.event.TickEvent.ClientTickEvent
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.client.FMLClientHandler
-import net.minecraftforge.fml.common.FMLCommonHandler
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
-import paulscode.sound.SoundSystemConfig
import scala.collection.mutable
-import scala.io.Source
object Sound {
private val sources = mutable.Map.empty[TileEntity, PseudoLoopingStream]
private val commandQueue = mutable.PriorityQueue.empty[Command]
- private var lastVolume = FMLClientHandler.instance.getClient.gameSettings.getSoundLevel(SoundCategory.BLOCKS)
-
private val updateTimer = new Timer("OpenComputers-SoundUpdater", true)
if (Settings.get.soundVolume > 0) {
updateTimer.scheduleAtFixedRate(new TimerTask {
override def run() {
- sources.synchronized(updateCallable = Some(() => {
- updateVolume()
- processQueue()
- }))
+ sources.synchronized(Sound.updateCallable = Some(() => processQueue()))
}
}, 500, 50)
}
private var updateCallable = None: Option[() => Unit]
- // Set in init event.
- var manager: SoundManager = _
-
- def soundSystem = if (manager != null) manager.sndSystem else null
-
- private def updateVolume() {
- val volume =
- if (isGamePaused) 0f
- else FMLClientHandler.instance.getClient.gameSettings.getSoundLevel(SoundCategory.BLOCKS)
- if (volume != lastVolume) {
- lastVolume = volume
- sources.synchronized {
- for (sound <- sources.values) {
- sound.updateVolume()
- }
- }
- }
- }
-
- private def isGamePaused = {
- val server = FMLCommonHandler.instance.getMinecraftServerInstance
- // Check outside of match to avoid client side class access.
- server != null && !server.isDedicatedServer && (server match {
- case integrated: IntegratedServer => Minecraft.getMinecraft.isGamePaused
- case _ => false
- })
- }
-
private def processQueue() {
if (commandQueue.nonEmpty) {
commandQueue.synchronized {
@@ -113,42 +76,11 @@ object Sound {
}
}
- @SubscribeEvent
- def onSoundLoad(event: SoundLoadEvent) {
- manager = event.getManager
- }
-
- private var hasPreloaded = Settings.get.soundVolume <= 0
-
@SubscribeEvent
def onTick(e: ClientTickEvent) {
- if (soundSystem != null) {
- if (!hasPreloaded) {
- hasPreloaded = true
- new Thread(new Runnable() {
- override def run(): Unit = {
- val preloadConfigLocation = new ResourceLocation(Settings.resourceDomain, "sounds/preload.cfg")
- val preloadConfigResource = Minecraft.getMinecraft.getResourceManager.getResource(preloadConfigLocation)
- for (location <- Source.fromInputStream(preloadConfigResource.getInputStream)(Charsets.UTF_8).getLines()) {
- val url = getClass.getClassLoader.getResource(location)
- if (url != null) try {
- val sourceName = "preload_" + location
- soundSystem.newSource(false, sourceName, url, location, true, 0, 0, 0, SoundSystemConfig.ATTENUATION_NONE, 16)
- soundSystem.activate(sourceName)
- soundSystem.removeSource(sourceName)
- } catch {
- case _: Throwable => // Meh.
- }
- else OpenComputers.log.warn(s"Couldn't preload sound $location!")
- }
- }
- })
- }
-
- sources.synchronized {
- updateCallable.foreach(_ ())
- updateCallable = None
- }
+ sources.synchronized {
+ updateCallable.foreach(_ ())
+ updateCallable = None
}
}
@@ -170,7 +102,11 @@ object Sound {
private class StartCommand(when: Long, tileEntity: TileEntity, val name: String, val volume: Float) extends Command(when, tileEntity) {
override def apply() {
sources.synchronized {
- sources.getOrElseUpdate(tileEntity, new PseudoLoopingStream(tileEntity, volume)).play(name)
+ val current = sources.getOrElse(tileEntity, null)
+ if (current == null || !current.getLocation.getPath.equals(name)) {
+ if (current != null) current.stop()
+ sources(tileEntity) = new PseudoLoopingStream(tileEntity, volume, name)
+ }
}
}
}
@@ -203,65 +139,34 @@ object Sound {
}
}
- private class PseudoLoopingStream(val tileEntity: TileEntity, val volume: Float, val source: String = UUID.randomUUID.toString) {
- var initialized = false
+ private class PseudoLoopingStream(val tileEntity: TileEntity, val subVolume: Float, name: String)
+ extends LocatableSound(new ResourceLocation(OpenComputers.ID, name), SoundCategory.BLOCKS) with ITickableSound {
- def updateVolume() {
- soundSystem.setVolume(source, lastVolume * volume * Settings.get.soundVolume)
- }
+ var stopped = false
+ volume = subVolume * Settings.get.soundVolume
+ relative = tileEntity != null
+ looping = true
+ updatePosition()
def updatePosition() {
- if (tileEntity != null) soundSystem.setPosition(source, tileEntity.getPos.getX, tileEntity.getPos.getY, tileEntity.getPos.getZ)
- else soundSystem.setPosition(source, 0, 0, 0)
- }
-
- def play(name: String) {
- val resourceName = s"${Settings.resourceDomain}:$name"
- val sound = manager.sndHandler.getAccessor(new ResourceLocation(resourceName))
- // Specified return type because apparently this is ambiguous according to Jenkins. I don't even.
- val resource = (sound.cloneEntry(): net.minecraft.client.audio.Sound).getSoundAsOggLocation
- if (!initialized) {
- initialized = true
- if (tileEntity != null) soundSystem.newSource(false, source, toUrl(resource), resource.toString, true, tileEntity.getPos.getX, tileEntity.getPos.getY, tileEntity.getPos.getZ, SoundSystemConfig.ATTENUATION_LINEAR, 16)
- else soundSystem.newSource(false, source, toUrl(resource), resource.toString, false, 0, 0, 0, SoundSystemConfig.ATTENUATION_NONE, 0)
- updateVolume()
- soundSystem.activate(source)
+ if (tileEntity != null) {
+ val pos = tileEntity.getBlockPos
+ x = pos.getX + 0.5
+ y = pos.getY + 0.5
+ z = pos.getZ + 0.5
}
- soundSystem.play(source)
}
- def stop() {
- if (soundSystem != null) try {
- soundSystem.stop(source)
- soundSystem.removeSource(source)
- }
- catch {
- case _: Throwable =>
- }
- }
- }
+ override def canStartSilent() = true
- // This is copied from SoundManager.getURLForSoundResource, which is private.
- private def toUrl(resource: ResourceLocation): URL = {
- val name = s"mcsounddomain:${resource.getResourceDomain}:${resource.getResourcePath}"
- try {
- new URL(null, name, new URLStreamHandler {
- protected def openConnection(url: URL): URLConnection = new URLConnection(url) {
- def connect() {
- }
+ override def isStopped() = stopped
- override def getInputStream = try {
- Minecraft.getMinecraft.getResourceManager.getResource(resource).getInputStream
- } catch {
- case t: Throwable =>
- OpenComputers.log.warn(t)
- null
- }
- }
- })
- }
- catch {
- case _: MalformedURLException => null
+ // Required by ITickableSound, which is required to update position while playing
+ override def tick() = ()
+
+ def stop() {
+ stopped = true
+ looping = false
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/Textures.scala b/src/main/scala/li/cil/oc/client/Textures.scala
index f457d7322a..5eb23ac767 100644
--- a/src/main/scala/li/cil/oc/client/Textures.scala
+++ b/src/main/scala/li/cil/oc/client/Textures.scala
@@ -1,15 +1,17 @@
package li.cil.oc.client
+import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
+import net.minecraft.inventory.container.PlayerContainer
+import net.minecraft.client.renderer.texture.SimpleTexture
import net.minecraft.client.renderer.texture.TextureAtlasSprite
-import net.minecraft.client.renderer.texture.TextureMap
import net.minecraft.util.ResourceLocation
import net.minecraftforge.client.event.TextureStitchEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import scala.collection.mutable
@@ -19,9 +21,10 @@ object Textures {
val Aliased = L("chars_aliased")
val AntiAliased = L("chars")
- override protected def basePath = "textures/font/%s.png"
+ override protected def basePath = "font/%s"
- override protected def loader(map: TextureMap, loc: ResourceLocation) = Textures.bind(loc)
+ override protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation) =
+ Minecraft.getInstance.textureManager.register(loc, new SimpleTexture(new ResourceLocation(loc.getNamespace, s"textures/${loc.getPath}.png")))
}
object GUI extends TextureBundle {
@@ -65,9 +68,10 @@ object Textures {
val UpgradeTab = L("upgrade_tab")
val Waypoint = L("waypoint")
- override protected def basePath = "textures/gui/%s.png"
+ override protected def basePath = "gui/%s"
- override protected def loader(map: TextureMap, loc: ResourceLocation) = Textures.bind(loc)
+ override protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation) =
+ Minecraft.getInstance.textureManager.register(loc, new SimpleTexture(new ResourceLocation(loc.getNamespace, s"textures/${loc.getPath}.png")))
}
object Icons extends TextureBundle {
@@ -78,9 +82,10 @@ object Textures {
def get(tier: Int) = ForTier.get(tier).orNull
- override protected def basePath = "textures/icons/%s.png"
+ override protected def basePath = "icons/%s"
- override protected def loader(map: TextureMap, loc: ResourceLocation) = Textures.bind(loc)
+ override protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation) =
+ Minecraft.getInstance.textureManager.register(loc, new SimpleTexture(new ResourceLocation(loc.getNamespace, s"textures/${loc.getPath}.png")))
}
object Model extends TextureBundle {
@@ -91,9 +96,10 @@ object Textures {
val Drone = L("drone")
val Robot = L("robot")
- override protected def basePath = "textures/model/%s.png"
+ override protected def basePath = "model/%s"
- override protected def loader(map: TextureMap, loc: ResourceLocation) = Textures.bind(loc)
+ override protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation) =
+ Minecraft.getInstance.textureManager.register(loc, new SimpleTexture(new ResourceLocation(loc.getNamespace, s"textures/${loc.getPath}.png")))
}
object Item extends TextureBundle {
@@ -102,7 +108,7 @@ object Textures {
override protected def basePath = "items/%s"
- override protected def loader(map: TextureMap, loc: ResourceLocation) = map.registerSprite(loc)
+ override protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation) = e.addSprite(loc)
}
// These are kept in the block texture atlas to support animations.
@@ -118,14 +124,14 @@ object Textures {
val ChargerSideOn = L("overlay/charger_side_on")
val DisassemblerSideOn = L("overlay/disassembler_side_on")
val DisassemblerTopOn = L("overlay/disassembler_top_on")
- val DiskDriveFrontActivity = L("overlay/diskDrive_front_activity")
+ val DiskDriveFrontActivity = L("overlay/diskdrive_front_activity")
val GeolyzerTopOn = L("overlay/geolyzer_top_on")
val MicrocontrollerFrontLight = L("overlay/microcontroller_front_light")
val MicrocontrollerFrontOn = L("overlay/microcontroller_front_on")
val MicrocontrollerFrontError = L("overlay/microcontroller_front_error")
- val NetSplitterOn = L("overlay/netSplitter_on")
- val PowerDistributorSideOn = L("overlay/powerDistributor_side_on")
- val PowerDistributorTopOn = L("overlay/powerDistributor_top_on")
+ val NetSplitterOn = L("overlay/netsplitter_on")
+ val PowerDistributorSideOn = L("overlay/powerdistributor_side_on")
+ val PowerDistributorTopOn = L("overlay/powerdistributor_top_on")
val RackDiskDrive = L("rack_disk_drive")
val RackDiskDriveActivity = L("overlay/rack_disk_drive_activity")
val RackServer = L("rack_server")
@@ -143,10 +149,10 @@ object Textures {
val TransposerOn = L("overlay/transposer_on")
val Cable = L("cable")
- val CableCap = L("cableCap")
+ val CableCap = L("cablecap")
val GenericTop = L("generic_top", load = false)
- val NetSplitterSide = L("netSplitter_side")
- val NetSplitterTop = L("netSplitter_top")
+ val NetSplitterSide = L("netsplitter_side")
+ val NetSplitterTop = L("netsplitter_top")
val RackFront = L("rack_front", load = false)
val RackSide = L("rack_side", load = false)
@@ -526,61 +532,50 @@ object Textures {
Screen.makeSureThisIsInitialized()
- def bind(): Unit = Textures.bind(TextureMap.LOCATION_BLOCKS_TEXTURE)
+ def bind(): Unit = Textures.bind(PlayerContainer.BLOCK_ATLAS)
override protected def basePath = "blocks/%s"
- override protected def loader(map: TextureMap, loc: ResourceLocation) = map.registerSprite(loc)
+ override protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation) = e.addSprite(loc)
}
def bind(location: ResourceLocation): Unit = {
- if (location == null) RenderState.bindTexture(0)
- else {
- val manager = Minecraft.getMinecraft.renderEngine
- manager.bindTexture(location)
- // IMPORTANT: manager.bindTexture uses GlStateManager.bindTexture, and
- // that has borked caching, so binding textures will sometimes fail,
- // because it'll think the texture is already bound although it isn't.
- // So we do it manually.
- val texture = manager.getTexture(location)
- if (texture != null) {
- RenderState.bindTexture(texture.getGlTextureId)
- }
- }
+ val texture = if (location != null) Minecraft.getInstance.textureManager.getTexture(location) else null
+ if (texture != null) texture.bind()
+ else RenderState.bindTexture(0)
}
- def getSprite(location: String): TextureAtlasSprite = Minecraft.getMinecraft.getTextureMapBlocks.getAtlasSprite(location)
-
- def getSprite(location: ResourceLocation): TextureAtlasSprite = getSprite(location.toString)
+ def getSprite(location: ResourceLocation): TextureAtlasSprite =
+ Minecraft.getInstance.getModelManager.getAtlas(PlayerContainer.BLOCK_ATLAS).getSprite(location)
@SubscribeEvent
def onTextureStitchPre(e: TextureStitchEvent.Pre): Unit = {
- Font.init(e.getMap)
- GUI.init(e.getMap)
- Icons.init(e.getMap)
- Model.init(e.getMap)
- Item.init(e.getMap)
- Block.init(e.getMap)
+ if (e.getMap.location.equals(PlayerContainer.BLOCK_ATLAS)) {
+ Font.init(e)
+ GUI.init(e)
+ Icons.init(e)
+ Model.init(e)
+ Item.init(e)
+ Block.init(e)
+ }
}
abstract class TextureBundle {
private val locations = mutable.ArrayBuffer.empty[ResourceLocation]
- protected def textureManager = Minecraft.getMinecraft.getTextureManager
-
- final def init(map: TextureMap): Unit = {
- locations.foreach(loader(map, _))
+ final def init(e: TextureStitchEvent.Pre): Unit = {
+ locations.foreach(loader(e, _))
}
protected def L(name: String, load: Boolean = true) = {
- val location = new ResourceLocation(Settings.resourceDomain, String.format(basePath, name))
+ val location = new ResourceLocation(OpenComputers.ID, String.format(basePath, name))
if (load) locations += location
location
}
protected def basePath: String
- protected def loader(map: TextureMap, loc: ResourceLocation): Unit
+ protected def loader(e: TextureStitchEvent.Pre, loc: ResourceLocation): Unit
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Adapter.scala b/src/main/scala/li/cil/oc/client/gui/Adapter.scala
index 1b73504983..475685f0ba 100644
--- a/src/main/scala/li/cil/oc/client/gui/Adapter.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Adapter.scala
@@ -1,15 +1,9 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Adapter(playerInventory: InventoryPlayer, val adapter: tileentity.Adapter) extends DynamicGuiContainer(new container.Adapter(playerInventory, adapter)) {
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(adapter.getName),
- 8, 6, 0x404040)
- }
+class Adapter(state: container.Adapter, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Assembler.scala b/src/main/scala/li/cil/oc/client/gui/Assembler.scala
index 60146d69c2..378a74b038 100644
--- a/src/main/scala/li/cil/oc/client/gui/Assembler.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Assembler.scala
@@ -1,5 +1,7 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.client.gui.widget.ProgressBar
@@ -7,29 +9,29 @@ import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.container
import li.cil.oc.common.container.ComponentSlot
import li.cil.oc.common.template.AssemblerTemplates
-import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.inventory.Slot
+import net.minecraft.client.gui.widget.button.Button
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.Slot
import net.minecraft.util.text.ITextComponent
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
-class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Assembler) extends DynamicGuiContainer(new container.Assembler(playerInventory, assembler)) {
- xSize = 176
- ySize = 192
+class Assembler(state: container.Assembler, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
- for (slot <- inventorySlots.inventorySlots) slot match {
+ imageWidth = 176
+ imageHeight = 192
+
+ for (slot <- menu.slots) slot match {
case component: ComponentSlot => component.changeListener = Option(onSlotChanged)
case _ =>
}
private def onSlotChanged(slot: Slot) {
- runButton.enabled = canBuild
- runButton.toggled = !runButton.enabled
+ runButton.active = canBuild
+ runButton.toggled = !runButton.active
info = validate
}
@@ -37,53 +39,57 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
protected var runButton: ImageButton = _
- private val progress = addWidget(new ProgressBar(28, 92))
+ private val progress = addCustomWidget(new ProgressBar(28, 92))
- private def validate = AssemblerTemplates.select(inventoryContainer.getSlot(0).getStack).map(_.validate(inventoryContainer.otherInventory))
+ private def validate = AssemblerTemplates.select(inventoryContainer.getSlot(0).getItem).map(_.validate(inventoryContainer.otherInventory))
private def canBuild = !inventoryContainer.isAssembling && validate.exists(_._1)
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0 && canBuild) {
- ClientPacketSender.sendRobotAssemblerStart(assembler)
- }
+ override protected def init() {
+ super.init()
+ runButton = new ImageButton(leftPos + 7, topPos + 89, 18, 18, new Button.IPressable {
+ override def onPress(b: Button) = if (canBuild) ClientPacketSender.sendRobotAssemblerStart(inventoryContainer)
+ }, Textures.GUI.ButtonRun, canToggle = true)
+ addButton(runButton)
}
- override def initGui() {
- super.initGui()
- runButton = new ImageButton(0, guiLeft + 7, guiTop + 89, 18, 18, Textures.GUI.ButtonRun, canToggle = true)
- add(buttonList, runButton)
+ override protected def renderLabels(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ drawSecondaryForegroundLayer(stack, mouseX, mouseY)
+
+ for (slot <- 0 until menu.slots.size()) {
+ drawSlotHighlight(stack, menu.getSlot(slot))
+ }
}
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int): Unit = {
+ override def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int): Unit = {
RenderState.pushAttrib()
if (!inventoryContainer.isAssembling) {
val message =
- if (!inventoryContainer.getSlot(0).getHasStack) {
+ if (!inventoryContainer.getSlot(0).hasItem) {
Localization.Assembler.InsertTemplate
}
else info match {
- case Some((_, value, _)) if value != null => value.getUnformattedText
- case _ if inventoryContainer.getSlot(0).getHasStack => Localization.Assembler.CollectResult
+ case Some((_, value, _)) if value != null => value.getString
+ case _ if inventoryContainer.getSlot(0).hasItem => Localization.Assembler.CollectResult
case _ => ""
}
- fontRenderer.drawString(message, 30, 94, 0x404040)
- if (runButton.isMouseOver) {
+ font.draw(stack, message, 30, 94, 0x404040)
+ if (runButton.isMouseOver(mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
tooltip.add(Localization.Assembler.Run)
info.foreach {
case (valid, _, warnings) => if (valid && warnings.length > 0) {
- tooltip.addAll(warnings.map(_.getUnformattedText).toList)
+ tooltip.addAll(warnings.map(_.getString).toList)
}
}
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
}
- else if (isPointInRegion(progress.x, progress.y, progress.width, progress.height, mouseX, mouseY)) {
+ else if (isPointInRegion(progress.x, progress.y, progress.width, progress.height, mouseX - leftPos, mouseY - topPos)) {
val tooltip = new java.util.ArrayList[String]
val timeRemaining = formatTime(inventoryContainer.assemblyRemainingTime)
tooltip.add(Localization.Assembler.Progress(inventoryContainer.assemblyProgress, timeRemaining))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
RenderState.popAttrib()
}
@@ -94,15 +100,15 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
else f"${seconds / 60}:${seconds % 60}%02d"
}
- override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1) // Required under Linux.
+ override protected def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color3f(1, 1, 1) // Required under Linux.
Textures.bind(Textures.GUI.RobotAssembler)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
if (inventoryContainer.isAssembling) progress.level = inventoryContainer.assemblyProgress / 100.0
else progress.level = 0
- drawWidgets()
- drawInventorySlots()
+ drawWidgets(stack)
+ drawInventorySlots(stack)
}
- override protected def drawDisabledSlot(slot: ComponentSlot) {}
+ override protected def drawDisabledSlot(stack: MatrixStack, slot: ComponentSlot) {}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Case.scala b/src/main/scala/li/cil/oc/client/gui/Case.scala
index 7900bce06b..27ab95b807 100644
--- a/src/main/scala/li/cil/oc/client/gui/Case.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Case.scala
@@ -1,51 +1,48 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.client.gui.widget.button.Button
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaCollection
+import scala.collection.convert.ImplicitConversionsToJava._
-class Case(playerInventory: InventoryPlayer, val computer: tileentity.Case) extends DynamicGuiContainer(new container.Case(playerInventory, computer)) {
- protected var powerButton: ImageButton = _
+class Case(state: container.Case, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0) {
- ClientPacketSender.sendComputerPower(computer, !computer.isRunning)
- }
- }
+ protected var powerButton: ImageButton = _
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
- powerButton.toggled = computer.isRunning
- super.drawScreen(mouseX, mouseY, dt)
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float) {
+ powerButton.toggled = inventoryContainer.isRunning
+ super.render(stack, mouseX, mouseY, dt)
}
- override def initGui() {
- super.initGui()
- powerButton = new ImageButton(0, guiLeft + 70, guiTop + 33, 18, 18, Textures.GUI.ButtonPower, canToggle = true)
- add(buttonList, powerButton)
+ override protected def init() {
+ super.init()
+ powerButton = new ImageButton(leftPos + 70, topPos + 33, 18, 18, new Button.IPressable {
+ override def onPress(b: Button) = ClientPacketSender.sendComputerPower(inventoryContainer, !inventoryContainer.isRunning)
+ }, Textures.GUI.ButtonPower, canToggle = true)
+ addButton(powerButton)
}
- override protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(computer.getName),
- 8, 6, 0x404040)
- if (powerButton.isMouseOver) {
+ override protected def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(stack, mouseX, mouseY)
+ if (powerButton.isMouseOver(mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
- tooltip.addAll(asJavaCollection(if (computer.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ tooltip.addAll(asJavaCollection(if (inventoryContainer.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
}
- override def drawSecondaryBackgroundLayer() {
- GlStateManager.color(1, 1, 1)
+ override def drawSecondaryBackgroundLayer(stack: MatrixStack) {
+ RenderSystem.color3f(1, 1, 1)
Textures.bind(Textures.GUI.Computer)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Charger.scala b/src/main/scala/li/cil/oc/client/gui/Charger.scala
index 1cf35a188f..afb106a42c 100644
--- a/src/main/scala/li/cil/oc/client/gui/Charger.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Charger.scala
@@ -1,15 +1,9 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Charger(playerInventory: InventoryPlayer, val charger: tileentity.Charger) extends DynamicGuiContainer(new container.Charger(playerInventory, charger)) {
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(charger.getName),
- 8, 6, 0x404040)
- }
+class Charger(state: container.Charger, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
}
diff --git a/src/main/scala/li/cil/oc/client/gui/CustomGuiContainer.scala b/src/main/scala/li/cil/oc/client/gui/CustomGuiContainer.scala
index 9eaf3998f2..aa32642b81 100644
--- a/src/main/scala/li/cil/oc/client/gui/CustomGuiContainer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/CustomGuiContainer.scala
@@ -2,44 +2,65 @@ package li.cil.oc.client.gui
import java.util
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.gui.widget.WidgetContainer
import li.cil.oc.util.RenderState
import net.minecraft.client.gui.FontRenderer
-import net.minecraft.client.gui.inventory.GuiContainer
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.gui.screen.inventory.ContainerScreen
+import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.renderer.RenderHelper
-import net.minecraft.inventory.Container
+import net.minecraft.client.renderer.Tessellator
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.Container
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.ITextProperties
+import net.minecraft.util.text.LanguageMap
+import net.minecraft.util.text.StringTextComponent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
// Workaround because certain other mods *cough*TMI*cough* do base class
// transformations that break things! Such fun. Many annoyed. And yes, this
// is a common issue, have a look at EnderIO and Enchanting Plus. They have
// to work around this, too.
-abstract class CustomGuiContainer[C <: Container](val inventoryContainer: C) extends GuiContainer(inventoryContainer) with WidgetContainer {
- override def windowX = guiLeft
+abstract class CustomGuiContainer[C <: Container](val inventoryContainer: C, inv: PlayerInventory, title: ITextComponent)
+ extends ContainerScreen(inventoryContainer, inv, title) with WidgetContainer {
- override def windowY = guiTop
+ override def windowX = leftPos
- override def windowZ = zLevel
+ override def windowY = topPos
- override def doesGuiPauseGame = false
+ override def windowZ = getBlitOffset
+
+ override def isPauseScreen = false
protected def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
// Pretty much Scalaified copy-pasta from base-class.
- override def drawHoveringText(text: util.List[String], x: Int, y: Int, font: FontRenderer): Unit = {
- copiedDrawHoveringText(text, x, y, font)
+ override def renderWrappedToolTip(stack: MatrixStack, text: util.List[_ <: ITextProperties], x: Int, y: Int, font: FontRenderer): Unit = {
+ copiedDrawHoveringText0(stack, text, x, y, font)
}
- protected def copiedDrawHoveringText(text: util.List[String], x: Int, y: Int, font: FontRenderer): Unit = {
+ protected def isPointInRegion(rectX: Int, rectY: Int, rectWidth: Int, rectHeight: Int, pointX: Int, pointY: Int): Boolean =
+ pointX >= rectX - 1 && pointX < rectX + rectWidth + 1 && pointY >= rectY - 1 && pointY < rectY + rectHeight + 1
+
+ protected def copiedDrawHoveringText(stack: MatrixStack, lines: util.List[String], x: Int, y: Int, font: FontRenderer): Unit = {
+ val text = new util.ArrayList[StringTextComponent]()
+ for (line <- lines) {
+ text.add(new StringTextComponent(line))
+ }
+ copiedDrawHoveringText0(stack, text, x, y, font)
+ }
+
+ protected def copiedDrawHoveringText0(stack: MatrixStack, text: util.List[_ <: ITextProperties], x: Int, y: Int, font: FontRenderer): Unit = {
if (!text.isEmpty) {
- GlStateManager.disableRescaleNormal()
- RenderHelper.disableStandardItemLighting()
- GlStateManager.disableLighting()
- GlStateManager.disableDepth()
+ RenderSystem.disableRescaleNormal()
+ RenderHelper.turnOff()
+ RenderSystem.disableLighting()
+ RenderSystem.disableDepthTest()
- val textWidth = text.map(line => font.getStringWidth(line)).max
+ val textWidth = text.map(line => font.width(line)).max
var posX = x + 12
var posY = y - 12
@@ -54,46 +75,51 @@ abstract class CustomGuiContainer[C <: Container](val inventoryContainer: C) ext
posY = height - textHeight - 6
}
- zLevel = 300f
- itemRender.zLevel = 300f
+ setBlitOffset(300)
+ itemRenderer.blitOffset = 300f
val bg = 0xF0100010
- drawGradientRect(posX - 3, posY - 4, posX + textWidth + 3, posY - 3, bg, bg)
- drawGradientRect(posX - 3, posY + textHeight + 3, posX + textWidth + 3, posY + textHeight + 4, bg, bg)
- drawGradientRect(posX - 3, posY - 3, posX + textWidth + 3, posY + textHeight + 3, bg, bg)
- drawGradientRect(posX - 4, posY - 3, posX - 3, posY + textHeight + 3, bg, bg)
- drawGradientRect(posX + textWidth + 3, posY - 3, posX + textWidth + 4, posY + textHeight + 3, bg, bg)
+ fillGradient(stack, posX - 3, posY - 4, posX + textWidth + 3, posY - 3, bg, bg)
+ fillGradient(stack, posX - 3, posY + textHeight + 3, posX + textWidth + 3, posY + textHeight + 4, bg, bg)
+ fillGradient(stack, posX - 3, posY - 3, posX + textWidth + 3, posY + textHeight + 3, bg, bg)
+ fillGradient(stack, posX - 4, posY - 3, posX - 3, posY + textHeight + 3, bg, bg)
+ fillGradient(stack, posX + textWidth + 3, posY - 3, posX + textWidth + 4, posY + textHeight + 3, bg, bg)
val color1 = 0x505000FF
val color2 = (color1 & 0x00FEFEFE) >> 1 | (color1 & 0xFF000000)
- drawGradientRect(posX - 3, posY - 3 + 1, posX - 3 + 1, posY + textHeight + 3 - 1, color1, color2)
- drawGradientRect(posX + textWidth + 2, posY - 3 + 1, posX + textWidth + 3, posY + textHeight + 3 - 1, color1, color2)
- drawGradientRect(posX - 3, posY - 3, posX + textWidth + 3, posY - 3 + 1, color1, color1)
- drawGradientRect(posX - 3, posY + textHeight + 2, posX + textWidth + 3, posY + textHeight + 3, color2, color2)
-
+ fillGradient(stack, posX - 3, posY - 3 + 1, posX - 3 + 1, posY + textHeight + 3 - 1, color1, color2)
+ fillGradient(stack, posX + textWidth + 2, posY - 3 + 1, posX + textWidth + 3, posY + textHeight + 3 - 1, color1, color2)
+ fillGradient(stack, posX - 3, posY - 3, posX + textWidth + 3, posY - 3 + 1, color1, color1)
+ fillGradient(stack, posX - 3, posY + textHeight + 2, posX + textWidth + 3, posY + textHeight + 3, color2, color2)
+
+ stack.pushPose()
+ stack.translate(0, 0, 400)
+ val buffer = IRenderTypeBuffer.immediate(Tessellator.getInstance.getBuilder())
for ((line, index) <- text.zipWithIndex) {
- font.drawStringWithShadow(line.asInstanceOf[String], posX, posY, -1)
+ font.drawInBatch(LanguageMap.getInstance.getVisualOrder(line), posX, posY, -1, true, stack.last.pose, buffer, false, 0, 15728880)
if (index == 0) {
posY += 2
}
posY += 10
}
- zLevel = 0f
- itemRender.zLevel = 0f
-
- GlStateManager.enableLighting()
- GlStateManager.enableDepth()
- RenderHelper.enableStandardItemLighting()
- GlStateManager.enableRescaleNormal()
+ buffer.endBatch()
+ stack.popPose()
+ setBlitOffset(0)
+ itemRenderer.blitOffset = 0f
+
+ RenderSystem.enableLighting()
+ RenderSystem.enableDepthTest()
+ RenderHelper.turnBackOn()
+ RenderSystem.enableRescaleNormal()
}
}
- override def drawGradientRect(left: Int, top: Int, right: Int, bottom: Int, startColor: Int, endColor: Int): Unit = {
- super.drawGradientRect(left, top, right, bottom, startColor, endColor)
+ override def fillGradient(stack: MatrixStack, left: Int, top: Int, right: Int, bottom: Int, startColor: Int, endColor: Int): Unit = {
+ super.fillGradient(stack, left, top, right, bottom, startColor, endColor)
RenderState.makeItBlend()
}
- override def drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float): Unit = {
- this.drawDefaultBackground()
- super.drawScreen(mouseX, mouseY, partialTicks)
- this.renderHoveredToolTip(mouseX, mouseY)
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float): Unit = {
+ this.renderBackground(stack)
+ super.render(stack, mouseX, mouseY, partialTicks)
+ this.renderTooltip(stack, mouseX, mouseY)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Database.scala b/src/main/scala/li/cil/oc/client/gui/Database.scala
index 36b42f1894..805adf2ab7 100644
--- a/src/main/scala/li/cil/oc/client/gui/Database.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Database.scala
@@ -1,32 +1,39 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import li.cil.oc.common.Tier
import li.cil.oc.common.container
-import li.cil.oc.common.inventory.DatabaseInventory
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Database(playerInventory: InventoryPlayer, val databaseInventory: DatabaseInventory) extends DynamicGuiContainer(new container.Database(playerInventory, databaseInventory)) with traits.LockedHotbar {
- ySize = 256
+class Database(state: container.Database, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name)
+ with traits.LockedHotbar[container.Database] {
- override def lockedStack = databaseInventory.container
+ imageHeight = 256
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {}
+ override def lockedStack = inventoryContainer.container
- override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1, 1)
+ override protected def renderLabels(stack: MatrixStack, mouseX: Int, mouseY: Int) =
+ drawSecondaryForegroundLayer(stack, mouseX, mouseY)
+
+ override def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) {}
+
+ override protected def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color4f(1, 1, 1, 1)
Textures.bind(Textures.GUI.Database)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
- if (databaseInventory.tier > Tier.One) {
+ if (inventoryContainer.tier > Tier.One) {
Textures.bind(Textures.GUI.Database1)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
}
- if (databaseInventory.tier > Tier.Two) {
+ if (inventoryContainer.tier > Tier.Two) {
Textures.bind(Textures.GUI.Database2)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Disassembler.scala b/src/main/scala/li/cil/oc/client/gui/Disassembler.scala
index 1a90a66b3e..3b8fea9840 100644
--- a/src/main/scala/li/cil/oc/client/gui/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Disassembler.scala
@@ -1,27 +1,32 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import li.cil.oc.client.gui.widget.ProgressBar
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentity.Disassembler) extends DynamicGuiContainer(new container.Disassembler(playerInventory, disassembler)) {
- val progress = addWidget(new ProgressBar(18, 65))
+class Disassembler(state: container.Disassembler, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- fontRenderer.drawString(
- Localization.localizeImmediately(disassembler.getName),
- 8, 6, 0x404040)
+ val progress = addCustomWidget(new ProgressBar(18, 65))
+
+ override protected def renderLabels(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ font.draw(stack, title, titleLabelX, titleLabelY, 0x404040)
+ drawSecondaryForegroundLayer(stack, mouseX, mouseY)
+
+ for (slot <- 0 until menu.slots.size()) {
+ drawSlotHighlight(stack, menu.getSlot(slot))
+ }
}
- override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1)
+ override def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color3f(1, 1, 1)
Textures.bind(Textures.GUI.Disassembler)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
progress.level = inventoryContainer.disassemblyProgress / 100.0
- drawWidgets()
+ drawWidgets(stack)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala b/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala
index 14ab5bd7ed..0db7dd3b8e 100644
--- a/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala
+++ b/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala
@@ -1,15 +1,9 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
import li.cil.oc.common.container
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.inventory.IInventory
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class DiskDrive(playerInventory: InventoryPlayer, val drive: IInventory) extends DynamicGuiContainer(new container.DiskDrive(playerInventory, drive)) {
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(drive.getName),
- 8, 6, 0x404040)
- }
+class DiskDrive(state: container.DiskDrive, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Drive.scala b/src/main/scala/li/cil/oc/client/gui/Drive.scala
index 74185a031e..ab990274ab 100644
--- a/src/main/scala/li/cil/oc/client/gui/Drive.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Drive.scala
@@ -1,15 +1,18 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.item.data.DriveData
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.client.gui.widget.button.Button
+import net.minecraft.client.gui.screen
+import net.minecraft.client.settings.KeyBinding
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.StringTextComponent
-class Drive(playerInventory: InventoryPlayer, val driveStack: () => ItemStack) extends GuiScreen with traits.Window {
+class Drive(playerInventory: PlayerInventory, val driveStack: () => ItemStack) extends screen.Screen(StringTextComponent.EMPTY) with traits.Window {
override val windowHeight = 120
override def backgroundImage = Textures.GUI.Drive
@@ -18,46 +21,45 @@ class Drive(playerInventory: InventoryPlayer, val driveStack: () => ItemStack) e
protected var unmanagedButton: ImageButton = _
protected var lockedButton: ImageButton = _
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0) {
- ClientPacketSender.sendDriveMode(unmanaged = false)
- DriveData.setUnmanaged(driveStack(), unmanaged = false)
- } else if (button.id == 1) {
- ClientPacketSender.sendDriveMode(unmanaged = true)
- DriveData.setUnmanaged(driveStack(), unmanaged = true)
- } else if (button.id == 2) {
- ClientPacketSender.sendDriveLock()
- DriveData.lock(driveStack(), playerInventory.player)
- }
- updateButtonStates()
- }
-
def updateButtonStates(): Unit = {
val data = new DriveData(driveStack())
unmanagedButton.toggled = data.isUnmanaged
managedButton.toggled = !unmanagedButton.toggled
lockedButton.toggled = data.isLocked
- lockedButton.enabled = !data.isLocked
+ lockedButton.active = !data.isLocked
}
- override def initGui(): Unit = {
- super.initGui()
- managedButton = new ImageButton(0, guiLeft + 11, guiTop + 11, 74, 18, Textures.GUI.ButtonDriveMode, text = Localization.Drive.Managed, textColor = 0x608060, canToggle = true)
- unmanagedButton = new ImageButton(1, guiLeft + 91, guiTop + 11, 74, 18, Textures.GUI.ButtonDriveMode, text = Localization.Drive.Unmanaged, textColor = 0x608060, canToggle = true)
- lockedButton = new ImageButton(2, guiLeft + 11, guiTop + windowHeight - 42, 44, 18, Textures.GUI.ButtonDriveMode, text = Localization.Drive.ReadOnlyLock, textColor = 0x608060, canToggle = true)
- add(buttonList, managedButton)
- add(buttonList, unmanagedButton)
- add(buttonList, lockedButton)
+ override protected def init(): Unit = {
+ super.init()
+ minecraft.mouseHandler.releaseMouse()
+ KeyBinding.releaseAll()
+ managedButton = new ImageButton(leftPos + 11, topPos + 11, 74, 18, new Button.IPressable {
+ override def onPress(b: Button) = {
+ ClientPacketSender.sendDriveMode(unmanaged = false)
+ DriveData.setUnmanaged(driveStack(), unmanaged = false)
+ }
+ }, Textures.GUI.ButtonDriveMode, text = new StringTextComponent(Localization.Drive.Managed), textColor = 0x608060, canToggle = true)
+ unmanagedButton = new ImageButton(leftPos + 91, topPos + 11, 74, 18, new Button.IPressable {
+ override def onPress(b: Button) = {
+ ClientPacketSender.sendDriveMode(unmanaged = true)
+ DriveData.setUnmanaged(driveStack(), unmanaged = true)
+ }
+ }, Textures.GUI.ButtonDriveMode, text = new StringTextComponent(Localization.Drive.Unmanaged), textColor = 0x608060, canToggle = true)
+ lockedButton = new ImageButton(leftPos + 11, topPos + windowHeight - 42, 44, 18, new Button.IPressable {
+ override def onPress(b: Button) = {
+ ClientPacketSender.sendDriveLock()
+ DriveData.lock(driveStack(), playerInventory.player)
+ }
+ }, Textures.GUI.ButtonDriveMode, text = new StringTextComponent(Localization.Drive.ReadOnlyLock), textColor = 0x608060, canToggle = true)
+ addButton(managedButton)
+ addButton(unmanagedButton)
+ addButton(lockedButton)
updateButtonStates()
}
- override def updateScreen(): Unit = {
- super.updateScreen()
- }
-
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
- super.drawScreen(mouseX, mouseY, dt)
- fontRenderer.drawSplitString(Localization.Drive.Warning, guiLeft + 11, guiTop + 37, xSize - 20, 0x404040)
- fontRenderer.drawSplitString(Localization.Drive.LockWarning, guiLeft + 61, guiTop + windowHeight - 48, xSize - 68, 0x404040)
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float): Unit = {
+ super.render(stack, mouseX, mouseY, dt)
+ font.drawWordWrap(new StringTextComponent(Localization.Drive.Warning), leftPos + 11, topPos + 37, imageWidth - 20, 0x404040)
+ font.drawWordWrap(new StringTextComponent(Localization.Drive.LockWarning), leftPos + 61, topPos + windowHeight - 48, imageWidth - 68, 0x404040)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Drone.scala b/src/main/scala/li/cil/oc/client/gui/Drone.scala
index e144077cc9..da14cfa0c1 100644
--- a/src/main/scala/li/cil/oc/client/gui/Drone.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Drone.scala
@@ -1,5 +1,7 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.client.gui.widget.ProgressBar
@@ -7,22 +9,25 @@ import li.cil.oc.client.renderer.TextBufferRenderCache
import li.cil.oc.client.renderer.font.TextBufferRenderData
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.container
-import li.cil.oc.common.entity
import li.cil.oc.util.PackedColor
import li.cil.oc.util.RenderState
import li.cil.oc.util.TextBuffer
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.gui.widget.button.Button
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
import org.lwjgl.opengl.GL11
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaCollection
+import scala.collection.convert.ImplicitConversionsToJava._
-class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends DynamicGuiContainer(new container.Drone(playerInventory, drone)) with traits.DisplayBuffer {
- xSize = 176
- ySize = 148
+class Drone(state: container.Drone, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name)
+ with traits.DisplayBuffer {
+
+ imageWidth = 176
+ imageHeight = 148
protected var powerButton: ImageButton = _
@@ -47,100 +52,97 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
private val inventoryX = 97
private val inventoryY = 7
- private val power = addWidget(new ProgressBar(28, 48))
+ private val power = addCustomWidget(new ProgressBar(28, 48))
private val selectionSize = 20
private val selectionsStates = 17
- private val selectionStepV = 1 / selectionsStates.toDouble
+ private val selectionStepV = 1 / selectionsStates.toFloat
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0) {
- ClientPacketSender.sendDronePower(drone, !drone.isRunning)
- }
- }
-
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
- powerButton.toggled = drone.isRunning
- bufferRenderer.dirty = drone.statusText.lines.zipWithIndex.exists {
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float) {
+ powerButton.toggled = inventoryContainer.isRunning
+ bufferRenderer.dirty = inventoryContainer.statusText.lines.zipWithIndex.exists {
case (line, i) => buffer.set(0, i, line, vertical = false)
}
- super.drawScreen(mouseX, mouseY, dt)
+ super.render(stack, mouseX, mouseY, dt)
}
- override def initGui() {
- super.initGui()
- powerButton = new ImageButton(0, guiLeft + 7, guiTop + 45, 18, 18, Textures.GUI.ButtonPower, canToggle = true)
- add(buttonList, powerButton)
+ override protected def init() {
+ super.init()
+ powerButton = new ImageButton(leftPos + 7, topPos + 45, 18, 18, new Button.IPressable {
+ override def onPress(b: Button) = ClientPacketSender.sendDronePower(inventoryContainer, !inventoryContainer.isRunning)
+ }, Textures.GUI.ButtonPower, canToggle = true)
+ addButton(powerButton)
}
- override protected def drawBuffer() {
- GlStateManager.translate(bufferX, bufferY, 0)
+ override protected def drawBuffer(stack: MatrixStack) {
+ stack.translate(bufferX, bufferY, 0)
RenderState.disableEntityLighting()
RenderState.makeItBlend()
- GlStateManager.scale(scale, scale, 1)
+ stack.scale(scale.toFloat, scale.toFloat, 1)
RenderState.pushAttrib()
- GlStateManager.depthMask(false)
- GlStateManager.color(0.5f, 0.5f, 1f)
- TextBufferRenderCache.render(bufferRenderer)
+ RenderSystem.depthMask(false)
+ RenderSystem.color3f(0.5f, 0.5f, 1f)
+ TextBufferRenderCache.render(stack, bufferRenderer)
RenderState.popAttrib()
}
- override protected def changeSize(w: Double, h: Double, recompile: Boolean) = 2.0
+ override protected def changeSize(w: Double, h: Double) = 2.0
+
+ override protected def renderLabels(stack: MatrixStack, mouseX: Int, mouseY: Int) =
+ drawSecondaryForegroundLayer(stack, mouseX, mouseY)
- override protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
- drawBufferLayer()
+ override protected def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ drawBufferLayer(stack)
RenderState.pushAttrib()
- if (isPointInRegion(power.x, power.y, power.width, power.height, mouseX, mouseY)) {
+ if (isPointInRegion(power.x, power.y, power.width, power.height, mouseX - leftPos, mouseY - topPos)) {
val tooltip = new java.util.ArrayList[String]
val format = Localization.Computer.Power + ": %d%% (%d/%d)"
tooltip.add(format.format(
- drone.globalBuffer * 100 / math.max(drone.globalBufferSize, 1),
- drone.globalBuffer,
- drone.globalBufferSize))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ inventoryContainer.globalBuffer * 100 / math.max(inventoryContainer.globalBufferSize, 1),
+ inventoryContainer.globalBuffer, inventoryContainer.globalBufferSize))
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
- if (powerButton.isMouseOver) {
+ if (powerButton.isMouseOver(mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
- tooltip.addAll(asJavaCollection(if (drone.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ tooltip.addAll(asJavaCollection(if (inventoryContainer.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
RenderState.popAttrib()
}
- override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1)
+ override protected def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color3f(1, 1, 1)
Textures.bind(Textures.GUI.Drone)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
- power.level = drone.globalBuffer.toDouble / math.max(drone.globalBufferSize.toDouble, 1.0)
- drawWidgets()
- if (drone.mainInventory.getSizeInventory > 0) {
- drawSelection()
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
+ power.level = inventoryContainer.globalBuffer.toFloat / math.max(inventoryContainer.globalBufferSize.toFloat, 1.0f)
+ drawWidgets(stack)
+ if (inventoryContainer.otherInventory.getContainerSize > 0) {
+ drawSelection(stack)
}
- drawInventorySlots()
+ drawInventorySlots(stack)
}
// No custom slots, we just extend DynamicGuiContainer for the highlighting.
- override protected def drawSlotBackground(x: Int, y: Int) {}
+ override protected def drawSlotBackground(stack: MatrixStack, x: Int, y: Int) {}
- private def drawSelection() {
- val slot = drone.selectedSlot
+ private def drawSelection(stack: MatrixStack) {
+ val slot = inventoryContainer.selectedSlot
if (slot >= 0 && slot < 16) {
- RenderState.makeItBlend()
Textures.bind(Textures.GUI.RobotSelection)
- val now = System.currentTimeMillis() / 1000.0
- val offsetV = ((now - now.toInt) * selectionsStates).toInt * selectionStepV
- val x = guiLeft + inventoryX - 1 + (slot % 4) * (selectionSize - 2)
- val y = guiTop + inventoryY - 1 + (slot / 4) * (selectionSize - 2)
+ val now = System.currentTimeMillis() % 1000 / 1000.0f
+ val offsetV = (now * selectionsStates).toInt * selectionStepV
+ val x = leftPos + inventoryX - 1 + (slot % 4) * (selectionSize - 2)
+ val y = topPos + inventoryY - 1 + (slot / 4) * (selectionSize - 2)
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y, zLevel).tex(0, offsetV).endVertex()
- r.pos(x, y + selectionSize, zLevel).tex(0, offsetV + selectionStepV).endVertex()
- r.pos(x + selectionSize, y + selectionSize, zLevel).tex(1, offsetV + selectionStepV).endVertex()
- r.pos(x + selectionSize, y, zLevel).tex(1, offsetV).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, x, y, getBlitOffset).uv(0, offsetV).endVertex()
+ r.vertex(stack.last.pose, x, y + selectionSize, getBlitOffset).uv(0, offsetV + selectionStepV).endVertex()
+ r.vertex(stack.last.pose, x + selectionSize, y + selectionSize, getBlitOffset).uv(1, offsetV + selectionStepV).endVertex()
+ r.vertex(stack.last.pose, x + selectionSize, y, getBlitOffset).uv(1, offsetV).endVertex()
+ t.end()
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala
index bee3a20419..b78d0ee57f 100644
--- a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala
@@ -1,5 +1,7 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.common
@@ -11,134 +13,130 @@ import li.cil.oc.integration.util.ItemSearch
import li.cil.oc.util.RenderState
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
-import net.minecraft.client.gui.Gui
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.gui.AbstractGui
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.inventory.Container
-import net.minecraft.inventory.Slot
-import net.minecraftforge.fml.common.Optional
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.Container
+import net.minecraft.inventory.container.Slot
+import net.minecraft.util.text.ITextComponent
import org.lwjgl.opengl.GL11
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
-abstract class DynamicGuiContainer[C <: Container](container: C) extends CustomGuiContainer(container) {
- protected var hoveredSlot: Option[Slot] = None
+abstract class DynamicGuiContainer[C <: Container](container: C, inv: PlayerInventory, title: ITextComponent)
+ extends CustomGuiContainer(container, inv, title) {
protected var hoveredStackNEI: StackOption = EmptyStack
- protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
- fontRenderer.drawString(
- Localization.localizeImmediately("container.inventory"),
- 8, ySize - 96 + 2, 0x404040)
+ override protected def init() {
+ super.init()
+ // imageHeight is set in the body of the extending class, so it's not available in ours.
+ inventoryLabelY = imageHeight - 96 + 2
}
- override protected def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
+ protected def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) {}
+
+ override protected def renderLabels(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ super.renderLabels(stack, mouseX, mouseY)
RenderState.pushAttrib()
- drawSecondaryForegroundLayer(mouseX, mouseY)
+ drawSecondaryForegroundLayer(stack, mouseX, mouseY)
- for (slot <- 0 until inventorySlots.inventorySlots.size()) {
- drawSlotHighlight(inventorySlots.inventorySlots.get(slot))
+ for (slot <- 0 until menu.slots.size()) {
+ drawSlotHighlight(stack, menu.getSlot(slot))
}
RenderState.popAttrib()
}
- protected def drawSecondaryBackgroundLayer() {}
+ protected def drawSecondaryBackgroundLayer(stack: MatrixStack) {}
- override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1, 1)
+ override protected def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color4f(1, 1, 1, 1)
Textures.bind(Textures.GUI.Background)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
- drawSecondaryBackgroundLayer()
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
+ drawSecondaryBackgroundLayer(stack)
RenderState.makeItBlend()
- GlStateManager.disableLighting()
+ RenderSystem.disableLighting()
- drawInventorySlots()
+ drawInventorySlots(stack)
}
- protected def drawInventorySlots(): Unit = {
- GlStateManager.pushMatrix()
- GlStateManager.translate(guiLeft, guiTop, 0)
- GlStateManager.disableDepth()
- for (slot <- 0 until inventorySlots.inventorySlots.size()) {
- drawSlotInventory(inventorySlots.inventorySlots.get(slot))
+ protected def drawInventorySlots(stack: MatrixStack): Unit = {
+ stack.pushPose()
+ stack.translate(leftPos, topPos, 0)
+ RenderSystem.disableDepthTest()
+ for (slot <- 0 until menu.slots.size()) {
+ drawSlotInventory(stack, menu.getSlot(slot))
}
- GlStateManager.enableDepth()
- GlStateManager.popMatrix()
+ RenderSystem.enableDepthTest()
+ stack.popPose()
RenderState.makeItBlend()
}
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
- hoveredSlot = (inventorySlots.inventorySlots collect {
- case slot: Slot if isPointInRegion(slot.xPos, slot.yPos, 16, 16, mouseX, mouseY) => slot
- }).headOption
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float) {
hoveredStackNEI = ItemSearch.hoveredStack(this, mouseX, mouseY)
- super.drawScreen(mouseX, mouseY, dt)
-
- if (Mods.JustEnoughItems.isModAvailable) {
- drawJEIHighlights()
- }
+ super.render(stack, mouseX, mouseY, dt)
}
- protected def drawSlotInventory(slot: Slot) {
- GlStateManager.enableBlend()
+ protected def drawSlotInventory(stack: MatrixStack, slot: Slot) {
+ RenderSystem.enableBlend()
slot match {
case component: ComponentSlot if component.slot == common.Slot.None || component.tier == common.Tier.None =>
- if (!slot.getHasStack && slot.xPos >= 0 && slot.yPos >= 0 && component.tierIcon != null) {
- drawDisabledSlot(component)
+ if (!slot.hasItem && slot.x >= 0 && slot.y >= 0 && component.tierIcon != null) {
+ drawDisabledSlot(stack, component)
}
case _ =>
- zLevel += 1
+ setBlitOffset(getBlitOffset + 1)
if (!isInPlayerInventory(slot)) {
- drawSlotBackground(slot.xPos - 1, slot.yPos - 1)
+ drawSlotBackground(stack, slot.x - 1, slot.y - 1)
}
- if (!slot.getHasStack) {
+ if (!slot.hasItem) {
slot match {
case component: ComponentSlot =>
if (component.tierIcon != null) {
Textures.bind(component.tierIcon)
- Gui.drawModalRectWithCustomSizedTexture(slot.xPos, slot.yPos, 0, 0, 16, 16, 16, 16)
+ AbstractGui.blit(stack, slot.x, slot.y, getBlitOffset, 0, 0, 16, 16, 16, 16)
}
if (component.hasBackground) {
- Textures.bind(slot.getBackgroundLocation)
- Gui.drawModalRectWithCustomSizedTexture(slot.xPos, slot.yPos, 0, 0, 16, 16, 16, 16)
+ Textures.bind(component.getBackgroundLocation)
+ AbstractGui.blit(stack, slot.x, slot.y, getBlitOffset, 0, 0, 16, 16, 16, 16)
}
case _ =>
}
- zLevel -= 1
+ setBlitOffset(getBlitOffset - 1)
}
}
- GlStateManager.disableBlend()
+ RenderSystem.disableBlend()
}
- protected def drawSlotHighlight(slot: Slot) {
- if (mc.player.inventory.getItemStack.isEmpty) slot match {
+ protected def drawSlotHighlight(matrix: MatrixStack, slot: Slot) {
+ if (minecraft.player.inventory.getCarried.isEmpty) slot match {
case component: ComponentSlot if component.slot == common.Slot.None || component.tier == common.Tier.None => // Ignore.
case _ =>
val currentIsInPlayerInventory = isInPlayerInventory(slot)
val drawHighlight = hoveredSlot match {
- case Some(hovered) =>
+ case hovered: Slot =>
val hoveredIsInPlayerInventory = isInPlayerInventory(hovered)
(currentIsInPlayerInventory != hoveredIsInPlayerInventory) &&
- ((currentIsInPlayerInventory && slot.getHasStack && isSelectiveSlot(hovered) && hovered.isItemValid(slot.getStack)) ||
- (hoveredIsInPlayerInventory && hovered.getHasStack && isSelectiveSlot(slot) && slot.isItemValid(hovered.getStack)))
+ ((currentIsInPlayerInventory && slot.hasItem && isSelectiveSlot(hovered) && hovered.mayPlace(slot.getItem)) ||
+ (hoveredIsInPlayerInventory && hovered.hasItem && isSelectiveSlot(slot) && slot.mayPlace(hovered.getItem)))
case _ => hoveredStackNEI match {
- case SomeStack(stack) => !currentIsInPlayerInventory && isSelectiveSlot(slot) && slot.isItemValid(stack)
+ case SomeStack(stack) => !currentIsInPlayerInventory && isSelectiveSlot(slot) && slot.mayPlace(stack)
case _ => false
}
}
if (drawHighlight) {
- zLevel += 100
- drawGradientRect(
- slot.xPos, slot.yPos,
- slot.xPos + 16, slot.yPos + 16,
+ setBlitOffset(getBlitOffset + 100)
+ fillGradient(matrix,
+ slot.x, slot.y,
+ slot.x + 16, slot.y + 16,
0x80FFFFFF, 0x80FFFFFF)
- zLevel -= 100
+ setBlitOffset(getBlitOffset - 100)
}
}
}
@@ -148,49 +146,27 @@ abstract class DynamicGuiContainer[C <: Container](container: C) extends CustomG
case _ => false
}
- protected def drawDisabledSlot(slot: ComponentSlot) {
- GlStateManager.color(1, 1, 1, 1)
+ protected def drawDisabledSlot(stack: MatrixStack, slot: ComponentSlot) {
+ RenderSystem.color4f(1, 1, 1, 1)
Textures.bind(slot.tierIcon)
- Gui.drawModalRectWithCustomSizedTexture(slot.xPos, slot.yPos, 0, 0, 16, 16, 16, 16)
+ AbstractGui.blit(stack, slot.x, slot.y, getBlitOffset, 0, 0, 16, 16, 16, 16)
}
- protected def drawSlotBackground(x: Int, y: Int) {
- GlStateManager.color(1, 1, 1, 1)
+ protected def drawSlotBackground(stack: MatrixStack, x: Int, y: Int) {
+ RenderSystem.color4f(1, 1, 1, 1)
Textures.bind(Textures.GUI.Slot)
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y + 18, zLevel + 1).tex(0, 1).endVertex()
- r.pos(x + 18, y + 18, zLevel + 1).tex(1, 1).endVertex()
- r.pos(x + 18, y, zLevel + 1).tex(1, 0).endVertex()
- r.pos(x, y, zLevel + 1).tex(0, 0).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, x, y + 18, getBlitOffset + 1).uv(0, 1).endVertex()
+ r.vertex(stack.last.pose, x + 18, y + 18, getBlitOffset + 1).uv(1, 1).endVertex()
+ r.vertex(stack.last.pose, x + 18, y, getBlitOffset + 1).uv(1, 0).endVertex()
+ r.vertex(stack.last.pose, x, y, getBlitOffset + 1).uv(0, 0).endVertex()
+ t.end()
}
private def isInPlayerInventory(slot: Slot) = container match {
- case player: Player => slot.inventory == player.playerInventory
+ case player: Player => slot.container == player.playerInventory
case _ => false
}
-
- override def onGuiClosed(): Unit = {
- super.onGuiClosed()
- if(Mods.JustEnoughItems.isModAvailable) {
- resetJEIHighlights()
- }
- }
-
- @Optional.Method(modid = Mods.IDs.JustEnoughItems)
- private def drawJEIHighlights(): Unit = {
- ModJEI.runtime.foreach { runtime =>
- val overlay = runtime.getItemListOverlay
- hoveredSlot match {
- case Some(hovered) if !isInPlayerInventory(hovered) && isSelectiveSlot(hovered) =>
- overlay.highlightStacks(overlay.getVisibleStacks.filter(hovered.isItemValid))
- case _ => overlay.highlightStacks(List[Nothing]())
- }
- }
- }
-
- @Optional.Method(modid = Mods.IDs.JustEnoughItems)
- private def resetJEIHighlights() = ModJEI.runtime.foreach(_.getItemListOverlay.highlightStacks(List[Nothing]()))
}
diff --git a/src/main/scala/li/cil/oc/client/gui/GuiTypes.java b/src/main/scala/li/cil/oc/client/gui/GuiTypes.java
new file mode 100644
index 0000000000..f609824e7d
--- /dev/null
+++ b/src/main/scala/li/cil/oc/client/gui/GuiTypes.java
@@ -0,0 +1,38 @@
+package li.cil.oc.client.gui;
+
+import li.cil.oc.OpenComputers;
+import li.cil.oc.common.container.ContainerTypes;
+import net.minecraft.client.gui.ScreenManager;
+import net.minecraft.inventory.container.Container;
+import net.minecraft.inventory.container.ContainerType;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
+
+public final class GuiTypes {
+ @SubscribeEvent
+ public static void clientSetup(FMLClientSetupEvent e) {
+ // ScreenManager.register is not thread-safe.
+ e.enqueueWork(() -> {
+ ScreenManager.register(ContainerTypes.ADAPTER, Adapter::new);
+ ScreenManager.register(ContainerTypes.ASSEMBLER, Assembler::new);
+ ScreenManager.register(ContainerTypes.CASE, Case::new);
+ ScreenManager.register(ContainerTypes.CHARGER, Charger::new);
+ ScreenManager.register(ContainerTypes.DATABASE, Database::new);
+ ScreenManager.register(ContainerTypes.DISASSEMBLER, Disassembler::new);
+ ScreenManager.register(ContainerTypes.DISK_DRIVE, DiskDrive::new);
+ ScreenManager.register(ContainerTypes.DRONE, Drone::new);
+ ScreenManager.register(ContainerTypes.PRINTER, Printer::new);
+ ScreenManager.register(ContainerTypes.RACK, Rack::new);
+ ScreenManager.register(ContainerTypes.RAID, Raid::new);
+ ScreenManager.register(ContainerTypes.RELAY, Relay::new);
+ ScreenManager.register(ContainerTypes.ROBOT, Robot::new);
+ ScreenManager.register(ContainerTypes.SERVER, Server::new);
+ ScreenManager.register(ContainerTypes.TABLET, Tablet::new);
+ });
+ }
+
+ private GuiTypes() {
+ throw new Error();
+ }
+}
diff --git a/src/main/scala/li/cil/oc/client/gui/ImageButton.scala b/src/main/scala/li/cil/oc/client/gui/ImageButton.scala
index 837b665b49..7306483be0 100644
--- a/src/main/scala/li/cil/oc/client/gui/ImageButton.scala
+++ b/src/main/scala/li/cil/oc/client/gui/ImageButton.scala
@@ -1,84 +1,86 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.platform.GlStateManager
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.gui.AbstractGui
+import net.minecraft.client.gui.widget.button.Button
+import net.minecraft.client.gui.widget.button.Button.IPressable
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
import net.minecraft.util.ResourceLocation
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import org.lwjgl.opengl.GL11
-@SideOnly(Side.CLIENT)
-class ImageButton(id: Int, xPos: Int, yPos: Int, w: Int, h: Int,
+@OnlyIn(Dist.CLIENT)
+class ImageButton(xPos: Int, yPos: Int, w: Int, h: Int,
+ handler: IPressable,
val image: ResourceLocation = null,
- text: String = null,
+ text: ITextComponent = StringTextComponent.EMPTY,
val canToggle: Boolean = false,
val textColor: Int = 0xE0E0E0,
val textDisabledColor: Int = 0xA0A0A0,
val textHoverColor: Int = 0xFFFFA0,
- val textIndent: Int = -1) extends GuiButton(id, xPos, yPos, w, h, text) {
+ val textIndent: Int = -1) extends Button(xPos, yPos, w, h, text, handler) {
var toggled = false
var hoverOverride = false
- override def drawButton(mc: Minecraft, mouseX: Int, mouseY: Int, partialTicks: Float) {
+ override def renderButton(stack: MatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) {
if (visible) {
Textures.bind(image)
- GlStateManager.color(1, 1, 1, 1)
- hovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height
+ RenderSystem.color4f(1, 1, 1, 1)
+ isHovered = isMouseOver(mouseX, mouseY)
val x0 = x
val x1 = x + width
val y0 = y
val y1 = y + height
- val isHovered = hoverOverride || getHoverState(isMouseOver) == 2
+ val drawHover = hoverOverride || getYImage(isHovered) == 2
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
if (image != null) {
- val u0 = if (toggled) 0.5 else 0
- val u1 = u0 + (if (canToggle) 0.5 else 1)
- val v0 = if (hoverOverride || getHoverState(hovered) == 2) 0.5 else 0
- val v1 = v0 + 0.5
+ val u0 = if (toggled) 0.5f else 0
+ val u1 = u0 + (if (canToggle) 0.5f else 1)
+ val v0 = if (drawHover) 0.5f else 0
+ val v1 = v0 + 0.5f
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x0, y1, zLevel).tex(u0, v1).endVertex()
- r.pos(x1, y1, zLevel).tex(u1, v1).endVertex()
- r.pos(x1, y0, zLevel).tex(u1, v0).endVertex()
- r.pos(x0, y0, zLevel).tex(u0, v0).endVertex()
- }
- else if (isHovered) {
- GlStateManager.color(1, 1, 1, 0.8f)
-
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION)
- r.pos(x0, y1, zLevel).endVertex()
- r.pos(x1, y1, zLevel).endVertex()
- r.pos(x1, y0, zLevel).endVertex()
- r.pos(x0, y0, zLevel).endVertex()
+ r.vertex(stack.last.pose, x0, y1, getBlitOffset).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, x1, y1, getBlitOffset).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, x1, y0, getBlitOffset).uv(u1, v0).endVertex()
+ r.vertex(stack.last.pose, x0, y0, getBlitOffset).uv(u0, v0).endVertex()
+ t.end()
}
else {
- GlStateManager.color(1, 1, 1, 0.4f)
-
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION)
- r.pos(x0, y1, zLevel).endVertex()
- r.pos(x1, y1, zLevel).endVertex()
- r.pos(x1, y0, zLevel).endVertex()
- r.pos(x0, y0, zLevel).endVertex()
+ RenderSystem.enableBlend()
+ RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA)
+ val alpha = if (drawHover) 0.8f else 0.4f
+ r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR)
+ r.vertex(stack.last.pose, x0, y1, getBlitOffset).color(1, 1, 1, alpha).endVertex()
+ r.vertex(stack.last.pose, x1, y1, getBlitOffset).color(1, 1, 1, alpha).endVertex()
+ r.vertex(stack.last.pose, x1, y0, getBlitOffset).color(1, 1, 1, alpha).endVertex()
+ r.vertex(stack.last.pose, x0, y0, getBlitOffset).color(1, 1, 1, alpha).endVertex()
+ t.end()
+ RenderSystem.disableBlend()
}
- t.draw()
- if (displayString != null) {
+ if (getMessage != StringTextComponent.EMPTY) {
val color =
- if (!enabled) textDisabledColor
- else if (hoverOverride || hovered) textHoverColor
+ if (!active) textDisabledColor
+ else if (hoverOverride || isHovered) textHoverColor
else textColor
- if (textIndent >= 0) drawString(mc.fontRenderer, displayString, textIndent + x, y + (height - 8) / 2, color)
- else drawCenteredString(mc.fontRenderer, displayString, x + width / 2, y + (height - 8) / 2, color)
+ val mc = Minecraft.getInstance
+ if (textIndent >= 0) AbstractGui.drawString(stack, mc.font, getMessage, textIndent + x, y + (height - 8) / 2, color)
+ else AbstractGui.drawCenteredString(stack, mc.font, getMessage, x + width / 2, y + (height - 8) / 2, color)
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Manual.scala b/src/main/scala/li/cil/oc/client/gui/Manual.scala
index a5f7d6f8d1..cddcef15b8 100644
--- a/src/main/scala/li/cil/oc/client/gui/Manual.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Manual.scala
@@ -1,5 +1,7 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.api
import li.cil.oc.client.Textures
@@ -8,15 +10,19 @@ import li.cil.oc.client.renderer.markdown.segment.InteractiveSegment
import li.cil.oc.client.renderer.markdown.segment.Segment
import li.cil.oc.client.{Manual => ManualAPI}
import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.client.renderer.GlStateManager
-import org.lwjgl.input.Mouse
-
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
-
-class Manual extends GuiScreen with traits.Window {
+import net.minecraft.client.gui.screen
+import net.minecraft.client.gui.widget.button.Button
+import net.minecraft.client.util.InputMappings
+import net.minecraft.client.settings.KeyBinding
+import net.minecraft.util.text.ITextProperties
+import net.minecraft.util.text.StringTextComponent
+import org.lwjgl.glfw.GLFW
+
+import scala.collection.JavaConverters.{asJavaIterable, seqAsJavaList}
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
+
+class Manual extends screen.Screen(StringTextComponent.EMPTY) with traits.Window {
final val documentMaxWidth = 230
final val documentMaxHeight = 176
final val scrollPosX = 244
@@ -34,7 +40,7 @@ class Manual extends GuiScreen with traits.Window {
override def backgroundImage = Textures.GUI.Manual
- var isDragging = false
+ var isScrolling = false
var document: Segment = null
var documentHeight = 0
var currentSegment = None: Option[InteractiveSegment]
@@ -58,7 +64,7 @@ class Manual extends GuiScreen with traits.Window {
val content = Option(api.Manual.contentFor(ManualAPI.history.top.path)).
getOrElse(asJavaIterable(Iterable("Document not found: " + ManualAPI.history.top.path)))
document = Document.parse(content)
- documentHeight = Document.height(document, documentMaxWidth, fontRenderer)
+ documentHeight = Document.height(document, documentMaxWidth, font)
scrollTo(offset)
}
@@ -75,122 +81,143 @@ class Manual extends GuiScreen with traits.Window {
refreshPage()
}
else {
- Minecraft.getMinecraft.player.closeScreen()
- }
- }
-
- override def actionPerformed(button: GuiButton): Unit = {
- if (button.id >= 0 && button.id < ManualAPI.tabs.length) {
- api.Manual.navigate(ManualAPI.tabs(button.id).path)
+ onClose()
}
}
- override def initGui(): Unit = {
- super.initGui()
+ override protected def init(): Unit = {
+ super.init()
+ minecraft.mouseHandler.releaseMouse()
+ KeyBinding.releaseAll()
for ((tab, i) <- ManualAPI.tabs.zipWithIndex if i < maxTabsPerSide) {
- val x = guiLeft + tabPosX
- val y = guiTop + tabPosY + i * (tabHeight - 1)
- add(buttonList, new ImageButton(i, x, y, tabWidth, tabHeight, Textures.GUI.ManualTab))
+ val x = leftPos + tabPosX
+ val y = topPos + tabPosY + i * (tabHeight - 1)
+ addButton(new ImageButton(x, y, tabWidth, tabHeight, new Button.IPressable {
+ override def onPress(b: Button) = api.Manual.navigate(tab.path)
+ }, Textures.GUI.ManualTab))
}
- scrollButton = new ImageButton(-1, guiLeft + scrollPosX, guiTop + scrollPosY, 6, 13, Textures.GUI.ButtonScroll)
- add(buttonList, scrollButton)
+ scrollButton = new ImageButton(leftPos + scrollPosX, topPos + scrollPosY, 6, 13, new Button.IPressable {
+ override def onPress(b: Button) = ()
+ }, Textures.GUI.ButtonScroll)
+ addButton(scrollButton)
refreshPage()
}
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
- super.drawScreen(mouseX, mouseY, dt)
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float): Unit = {
+ super.render(stack, mouseX, mouseY, dt)
- scrollButton.enabled = canScroll
- scrollButton.hoverOverride = isDragging
+ scrollButton.active = canScroll
+ scrollButton.hoverOverride = isScrolling
for ((tab, i) <- ManualAPI.tabs.zipWithIndex if i < maxTabsPerSide) {
- val button = buttonList.get(i).asInstanceOf[ImageButton]
- GlStateManager.pushMatrix()
- GlStateManager.translate(button.x + 5, button.y + 5, zLevel)
- tab.renderer.render()
- GlStateManager.popMatrix()
+ val button = buttons.get(i).asInstanceOf[ImageButton]
+ stack.pushPose()
+ stack.translate(button.x + 5, button.y + 5, getBlitOffset)
+ tab.renderer.render(stack)
+ stack.popPose()
}
- currentSegment = Document.render(document, guiLeft + 8, guiTop + 8, documentMaxWidth, documentMaxHeight, offset, fontRenderer, mouseX, mouseY)
+ currentSegment = Document.render(stack, document, leftPos + 8, topPos + 8, documentMaxWidth, documentMaxHeight, offset, font, mouseX, mouseY)
+ def localizeAndWrap(text: String): java.util.List[_ <: ITextProperties] = {
+ val lines = Localization.localizeImmediately(text).lines.map(new StringTextComponent(_))
+ seqAsJavaList(lines.toSeq)
+ }
- if (!isDragging) currentSegment match {
+ if (!isScrolling) currentSegment match {
case Some(segment) =>
segment.tooltip match {
- case Some(text) if text.nonEmpty => drawHoveringText(seqAsJavaList(Localization.localizeImmediately(text).lines.toSeq), mouseX, mouseY, fontRenderer)
+ case Some(text) if text.nonEmpty => renderWrappedToolTip(stack, localizeAndWrap(text), mouseX, mouseY, font)
case _ =>
}
case _ =>
}
- if (!isDragging) for ((tab, i) <- ManualAPI.tabs.zipWithIndex if i < maxTabsPerSide) {
- val button = buttonList.get(i).asInstanceOf[ImageButton]
+ if (!isScrolling) for ((tab, i) <- ManualAPI.tabs.zipWithIndex if i < maxTabsPerSide) {
+ val button = buttons.get(i).asInstanceOf[ImageButton]
if (mouseX > button.x && mouseX < button.x + tabWidth && mouseY > button.y && mouseY < button.y + tabHeight) tab.tooltip.foreach(text => {
- drawHoveringText(seqAsJavaList(Localization.localizeImmediately(text).lines.toSeq), mouseX, mouseY, fontRenderer)
+ renderWrappedToolTip(stack, localizeAndWrap(text), mouseX, mouseY, font)
})
}
- if (canScroll && (isCoordinateOverScrollBar(mouseX - guiLeft, mouseY - guiTop) || isDragging)) {
- drawHoveringText(seqAsJavaList(Seq(s"${100 * offset / maxOffset}%")), guiLeft + scrollPosX + scrollWidth, scrollButton.y + scrollButton.height + 1, fontRenderer)
+ if (canScroll && (isCoordinateOverScrollBar(mouseX - leftPos, mouseY - topPos) || isScrolling)) {
+ val lines = seqAsJavaList(Seq(new StringTextComponent(s"${100 * offset / maxOffset}%")))
+ renderWrappedToolTip(stack, lines, leftPos + scrollPosX + scrollWidth, scrollButton.y + scrollButton.getHeight + 1, font)
}
}
- override def keyTyped(char: Char, code: Int): Unit = {
- if (code == mc.gameSettings.keyBindJump.getKeyCode) {
+ override def keyPressed(keyCode: Int, scanCode: Int, mods: Int): Boolean = {
+ val input = InputMappings.getKey(keyCode, scanCode)
+ if (minecraft.options.keyJump.isActiveAndMatches(input)) {
popPage()
+ return true
}
- else if (code == mc.gameSettings.keyBindInventory.getKeyCode) {
- mc.player.closeScreen()
+ if (minecraft.options.keyInventory.isActiveAndMatches(input)) {
+ onClose()
+ return true
}
- else super.keyTyped(char, code)
+ super.keyPressed(keyCode, scanCode, mods)
}
- override def handleMouseInput(): Unit = {
- super.handleMouseInput()
- if (Mouse.hasWheel && Mouse.getEventDWheel != 0) {
- if (math.signum(Mouse.getEventDWheel) < 0) scrollDown()
- else scrollUp()
- }
+ override def mouseScrolled(mouseX: Double, mouseY: Double, scroll: Double): Boolean = {
+ if (scroll < 0) scrollDown()
+ else scrollUp()
+ true
}
- override def mouseClicked(mouseX: Int, mouseY: Int, button: Int): Unit = {
- super.mouseClicked(mouseX, mouseY, button)
-
- if (canScroll && button == 0 && isCoordinateOverScrollBar(mouseX - guiLeft, mouseY - guiTop)) {
- isDragging = true
+ override def mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean = {
+ val (mcx, mcy) = (mouseX.asInstanceOf[Int] - leftPos, mouseY.asInstanceOf[Int] - topPos)
+ if (canScroll && button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isCoordinateOverScrollBar(mcx, mcy)) {
+ isScrolling = true
scrollMouse(mouseY)
+ return true
}
- else if (button == 0) currentSegment.foreach(_.onMouseClick(mouseX, mouseY))
- else if (button == 1) popPage()
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isCoordinateOverContent(mcx, mcy)) {
+ if (currentSegment.exists(_.onMouseClick(mouseX.asInstanceOf[Int], mouseY.asInstanceOf[Int]))) {
+ return true
+ }
+ }
+ if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
+ popPage()
+ return true
+ }
+ super.mouseClicked(mouseX, mouseY, button)
}
- override protected def mouseClickMove(mouseX: Int, mouseY: Int, lastButtonClicked: Int, timeSinceMouseClick: Long) {
- super.mouseClickMove(mouseX, mouseY, lastButtonClicked, timeSinceMouseClick)
- if (isDragging) {
+ override def mouseMoved(mouseX: Double, mouseY: Double): Unit = {
+ if (isScrolling) scrollMouse(mouseY)
+ super.mouseMoved(mouseX, mouseY)
+ }
+
+ override def mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean = {
+ if (isScrolling) {
scrollMouse(mouseY)
+ return true
}
+ super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
}
- override protected def mouseReleased(mouseX: Int, mouseY: Int, button: Int) {
- super.mouseReleased(mouseX, mouseY, button)
- if (button == 0) {
- isDragging = false
+ override def mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean = {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isScrolling) {
+ isScrolling = false
+ return true
}
+ super.mouseReleased(mouseX, mouseY, button)
}
- private def scrollMouse(mouseY: Int) {
- scrollTo(math.round((mouseY - guiTop - scrollPosY - 6.5) * maxOffset / (scrollHeight - 13.0)).toInt)
+ private def scrollMouse(mouseY: Double) {
+ scrollTo(math.round((mouseY - topPos - scrollPosY - 6.5) * maxOffset / (scrollHeight - 13.0)).toInt)
}
- private def scrollUp() = scrollTo(offset - Document.lineHeight(fontRenderer) * 3)
+ private def scrollUp() = scrollTo(offset - Document.lineHeight(font) * 3)
- private def scrollDown() = scrollTo(offset + Document.lineHeight(fontRenderer) * 3)
+ private def scrollDown() = scrollTo(offset + Document.lineHeight(font) * 3)
private def scrollTo(row: Int): Unit = {
ManualAPI.history.top.offset = math.max(0, math.min(maxOffset, row))
- val yMin = guiTop + scrollPosY
+ val yMin = topPos + scrollPosY
if (maxOffset > 0) {
scrollButton.y = yMin + (scrollHeight - 13) * offset / maxOffset
}
@@ -199,7 +226,11 @@ class Manual extends GuiScreen with traits.Window {
}
}
+ private def isCoordinateOverContent(x: Int, y: Int) =
+ x >= 8 && x < 8 + documentMaxWidth &&
+ y >= 8 && y < 8 + documentMaxHeight
+
private def isCoordinateOverScrollBar(x: Int, y: Int) =
- x > scrollPosX && x < scrollPosX + scrollWidth &&
+ x >= scrollPosX && x < scrollPosX + scrollWidth &&
y >= scrollPosY && y < scrollPosY + scrollHeight
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Printer.scala b/src/main/scala/li/cil/oc/client/gui/Printer.scala
index 41a96f69e9..ce20911a96 100644
--- a/src/main/scala/li/cil/oc/client/gui/Printer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Printer.scala
@@ -1,34 +1,36 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import li.cil.oc.client.gui.widget.ProgressBar
import li.cil.oc.common.container
import li.cil.oc.common.container.ComponentSlot
-import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends DynamicGuiContainer(new container.Printer(playerInventory, printer)) {
- xSize = 176
- ySize = 166
+class Printer(state: container.Printer, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
- private val materialBar = addWidget(new ProgressBar(40, 21) {
+ imageWidth = 176
+ imageHeight = 166
+
+ private val materialBar = addCustomWidget(new ProgressBar(40, 21) {
override def width = 62
override def height = 12
override def barTexture = Textures.GUI.PrinterMaterial
})
- private val inkBar = addWidget(new ProgressBar(40, 53) {
+ private val inkBar = addCustomWidget(new ProgressBar(40, 53) {
override def width = 62
override def height = 12
override def barTexture = Textures.GUI.PrinterInk
})
- private val progressBar = addWidget(new ProgressBar(105, 20) {
+ private val progressBar = addCustomWidget(new ProgressBar(105, 20) {
override def width = 46
override def height = 46
@@ -36,39 +38,32 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer)
override def barTexture = Textures.GUI.PrinterProgress
})
- override def initGui() {
- super.initGui()
- }
-
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(printer.getName),
- 8, 6, 0x404040)
+ override def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(stack, mouseX, mouseY)
RenderState.pushAttrib()
- if (isPointInRegion(materialBar.x, materialBar.y, materialBar.width, materialBar.height, mouseX, mouseY)) {
+ if (isPointInRegion(materialBar.x, materialBar.y, materialBar.width, materialBar.height, mouseX - leftPos, mouseY - topPos)) {
val tooltip = new java.util.ArrayList[String]
- tooltip.add(inventoryContainer.amountMaterial + "/" + printer.maxAmountMaterial)
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ tooltip.add(inventoryContainer.amountMaterial + "/" + inventoryContainer.maxAmountMaterial)
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
- if (isPointInRegion(inkBar.x, inkBar.y, inkBar.width, inkBar.height, mouseX, mouseY)) {
+ if (isPointInRegion(inkBar.x, inkBar.y, inkBar.width, inkBar.height, mouseX - leftPos, mouseY - topPos)) {
val tooltip = new java.util.ArrayList[String]
- tooltip.add(inventoryContainer.amountInk + "/" + printer.maxAmountInk)
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ tooltip.add(inventoryContainer.amountInk + "/" + inventoryContainer.maxAmountInk)
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
RenderState.popAttrib()
}
- override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1)
+ override def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color3f(1, 1, 1)
Textures.bind(Textures.GUI.Printer)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
- materialBar.level = inventoryContainer.amountMaterial / printer.maxAmountMaterial.toDouble
- inkBar.level = inventoryContainer.amountInk / printer.maxAmountInk.toDouble
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
+ materialBar.level = inventoryContainer.amountMaterial / inventoryContainer.maxAmountMaterial.toDouble
+ inkBar.level = inventoryContainer.amountInk / inventoryContainer.maxAmountInk.toDouble
progressBar.level = inventoryContainer.progress
- drawWidgets()
- drawInventorySlots()
+ drawWidgets(stack)
+ drawInventorySlots(stack)
}
- override protected def drawDisabledSlot(slot: ComponentSlot) {}
+ override protected def drawDisabledSlot(stack: MatrixStack, slot: ComponentSlot) {}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Rack.scala b/src/main/scala/li/cil/oc/client/gui/Rack.scala
index 8929fe3ac2..c2bac7f5b6 100644
--- a/src/main/scala/li/cil/oc/client/gui/Rack.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Rack.scala
@@ -1,23 +1,27 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.gui.widget.button.Button
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.util.EnumFacing
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.Direction
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import org.lwjgl.opengl.GL11
-import scala.collection.convert.WrapAsJava.asJavaCollection
+import scala.collection.JavaConverters.asJavaCollection
-class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends DynamicGuiContainer(new container.Rack(playerInventory, rack)) {
- ySize = 210
+class Rack(state: container.Rack, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
+
+ imageHeight = 210
final val busMasterBlankUVs = (195, 14, 3, 5)
final val busMasterPresentUVs = (194, 20, 5, 5)
@@ -73,109 +77,94 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
(83, 104)
)
- final val busToSide = EnumFacing.values().filter(_ != EnumFacing.SOUTH)
+ final val busToSide = Direction.values().filter(_ != Direction.SOUTH)
final val sideToBus = busToSide.zipWithIndex.toMap
var relayButton: ImageButton = _
// bus -> mountable -> connectable
- var wireButtons = Array.fill(rack.getSizeInventory)(Array.fill(4)(Array.fill(5)(null: ImageButton)))
-
- def sideName(side: EnumFacing) = side match {
- case EnumFacing.UP => Localization.Rack.Top
- case EnumFacing.DOWN => Localization.Rack.Bottom
- case EnumFacing.EAST => Localization.Rack.Left
- case EnumFacing.WEST => Localization.Rack.Right
- case EnumFacing.NORTH => Localization.Rack.Back
+ var wireButtons = Array.fill(inventoryContainer.otherInventory.getContainerSize)(Array.fill(4)(Array.fill(5)(null: ImageButton)))
+
+ def sideName(side: Direction) = side match {
+ case Direction.UP => Localization.Rack.Top
+ case Direction.DOWN => Localization.Rack.Bottom
+ case Direction.EAST => Localization.Rack.Left
+ case Direction.WEST => Localization.Rack.Right
+ case Direction.NORTH => Localization.Rack.Back
case _ => Localization.Rack.None
}
- def encodeButtonId(mountable: Int, connectable: Int, bus: Int) = {
- // +1 to offset for relay button
- 1 + mountable * 4 * 5 + connectable * 5 + bus
- }
-
- def decodeButtonId(buttonId: Int) = {
- // -1 to offset for relay button
- val bus = (buttonId - 1) % 5
- val connectable = ((buttonId - 1) / 5) % 4
- val mountable = (buttonId - 1) / 5 / 4
- (mountable, connectable, bus)
- }
-
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0) {
- ClientPacketSender.sendRackRelayState(rack, !rack.isRelayEnabled)
+ protected def onRackButton(mountable: Int, connectable: Int, bus: Int) {
+ if (inventoryContainer.nodeMapping(mountable)(connectable).contains(busToSide(bus))) {
+ ClientPacketSender.sendRackMountableMapping(inventoryContainer, mountable, connectable, None)
}
else {
- val (mountable, connectable, bus) = decodeButtonId(button.id)
- if (rack.nodeMapping(mountable)(connectable).contains(busToSide(bus))) {
- ClientPacketSender.sendRackMountableMapping(rack, mountable, connectable, None)
- }
- else {
- ClientPacketSender.sendRackMountableMapping(rack, mountable, connectable, Option(busToSide(bus)))
- }
+ ClientPacketSender.sendRackMountableMapping(inventoryContainer, mountable, connectable, Option(busToSide(bus)))
}
}
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float) {
for (bus <- 0 until 5) {
- for (mountable <- 0 until rack.getSizeInventory) {
+ for (mountable <- 0 until inventoryContainer.otherInventory.getContainerSize) {
val presence = inventoryContainer.nodePresence(mountable)
for (connectable <- 0 until 4) {
wireButtons(mountable)(connectable)(bus).visible = presence(connectable)
}
}
}
- relayButton.displayString = if (rack.isRelayEnabled) Localization.Rack.RelayEnabled else Localization.Rack.RelayDisabled
- super.drawScreen(mouseX, mouseY, dt)
+ val relayMessage = if (inventoryContainer.isRelayEnabled) Localization.Rack.RelayEnabled else Localization.Rack.RelayDisabled
+ relayButton.setMessage(new StringTextComponent(relayMessage))
+ super.render(stack, mouseX, mouseY, dt)
}
- override def initGui() {
- super.initGui()
+ override protected def init() {
+ super.init()
- relayButton = new ImageButton(0, guiLeft + 101, guiTop + 96, 65, 18, Textures.GUI.ButtonRelay, Localization.Rack.RelayDisabled, textIndent = 18)
- add(buttonList, relayButton)
+ relayButton = new ImageButton(leftPos + 101, topPos + 96, 65, 18, new Button.IPressable {
+ override def onPress(b: Button) = ClientPacketSender.sendRackRelayState(inventoryContainer, !inventoryContainer.isRelayEnabled)
+ }, Textures.GUI.ButtonRelay, new StringTextComponent(Localization.Rack.RelayDisabled), textIndent = 18)
+ addButton(relayButton)
val (mw, mh) = hoverMasterSize
val (sw, sh) = hoverSlaveSize
val (_, _, _, mbh) = busMasterBlankUVs
val (_, _, _, sbh) = busSlaveBlankUVs
for (bus <- 0 until 5) {
- for (mountable <- 0 until rack.getSizeInventory) {
+ for (mountable <- 0 until inventoryContainer.otherInventory.getContainerSize) {
val offset = mountable * (mbh + sbh * 3 + busGap)
val (bx, by) = busStart(bus)
{
- val button = new ImageButton(encodeButtonId(mountable, 0, bus), guiLeft + bx, guiTop + by + offset + 1, mw, mh)
- add(buttonList, button)
+ val button = new ImageButton(leftPos + bx, topPos + by + offset + 1, mw, mh, new Button.IPressable {
+ override def onPress(b: Button) = onRackButton(mountable, 0, bus)
+ })
+ addButton(button)
wireButtons(mountable)(0)(bus) = button
}
for (connectable <- 0 until 3) {
- val button = new ImageButton(encodeButtonId(mountable, connectable + 1, bus), guiLeft + bx, guiTop + by + offset + 1 + mbh + sbh * connectable, sw, sh)
- add(buttonList, button)
+ val button = new ImageButton(leftPos + bx, topPos + by + offset + 1 + mbh + sbh * connectable, sw, sh, new Button.IPressable {
+ override def onPress(b: Button) = onRackButton(mountable, connectable + 1, bus)
+ })
+ addButton(button)
wireButtons(mountable)(connectable + 1)(bus) = button
}
}
}
}
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(stack, mouseX, mouseY)
RenderState.pushAttrib() // Prevents NEI render glitch.
- fontRenderer.drawString(
- Localization.localizeImmediately(rack.getName),
- 8, 6, 0x404040)
-
- GlStateManager.color(1, 1, 1)
- mc.renderEngine.bindTexture(Textures.GUI.Rack)
+ RenderSystem.color4f(1, 1, 1, 1)
+ RenderState.makeItBlend()
+ minecraft.getTextureManager.bind(Textures.GUI.Rack)
- if (rack.isRelayEnabled) {
+ if (inventoryContainer.isRelayEnabled) {
val (left, top, w, h) = relayModeUVs
for ((x, y) <- wireRelay) {
- drawRect(x, y, w, h, left, top)
+ drawRect(stack, x, y, w, h, left, top)
}
}
@@ -185,32 +174,32 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
val (scx, scy, scw, sch) = connectorSlaveUVs
val (sbx, sby, sbw, sbh) = busSlaveBlankUVs
val (spx, spy, spw, sph) = busSlavePresentUVs
- for (mountable <- 0 until rack.getSizeInventory) {
+ for (mountable <- 0 until inventoryContainer.otherInventory.getContainerSize) {
val presence = inventoryContainer.nodePresence(mountable)
// Draw connectable indicators next to item slots.
val (cx, cy) = connectorStart(mountable)
if (presence(0)) {
- drawRect(cx, cy, mcw, mch, mcx, mcy)
- rack.nodeMapping(mountable)(0) match {
+ drawRect(stack, cx, cy, mcw, mch, mcx, mcy)
+ inventoryContainer.nodeMapping(mountable)(0) match {
case Some(side) =>
val bus = sideToBus(side)
val (mwx, mwy, mww, mwh) = wireMasterUVs(bus)
for (i <- 0 to bus) {
val xOffset = mcw + i * (mpw + mww)
- drawRect(cx + xOffset, cy, mww, mwh, mwx, mwy)
+ drawRect(stack, cx + xOffset, cy, mww, mwh, mwx, mwy)
}
case _ =>
}
for (connectable <- 1 until 4) {
- rack.nodeMapping(mountable)(connectable) match {
+ inventoryContainer.nodeMapping(mountable)(connectable) match {
case Some(side) =>
val bus = sideToBus(side)
val (swx, swy, sww, swh) = wireSlaveUVs(bus)
val yOffset = (mch + connectorGap) + (sch + connectorGap) * (connectable - 1)
for (i <- 0 to bus) {
val xOffset = scw + i * (spw + sww)
- drawRect(cx + xOffset, cy + yOffset, sww, swh, swx, swy)
+ drawRect(stack, cx + xOffset, cy + yOffset, sww, swh, swx, swy)
}
case _ =>
}
@@ -219,7 +208,7 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
for (connectable <- 1 until 4) {
if (presence(connectable)) {
val yOffset = (mch + connectorGap) + (sch + connectorGap) * (connectable - 1)
- drawRect(cx, cy + yOffset, scw, sch, scx, scy)
+ drawRect(stack, cx, cy + yOffset, scw, sch, scx, scy)
}
}
@@ -228,17 +217,17 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
for (bus <- 0 until 5) {
val (bx, by) = busStart(bus)
if (presence(0)) {
- drawRect(bx - 1, by + yOffset, mpw, mph, mpx, mpy)
+ drawRect(stack, bx - 1, by + yOffset, mpw, mph, mpx, mpy)
}
else {
- drawRect(bx, by + yOffset, mbw, mbh, mbx, mby)
+ drawRect(stack, bx, by + yOffset, mbw, mbh, mbx, mby)
}
for (connectable <- 0 until 3) {
if (presence(connectable + 1)) {
- drawRect(bx - 1, by + yOffset + mph + sph * connectable, spw, sph, spx, spy)
+ drawRect(stack, bx - 1, by + yOffset + mph + sph * connectable, spw, sph, spx, spy)
}
else {
- drawRect(bx, by + yOffset + mbh + sbh * connectable, sbw, sbh, sbx, sby)
+ drawRect(stack, bx, by + yOffset + mbh + sbh * connectable, sbw, sbh, sbx, sby)
}
}
}
@@ -248,38 +237,38 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
val x = 122
val y = 20 + bus * 11
- fontRenderer.drawString(
+ font.draw(stack,
Localization.localizeImmediately(sideName(busToSide(bus))),
x, y, 0x404040)
}
- if (relayButton.isMouseOver) {
+ if (relayButton.isMouseOver(mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
tooltip.addAll(asJavaCollection(Localization.Rack.RelayModeTooltip.lines.toIterable))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
RenderState.popAttrib()
}
- override def drawSecondaryBackgroundLayer() {
- GlStateManager.color(1, 1, 1) // Required under Linux.
- mc.renderEngine.bindTexture(Textures.GUI.Rack)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ override def drawSecondaryBackgroundLayer(stack: MatrixStack) {
+ RenderSystem.color3f(1, 1, 1) // Required under Linux.
+ minecraft.getTextureManager.bind(Textures.GUI.Rack)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
}
- private def drawRect(x: Int, y: Int, w: Int, h: Int, u: Int, v: Int): Unit = {
+ private def drawRect(stack: MatrixStack, x: Int, y: Int, w: Int, h: Int, u: Int, v: Int): Unit = {
val u0 = u / 256f
val v0 = v / 256f
val u1 = u0 + w / 256f
val v1 = v0 + h / 256f
val t = Tessellator.getInstance()
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y, windowZ).tex(u0, v0).endVertex()
- r.pos(x, y + h, windowZ).tex(u0, v1).endVertex()
- r.pos(x + w, y + h, windowZ).tex(u1, v1).endVertex()
- r.pos(x + w, y, windowZ).tex(u1, v0).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, x, y, windowZ).uv(u0, v0).endVertex()
+ r.vertex(stack.last.pose, x, y + h, windowZ).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, x + w, y + h, windowZ).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, x + w, y, windowZ).uv(u1, v0).endVertex()
+ t.end()
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Raid.scala b/src/main/scala/li/cil/oc/client/gui/Raid.scala
index 56e75f707e..ffd2ba6706 100644
--- a/src/main/scala/li/cil/oc/client/gui/Raid.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Raid.scala
@@ -1,27 +1,18 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Raid(playerInventory: InventoryPlayer, val raid: tileentity.Raid) extends DynamicGuiContainer(new container.Raid(playerInventory, raid)) {
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(raid.getName),
- 8, 6, 0x404040)
+class Raid(state: container.Raid, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
- fontRenderer.drawSplitString(
- Localization.Raid.Warning,
- 8, 46, 0x404040, width - 16)
- }
-
- override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1) // Required under Linux.
+ override def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color3f(1, 1, 1) // Required under Linux.
Textures.bind(Textures.GUI.Raid)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Relay.scala b/src/main/scala/li/cil/oc/client/gui/Relay.scala
index fcbe9d50a4..93684d6fb7 100644
--- a/src/main/scala/li/cil/oc/client/gui/Relay.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Relay.scala
@@ -2,90 +2,90 @@ package li.cil.oc.client.gui
import java.text.DecimalFormat
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
import net.minecraft.client.renderer.Tessellator
+import net.minecraft.client.renderer.Rectangle2d
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
import org.lwjgl.opengl.GL11
-import org.lwjgl.util.Rectangle
-class Relay(playerInventory: InventoryPlayer, val relay: tileentity.Relay) extends DynamicGuiContainer(new container.Relay(playerInventory, relay)) {
+class Relay(state: container.Relay, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name) {
+
private val format = new DecimalFormat("#.##hz")
- val tabPosition = new Rectangle(xSize, 10, 23, 26)
+ val tabPosition = new Rectangle2d(imageWidth, 10, 23, 26)
- override protected def drawSecondaryBackgroundLayer(): Unit = {
- super.drawSecondaryBackgroundLayer()
+ override protected def drawSecondaryBackgroundLayer(stack: MatrixStack): Unit = {
+ super.drawSecondaryBackgroundLayer(stack)
// Tab background.
- GlStateManager.color(1, 1, 1, 1)
- Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.GUI.UpgradeTab)
+ RenderSystem.color4f(1, 1, 1, 1)
+ Minecraft.getInstance.getTextureManager.bind(Textures.GUI.UpgradeTab)
val x = windowX + tabPosition.getX
val y = windowY + tabPosition.getY
val w = tabPosition.getWidth
val h = tabPosition.getHeight
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y + h, zLevel).tex(0, 1).endVertex()
- r.pos(x + w, y + h, zLevel).tex(1, 1).endVertex()
- r.pos(x + w, y, zLevel).tex(1, 0).endVertex()
- r.pos(x, y, zLevel).tex(0, 0).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, x, y + h, getBlitOffset).uv(0, 1).endVertex()
+ r.vertex(stack.last.pose, x + w, y + h, getBlitOffset).uv(1, 1).endVertex()
+ r.vertex(stack.last.pose, x + w, y, getBlitOffset).uv(1, 0).endVertex()
+ r.vertex(stack.last.pose, x, y, getBlitOffset).uv(0, 0).endVertex()
+ t.end()
}
- override def mouseClicked(mouseX: Int, mouseY: Int, button: Int): Unit = {
+ override def mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean = {
// So MC doesn't throw away the item in the upgrade slot when we're trying to pick it up...
- val originalWidth = xSize
+ val originalWidth = imageWidth
try {
- xSize += tabPosition.getWidth
+ imageWidth += tabPosition.getWidth
super.mouseClicked(mouseX, mouseY, button)
}
finally {
- xSize = originalWidth
+ imageWidth = originalWidth
}
}
- override def mouseReleased(mouseX: Int, mouseY: Int, button: Int): Unit = {
+ override def mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean = {
// So MC doesn't throw away the item in the upgrade slot when we're trying to pick it up...
- val originalWidth = xSize
+ val originalWidth = imageWidth
try {
- xSize += tabPosition.getWidth
+ imageWidth += tabPosition.getWidth
super.mouseReleased(mouseX, mouseY, button)
}
finally {
- xSize = originalWidth
+ imageWidth = originalWidth
}
}
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int): Unit = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(relay.getName),
- 8, 6, 0x404040)
+ override def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int): Unit = {
+ super.drawSecondaryForegroundLayer(stack, mouseX, mouseY)
- fontRenderer.drawString(
+ font.draw(stack,
Localization.Switch.TransferRate,
14, 20, 0x404040)
- fontRenderer.drawString(
+ font.draw(stack,
Localization.Switch.PacketsPerCycle,
14, 39, 0x404040)
- fontRenderer.drawString(
+ font.draw(stack,
Localization.Switch.QueueSize,
14, 58, 0x404040)
- fontRenderer.drawString(
+ font.draw(stack,
format.format(20f / inventoryContainer.relayDelay),
108, 20, 0x404040)
- fontRenderer.drawString(
+ font.draw(stack,
inventoryContainer.packetsPerCycleAvg + " / " + inventoryContainer.relayAmount,
108, 39, thresholdBasedColor(inventoryContainer.packetsPerCycleAvg, math.ceil(inventoryContainer.relayAmount / 2f).toInt, inventoryContainer.relayAmount))
- fontRenderer.drawString(
+ font.draw(stack,
inventoryContainer.queueSize + " / " + inventoryContainer.maxQueueSize,
108, 58, thresholdBasedColor(inventoryContainer.queueSize, inventoryContainer.maxQueueSize / 2, inventoryContainer.maxQueueSize))
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Robot.scala b/src/main/scala/li/cil/oc/client/gui/Robot.scala
index a2ad0ec5dd..e69a3987f8 100644
--- a/src/main/scala/li/cil/oc/client/gui/Robot.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Robot.scala
@@ -1,43 +1,50 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.internal.TextBuffer
+import li.cil.oc.client.ComponentTracker
import li.cil.oc.client.Textures
import li.cil.oc.client.gui.widget.ProgressBar
import li.cil.oc.client.renderer.TextBufferRenderCache
import li.cil.oc.client.renderer.gui.BufferRenderer
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.container
-import li.cil.oc.common.tileentity
-import li.cil.oc.integration.opencomputers
-import li.cil.oc.util.RenderState
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.INestedGuiEventHandler
+import net.minecraft.client.gui.widget.button.Button
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.player.InventoryPlayer
-import org.lwjgl.input.Keyboard
-import org.lwjgl.input.Mouse
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
+import org.lwjgl.glfw.GLFW
import org.lwjgl.opengl.GL11
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaCollection
+import scala.collection.convert.ImplicitConversionsToJava._
-class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) extends DynamicGuiContainer(new container.Robot(playerInventory, robot)) with traits.InputBuffer {
- override protected val buffer: TextBuffer = robot.components.collect {
- case Some(buffer: api.internal.TextBuffer) => buffer
- }.headOption.orNull
+class Robot(state: container.Robot, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name)
+ with traits.InputBuffer with INestedGuiEventHandler {
- override protected val hasKeyboard: Boolean = robot.info.components.map(api.Driver.driverFor(_, robot.getClass)).contains(opencomputers.DriverKeyboard)
+ override protected val buffer: TextBuffer = inventoryContainer.info.screenBuffer
+ .flatMap(ComponentTracker.get(Minecraft.getInstance.level, _))
+ .collectFirst {
+ case buffer: TextBuffer => buffer
+ }.orNull
+
+ override protected val hasKeyboard: Boolean = inventoryContainer.info.hasKeyboard
private val withScreenHeight = 256
private val noScreenHeight = 108
private val deltaY = if (buffer != null) 0 else withScreenHeight - noScreenHeight
- xSize = 256
- ySize = 256 - deltaY
+ imageWidth = 256
+ imageHeight = 256 - deltaY
protected var powerButton: ImageButton = _
@@ -45,11 +52,11 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
// Scroll offset for robot inventory.
private var inventoryOffset = 0
- private var isDragging = false
+ var isScrolling = false
- private def canScroll = robot.inventorySize > 16
+ private def canScroll = inventoryContainer.info.mainInvSize > 16
- private def maxOffset = robot.inventorySize / 4 - 4
+ private def maxOffset = inventoryContainer.info.mainInvSize / 4 - 4
private val slotSize = 18
@@ -70,142 +77,141 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
private val scrollX = inventoryX + slotSize * 4 + 2
private val scrollY = inventoryY
private val scrollWidth = 8
- private val scrollHeight = 94
+ private val scrollHeight = 92
- private val power = addWidget(new ProgressBar(26, 156 - deltaY))
+ private val power = addCustomWidget(new ProgressBar(26, 156 - deltaY))
private val selectionSize = 20
private val selectionsStates = 17
- private val selectionStepV = 1 / selectionsStates.toDouble
-
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0) {
- ClientPacketSender.sendComputerPower(robot, !robot.isRunning)
- }
- }
-
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
- powerButton.toggled = robot.isRunning
- scrollButton.enabled = canScroll
- scrollButton.hoverOverride = isDragging
- if (robot.inventorySize < 16 + inventoryOffset * 4) {
- scrollTo(0)
+ private val selectionStepV = 1 / selectionsStates.toFloat
+
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float) {
+ powerButton.toggled = inventoryContainer.isRunning
+ scrollButton.active = canScroll
+ scrollButton.hoverOverride = isScrolling
+ if (inventoryContainer.info.mainInvSize < 16 + inventoryOffset * 4) {
+ if (inventoryOffset != 0) scrollTo(0)
}
- super.drawScreen(mouseX, mouseY, dt)
+ super.render(stack, mouseX, mouseY, dt)
}
- override def initGui() {
- super.initGui()
- powerButton = new ImageButton(0, guiLeft + 5, guiTop + 153 - deltaY, 18, 18, Textures.GUI.ButtonPower, canToggle = true)
- scrollButton = new ImageButton(1, guiLeft + scrollX + 1, guiTop + scrollY + 1, 6, 13, Textures.GUI.ButtonScroll)
- add(buttonList, powerButton)
- add(buttonList, scrollButton)
+ override protected def init() {
+ super.init()
+ powerButton = new ImageButton(leftPos + 5, topPos + 153 - deltaY, 18, 18, new Button.IPressable {
+ override def onPress(b: Button) = ClientPacketSender.sendRobotPower(inventoryContainer, !inventoryContainer.isRunning)
+ }, Textures.GUI.ButtonPower, canToggle = true)
+ scrollButton = new ImageButton(leftPos + scrollX + 1, topPos + scrollY + 1, 6, 13, new Button.IPressable {
+ override def onPress(b: Button) = ()
+ }, Textures.GUI.ButtonScroll)
+ addButton(powerButton)
+ addButton(scrollButton)
}
- override def drawBuffer() {
+ override def drawBuffer(stack: MatrixStack) {
if (buffer != null) {
- GlStateManager.translate(bufferX, bufferY, 0)
- RenderState.disableEntityLighting()
- GlStateManager.pushMatrix()
- GlStateManager.translate(-3, -3, 0)
- GlStateManager.color(1, 1, 1, 1)
- BufferRenderer.drawBackground()
- GlStateManager.popMatrix()
- RenderState.makeItBlend()
+ stack.translate(bufferX, bufferY, 0)
+ stack.pushPose()
+ stack.translate(-3, -3, 0)
+ RenderSystem.color4f(1, 1, 1, 1)
+ BufferRenderer.drawBackground(stack, bufferRenderWidth.toInt, bufferRenderHeight.toInt, forRobot = true)
+ stack.popPose()
val scaleX = bufferRenderWidth / buffer.renderWidth
val scaleY = bufferRenderHeight / buffer.renderHeight
- val scale = math.min(scaleX, scaleY)
+ val scale = math.min(scaleX, scaleY).toFloat
if (scaleX > scale) {
- GlStateManager.translate(buffer.renderWidth * (scaleX - scale) / 2, 0, 0)
+ stack.translate(buffer.renderWidth * (scaleX - scale) / 2, 0, 0)
}
else if (scaleY > scale) {
- GlStateManager.translate(0, buffer.renderHeight * (scaleY - scale) / 2, 0)
+ stack.translate(0, buffer.renderHeight * (scaleY - scale) / 2, 0)
}
- GlStateManager.scale(scale, scale, scale)
- GlStateManager.scale(this.scale, this.scale, 1)
- BufferRenderer.drawText(buffer)
+ stack.scale(scale, scale, scale)
+ stack.scale(this.scale.toFloat, this.scale.toFloat, 1)
+ BufferRenderer.drawText(stack, buffer)
}
}
- override protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
- drawBufferLayer()
- RenderState.pushAttrib()
- if (isPointInRegion(power.x, power.y, power.width, power.height, mouseX, mouseY)) {
+ override protected def renderLabels(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ drawSecondaryForegroundLayer(stack, mouseX, mouseY)
+
+ for (slot <- 0 until menu.slots.size()) {
+ drawSlotHighlight(stack, menu.getSlot(slot))
+ }
+ }
+
+ override protected def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ drawBufferLayer(stack)
+ if (isPointInRegion(power.x, power.y, power.width, power.height, mouseX - leftPos, mouseY - topPos)) {
val tooltip = new java.util.ArrayList[String]
val format = Localization.Computer.Power + ": %d%% (%d/%d)"
tooltip.add(format.format(
- ((robot.globalBuffer / robot.globalBufferSize) * 100).toInt,
- robot.globalBuffer.toInt,
- robot.globalBufferSize.toInt))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ 100 * inventoryContainer.globalBuffer / inventoryContainer.globalBufferSize,
+ inventoryContainer.globalBuffer, inventoryContainer.globalBufferSize))
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
- if (powerButton.isMouseOver) {
+ if (powerButton.isMouseOver(mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
- tooltip.addAll(asJavaCollection(if (robot.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
+ tooltip.addAll(asJavaCollection(if (inventoryContainer.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
}
- RenderState.popAttrib()
}
- override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
- GlStateManager.color(1, 1, 1)
+ override protected def renderBg(stack: MatrixStack, dt: Float, mouseX: Int, mouseY: Int) {
+ RenderSystem.color4f(1, 1, 1, 1)
if (buffer != null) Textures.bind(Textures.GUI.Robot)
else Textures.bind(Textures.GUI.RobotNoScreen)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
- power.level = robot.globalBuffer / robot.globalBufferSize
- drawWidgets()
- if (robot.inventorySize > 0) {
- drawSelection()
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
+ power.level = inventoryContainer.globalBuffer.toDouble / inventoryContainer.globalBufferSize
+ drawWidgets(stack)
+ if (inventoryContainer.info.mainInvSize > 0) {
+ drawSelection(stack)
}
- drawInventorySlots()
+ drawInventorySlots(stack)
}
// No custom slots, we just extend DynamicGuiContainer for the highlighting.
- override protected def drawSlotBackground(x: Int, y: Int) {}
+ override protected def drawSlotBackground(stack: MatrixStack, x: Int, y: Int) {}
- override protected def keyTyped(char: Char, code: Int) {
- if (code == Keyboard.KEY_ESCAPE) {
- super.keyTyped(char, code)
- }
- }
-
- override protected def mouseClicked(mouseX: Int, mouseY: Int, button: Int) {
- super.mouseClicked(mouseX, mouseY, button)
- if (canScroll && button == 0 && isCoordinateOverScrollBar(mouseX - guiLeft, mouseY - guiTop)) {
- isDragging = true
+ override def mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean = {
+ val mx = mouseX.asInstanceOf[Int]
+ val my = mouseY.asInstanceOf[Int]
+ if (canScroll && button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isCoordinateOverScrollBar(mx - leftPos, my - topPos)) {
+ isScrolling = true
scrollMouse(mouseY)
+ true
}
+ else super.mouseClicked(mouseX, mouseY, button)
}
- override protected def mouseReleased(mouseX: Int, mouseY: Int, button: Int) {
- super.mouseReleased(mouseX, mouseY, button)
- if (button == 0) {
- isDragging = false
+ override def mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean = {
+ if (canScroll && button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isScrolling) {
+ isScrolling = false
+ return true
}
+ super.mouseReleased(mouseX, mouseY, button)
}
- override protected def mouseClickMove(mouseX: Int, mouseY: Int, lastButtonClicked: Int, timeSinceMouseClick: Long) {
- super.mouseClickMove(mouseX, mouseY, lastButtonClicked, timeSinceMouseClick)
- if (isDragging) {
+ override def mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean = {
+ if (isScrolling) {
scrollMouse(mouseY)
+ true
}
+ else super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
}
- private def scrollMouse(mouseY: Int) {
- scrollTo(math.round((mouseY - guiTop - scrollY + 1 - 6.5) * maxOffset / (scrollHeight - 13.0)).toInt)
+ private def scrollMouse(mouseY: Double) {
+ scrollTo(math.round((mouseY - topPos - scrollY + 1 - 6.5) * maxOffset / (scrollHeight - 13.0)).toInt)
}
- override def handleMouseInput() {
- super.handleMouseInput()
- if (Mouse.hasWheel && Mouse.getEventDWheel != 0) {
- val mouseX = Mouse.getEventX * width / mc.displayWidth - guiLeft
- val mouseY = height - Mouse.getEventY * height / mc.displayHeight - 1 - guiTop
- if (isCoordinateOverInventory(mouseX, mouseY) || isCoordinateOverScrollBar(mouseX, mouseY)) {
- if (math.signum(Mouse.getEventDWheel) < 0) scrollDown()
- else scrollUp()
- }
+ override def mouseScrolled(mouseX: Double, mouseY: Double, scroll: Double): Boolean = {
+ val mx = mouseX.asInstanceOf[Int] - leftPos
+ val my = mouseY.asInstanceOf[Int] - topPos
+ if (isCoordinateOverInventory(mx, my) || isCoordinateOverScrollBar(mx, my)) {
+ if (scroll < 0) scrollDown()
+ else scrollUp()
+ true
}
+ else super.mouseScrolled(mouseX, mouseY, scroll)
}
private def isCoordinateOverInventory(x: Int, y: Int) =
@@ -222,57 +228,41 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
private def scrollTo(row: Int) {
inventoryOffset = math.max(0, math.min(maxOffset, row))
- for (index <- 4 until 68) {
- val slot = inventorySlots.getSlot(index)
- val displayIndex = index - inventoryOffset * 4 - 4
- if (displayIndex >= 0 && displayIndex < 16) {
- slot.xPos = 1 + inventoryX + (displayIndex % 4) * slotSize
- slot.yPos = 1 + inventoryY + (displayIndex / 4) * slotSize
- }
- else {
- // Hide the rest!
- slot.xPos = -10000
- slot.yPos = -10000
- }
- }
- val yMin = guiTop + scrollY + 1
+ menu.generateSlotsFor(inventoryOffset)
+ val yMin = topPos + scrollY + 1
if (maxOffset > 0) {
- scrollButton.y = yMin + (scrollHeight - 15) * inventoryOffset / maxOffset
+ scrollButton.y = yMin + (scrollHeight - 13) * inventoryOffset / maxOffset
}
else {
scrollButton.y = yMin
}
}
- override protected def changeSize(w: Double, h: Double, recompile: Boolean): Double = {
+ override protected def changeSize(w: Double, h: Double): Double = {
val bw = w * TextBufferRenderCache.renderer.charRenderWidth
val bh = h * TextBufferRenderCache.renderer.charRenderHeight
val scaleX = math.min(bufferRenderWidth / bw, 1)
val scaleY = math.min(bufferRenderHeight / bh, 1)
- if (recompile) {
- BufferRenderer.compileBackground(bufferRenderWidth.toInt, bufferRenderHeight.toInt, forRobot = true)
- }
math.min(scaleX, scaleY)
}
- private def drawSelection() {
- val slot = robot.selectedSlot - inventoryOffset * 4
+ private def drawSelection(stack: MatrixStack) {
+ val slot = inventoryContainer.selectedSlot - inventoryOffset * 4
if (slot >= 0 && slot < 16) {
- RenderState.makeItBlend()
Textures.bind(Textures.GUI.RobotSelection)
- val now = System.currentTimeMillis() / 1000.0
- val offsetV = ((now - now.toInt) * selectionsStates).toInt * selectionStepV
- val x = guiLeft + inventoryX - 1 + (slot % 4) * (selectionSize - 2)
- val y = guiTop + inventoryY - 1 + (slot / 4) * (selectionSize - 2)
+ val now = System.currentTimeMillis() % 1000 / 1000.0f
+ val offsetV = (now * selectionsStates).toInt * selectionStepV
+ val x = leftPos + inventoryX - 1 + (slot % 4) * (selectionSize - 2)
+ val y = topPos + inventoryY - 1 + (slot / 4) * (selectionSize - 2)
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y, zLevel).tex(0, offsetV).endVertex()
- r.pos(x, y + selectionSize, zLevel).tex(0, offsetV + selectionStepV).endVertex()
- r.pos(x + selectionSize, y + selectionSize, zLevel).tex(1, offsetV + selectionStepV).endVertex()
- r.pos(x + selectionSize, y, zLevel).tex(1, offsetV).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, x, y, getBlitOffset).uv(0, offsetV).endVertex()
+ r.vertex(stack.last.pose, x, y + selectionSize, getBlitOffset).uv(0, offsetV + selectionStepV).endVertex()
+ r.vertex(stack.last.pose, x + selectionSize, y + selectionSize, getBlitOffset).uv(1, offsetV + selectionStepV).endVertex()
+ r.vertex(stack.last.pose, x + selectionSize, y, getBlitOffset).uv(1, offsetV).endVertex()
+ t.end()
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Screen.scala b/src/main/scala/li/cil/oc/client/gui/Screen.scala
index 104b2518a5..5dc7eaf5fe 100644
--- a/src/main/scala/li/cil/oc/client/gui/Screen.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Screen.scala
@@ -1,13 +1,18 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.api
import li.cil.oc.client.renderer.TextBufferRenderCache
import li.cil.oc.client.renderer.gui.BufferRenderer
-import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import org.lwjgl.input.Mouse
+import net.minecraft.client.gui.INestedGuiEventHandler
+import net.minecraft.client.gui.screen
+import net.minecraft.client.settings.KeyBinding
+import net.minecraft.util.text.StringTextComponent
+import org.lwjgl.glfw.GLFW
+
+class Screen(val buffer: api.internal.TextBuffer, val hasMouse: Boolean, val hasKeyboardCallback: () => Boolean, val hasPower: () => Boolean)
+ extends screen.Screen(StringTextComponent.EMPTY) with traits.InputBuffer with INestedGuiEventHandler {
-class Screen(val buffer: api.internal.TextBuffer, val hasMouse: Boolean, val hasKeyboardCallback: () => Boolean, val hasPower: () => Boolean) extends traits.InputBuffer {
override protected def hasKeyboard = hasKeyboardCallback()
override protected def bufferX = 8 + x
@@ -20,56 +25,60 @@ class Screen(val buffer: api.internal.TextBuffer, val hasMouse: Boolean, val has
private var x, y = 0
+ private var innerWidth, innerHeight = 0
+
private var mx, my = -1
- override def handleMouseInput() {
- super.handleMouseInput()
- if (hasMouse && Mouse.hasWheel && Mouse.getEventDWheel != 0) {
- val mouseX = Mouse.getEventX * width / mc.displayWidth
- val mouseY = height - Mouse.getEventY * height / mc.displayHeight - 1
+ override def mouseScrolled(mouseX: Double, mouseY: Double, scroll: Double): Boolean = {
+ if (hasMouse) {
toBufferCoordinates(mouseX, mouseY) match {
case Some((bx, by)) =>
- val scroll = math.signum(Mouse.getEventDWheel)
- buffer.mouseScroll(bx, by, scroll, null)
+ buffer.mouseScroll(bx, by, math.signum(scroll).asInstanceOf[Int], null)
+ return true
case _ => // Ignore when out of bounds.
}
}
+ super.mouseScrolled(mouseX, mouseY, scroll)
}
- override protected def mouseClicked(mouseX: Int, mouseY: Int, button: Int) {
- super.mouseClicked(mouseX, mouseY, button)
+ override def mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean = {
if (hasMouse) {
- if (button == 0 || button == 1) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT || button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
clickOrDrag(mouseX, mouseY, button)
+ return true
}
}
+ super.mouseClicked(mouseX, mouseY, button)
}
- protected override def mouseClickMove(mouseX: Int, mouseY: Int, button: Int, timeSinceLast: Long) {
- super.mouseClickMove(mouseX, mouseY, button, timeSinceLast)
- if (hasMouse && timeSinceLast > 10) {
- if (button == 0 || button == 1) {
+ override def mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean = {
+ if (hasMouse) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT || button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
clickOrDrag(mouseX, mouseY, button)
+ return true
}
}
+ super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
}
- override protected def mouseReleased(mouseX: Int, mouseY: Int, button: Int) {
- super.mouseReleased(mouseX, mouseY, button)
- if (hasMouse && button >= 0) {
+ override def mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean = {
+ if (hasMouse) {
if (didClick) {
toBufferCoordinates(mouseX, mouseY) match {
case Some((bx, by)) => buffer.mouseUp(bx, by, button, null)
case _ => buffer.mouseUp(-1.0, -1.0, button, null)
}
}
+ val hasClicked = didClick
didClick = false
mx = -1
my = -1
+ if (hasClicked) return true
}
+ super.mouseReleased(mouseX, mouseY, button)
}
- private def clickOrDrag(mouseX: Int, mouseY: Int, button: Int) {
+ private def clickOrDrag(mouseX: Double, mouseY: Double, button: Int) {
toBufferCoordinates(mouseX, mouseY) match {
case Some((bx, by)) if bx.toInt != mx || (by*2).toInt != my =>
if (mx >= 0 && my >= 0) buffer.mouseDrag(bx, by, button, null)
@@ -81,7 +90,7 @@ class Screen(val buffer: api.internal.TextBuffer, val hasMouse: Boolean, val has
}
}
- private def toBufferCoordinates(mouseX: Int, mouseY: Int): Option[(Double, Double)] = {
+ private def toBufferCoordinates(mouseX: Double, mouseY: Double): Option[(Double, Double)] = {
val bx = (mouseX - x - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderWidth
val by = (mouseY - y - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderHeight
val bw = buffer.getViewportWidth
@@ -90,35 +99,37 @@ class Screen(val buffer: api.internal.TextBuffer, val hasMouse: Boolean, val has
else None
}
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
- super.drawScreen(mouseX, mouseY, dt)
- drawBufferLayer()
+ override protected def init(): Unit = {
+ super.init()
+ minecraft.mouseHandler.releaseMouse()
+ KeyBinding.releaseAll()
}
- override def drawBuffer() {
- GlStateManager.translate(x, y, 0)
- BufferRenderer.drawBackground()
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float): Unit = {
+ super.render(stack, mouseX, mouseY, dt)
+ drawBufferLayer(stack)
+ }
+
+ override def drawBuffer(stack: MatrixStack) {
+ stack.translate(x, y, 0)
+ BufferRenderer.drawBackground(stack, innerWidth, innerHeight)
if (hasPower()) {
- GlStateManager.translate(bufferMargin, bufferMargin, 0)
- GlStateManager.scale(scale, scale, 1)
- RenderState.makeItBlend()
- BufferRenderer.drawText(buffer)
+ stack.translate(bufferMargin, bufferMargin, 0)
+ stack.scale(scale.toFloat, scale.toFloat, 1)
+ BufferRenderer.drawText(stack, buffer)
}
}
- override protected def changeSize(w: Double, h: Double, recompile: Boolean) = {
+ override protected def changeSize(w: Double, h: Double) = {
val bw = buffer.renderWidth
val bh = buffer.renderHeight
val scaleX = math.min(width / (bw + bufferMargin * 2.0), 1)
val scaleY = math.min(height / (bh + bufferMargin * 2.0), 1)
val scale = math.min(scaleX, scaleY)
- val innerWidth = (bw * scale).toInt
- val innerHeight = (bh * scale).toInt
+ innerWidth = (bw * scale).toInt
+ innerHeight = (bh * scale).toInt
x = (width - (innerWidth + bufferMargin * 2)) / 2
y = (height - (innerHeight + bufferMargin * 2)) / 2
- if (recompile) {
- BufferRenderer.compileBackground(innerWidth, innerHeight)
- }
scale
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Server.scala b/src/main/scala/li/cil/oc/client/gui/Server.scala
index 98f4af99cf..4d7ad48268 100644
--- a/src/main/scala/li/cil/oc/client/gui/Server.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Server.scala
@@ -1,67 +1,54 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.container
-import li.cil.oc.common.inventory.ServerInventory
-import li.cil.oc.common.tileentity
import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.client.gui.widget.button.Button
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-import scala.collection.convert.WrapAsJava.asJavaCollection
+import scala.collection.JavaConverters.asJavaCollection
-class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory, val rack: Option[tileentity.Rack] = None, val slot: Int = 0) extends DynamicGuiContainer(new container.Server(playerInventory, serverInventory)) with traits.LockedHotbar {
- protected var powerButton: ImageButton = _
-
- override def lockedStack = serverInventory.container
+class Server(state: container.Server, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name)
+ with traits.LockedHotbar[container.Server] {
- protected override def actionPerformed(button: GuiButton) {
- if (button.id == 0) {
- rack match {
- case Some(t) => ClientPacketSender.sendServerPower(t, slot, !inventoryContainer.isRunning)
- case _ =>
- }
- }
- }
+ protected var powerButton: ImageButton = _
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
- // Close GUI if item is removed from rack.
- rack match {
- case Some(t) if t.getStackInSlot(slot) != serverInventory.container =>
- Minecraft.getMinecraft.displayGuiScreen(null)
- return
- case _ =>
- }
+ override def lockedStack = inventoryContainer.stack
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float) {
powerButton.visible = !inventoryContainer.isItem
powerButton.toggled = inventoryContainer.isRunning
- super.drawScreen(mouseX, mouseY, dt)
+ super.render(stack, mouseX, mouseY, dt)
}
- override def initGui() {
- super.initGui()
- powerButton = new ImageButton(0, guiLeft + 48, guiTop + 33, 18, 18, Textures.GUI.ButtonPower, canToggle = true)
- add(buttonList, powerButton)
+ override protected def init() {
+ super.init()
+ powerButton = new ImageButton(leftPos + 48, topPos + 33, 18, 18, new Button.IPressable {
+ override def onPress(b: Button) = if (inventoryContainer.rackSlot >= 0) {
+ ClientPacketSender.sendServerPower(inventoryContainer, inventoryContainer.rackSlot, !inventoryContainer.isRunning)
+ }
+ }, Textures.GUI.ButtonPower, canToggle = true)
+ addButton(powerButton)
}
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(serverInventory.getName),
- 8, 6, 0x404040)
- if (powerButton.isMouseOver) {
+ override def drawSecondaryForegroundLayer(stack: MatrixStack, mouseX: Int, mouseY: Int) {
+ super.drawSecondaryForegroundLayer(stack, mouseX, mouseY)
+ if (powerButton.isMouseOver(mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
tooltip.addAll(asJavaCollection(if (inventoryContainer.isRunning) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
- copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
- }
+ copiedDrawHoveringText(stack, tooltip, mouseX - leftPos, mouseY - topPos, font)
+ }
}
- override def drawSecondaryBackgroundLayer() {
- GlStateManager.color(1, 1, 1)
+ override def drawSecondaryBackgroundLayer(stack: MatrixStack) {
+ RenderSystem.color3f(1, 1, 1)
Textures.bind(Textures.GUI.Server)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Tablet.scala b/src/main/scala/li/cil/oc/client/gui/Tablet.scala
index 94a934ed52..d0816a535e 100644
--- a/src/main/scala/li/cil/oc/client/gui/Tablet.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Tablet.scala
@@ -1,17 +1,12 @@
package li.cil.oc.client.gui
-import li.cil.oc.Localization
import li.cil.oc.common.container
-import li.cil.oc.common.item.TabletWrapper
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.util.text.ITextComponent
-class Tablet(playerInventory: InventoryPlayer, val tablet: TabletWrapper) extends DynamicGuiContainer(new container.Tablet(playerInventory, tablet)) with traits.LockedHotbar {
- override def lockedStack = tablet.stack
+class Tablet(state: container.Tablet, playerInventory: PlayerInventory, name: ITextComponent)
+ extends DynamicGuiContainer(state, playerInventory, name)
+ with traits.LockedHotbar[container.Tablet] {
- override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawSecondaryForegroundLayer(mouseX, mouseY)
- fontRenderer.drawString(
- Localization.localizeImmediately(tablet.getName),
- 8, 6, 0x404040)
- }
+ override def lockedStack = inventoryContainer.stack
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Waypoint.scala b/src/main/scala/li/cil/oc/client/gui/Waypoint.scala
index 6cee5dc1d6..e979cf3702 100644
--- a/src/main/scala/li/cil/oc/client/gui/Waypoint.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Waypoint.scala
@@ -1,78 +1,77 @@
package li.cil.oc.client.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.PacketSender
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity
-import li.cil.oc.util.OldScaledResolution
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.client.gui.GuiTextField
-import net.minecraft.client.gui.ScaledResolution
-import net.minecraft.client.renderer.GlStateManager
-import org.lwjgl.input.Keyboard
+import net.minecraft.client.gui.screen
+import net.minecraft.client.gui.widget.TextFieldWidget
+import net.minecraft.client.settings.KeyBinding
+import net.minecraft.util.text.StringTextComponent
+import org.lwjgl.glfw.GLFW
-class Waypoint(val waypoint: tileentity.Waypoint) extends GuiScreen {
- var guiLeft = 0
- var guiTop = 0
- var xSize = 0
- var ySize = 0
+class Waypoint(val waypoint: tileentity.Waypoint) extends screen.Screen(StringTextComponent.EMPTY) {
+ val imageWidth = 176
+ val imageHeight = 24
+ var leftPos = 0
+ var topPos = 0
+ passEvents = false
- var textField: GuiTextField = _
+ var textField: TextFieldWidget = _
- override def updateScreen(): Unit = {
- super.updateScreen()
- if (mc.player.getDistanceSq(waypoint.x + 0.5, waypoint.y + 0.5, waypoint.z + 0.5) > 64) {
- mc.player.closeScreen()
+ override def tick(): Unit = {
+ super.tick()
+ textField.tick()
+ if (minecraft.player.distanceToSqr(waypoint.x + 0.5, waypoint.y + 0.5, waypoint.z + 0.5) > 64) {
+ onClose()
}
}
- override def doesGuiPauseGame(): Boolean = false
+ override def isPauseScreen(): Boolean = false
- override def initGui(): Unit = {
- super.initGui()
+ override protected def init(): Unit = {
+ super.init()
+ minecraft.mouseHandler.releaseMouse()
+ KeyBinding.releaseAll()
+ leftPos = (width - imageWidth) / 2
+ topPos = (height - imageHeight) / 2
- val screenSize = new ScaledResolution(mc)
- val guiSize = new OldScaledResolution(mc, 176, 24)
- val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
- guiLeft = midX - guiSize.getScaledWidth / 2
- guiTop = midY - guiSize.getScaledHeight / 2
- xSize = guiSize.getScaledWidth
- ySize = guiSize.getScaledHeight
-
- textField = new GuiTextField(0, fontRenderer, guiLeft + 7, guiTop + 8, 164 - 12, 12)
- textField.setMaxStringLength(32)
- textField.setEnableBackgroundDrawing(false)
+ textField = new TextFieldWidget(font, leftPos + 7, topPos + 8, 164 - 12, 12, StringTextComponent.EMPTY) {
+ override def keyPressed(keyCode: Int, scanCode: Int, mods: Int): Boolean = {
+ if (keyCode == GLFW.GLFW_KEY_ENTER) {
+ val label = textField.getValue.take(32)
+ if (label != waypoint.label) {
+ waypoint.label = label
+ PacketSender.sendWaypointLabel(waypoint)
+ onClose()
+ }
+ return true
+ }
+ super.keyPressed(keyCode, scanCode, mods)
+ }
+ }
+ textField.setMaxLength(32)
+ textField.setBordered(false)
textField.setCanLoseFocus(false)
- textField.setFocused(true)
textField.setTextColor(0xFFFFFF)
- textField.setText(waypoint.label)
+ textField.setValue(waypoint.label)
+ addWidget(textField)
- Keyboard.enableRepeatEvents(true)
+ setInitialFocus(textField)
+ minecraft.keyboardHandler.setSendRepeatsToGui(true)
}
- override def onGuiClosed(): Unit = {
- super.onGuiClosed()
- Keyboard.enableRepeatEvents(false)
- }
-
- override def keyTyped(char: Char, code: Int): Unit = {
- if (!textField.textboxKeyTyped(char, code)) {
- if (code == Keyboard.KEY_RETURN) {
- val label = textField.getText.take(32)
- if (label != waypoint.label) {
- waypoint.label = label
- PacketSender.sendWaypointLabel(waypoint)
- mc.player.closeScreen()
- }
- }
- else super.keyTyped(char, code)
- }
+ override def removed(): Unit = {
+ minecraft.keyboardHandler.setSendRepeatsToGui(false)
+ super.removed()
}
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
- super.drawScreen(mouseX, mouseY, dt)
- GlStateManager.color(1, 1, 1) // Required under Linux.
- mc.renderEngine.bindTexture(Textures.GUI.Waypoint)
- drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
- textField.drawTextBox()
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float): Unit = {
+ super.render(stack, mouseX, mouseY, dt)
+ RenderSystem.color3f(1, 1, 1) // Required under Linux.
+ minecraft.getTextureManager.bind(Textures.GUI.Waypoint)
+ blit(stack, leftPos, topPos, 0, 0, imageWidth, imageHeight)
+ textField.render(stack, mouseX, mouseY, dt)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/traits/DisplayBuffer.scala b/src/main/scala/li/cil/oc/client/gui/traits/DisplayBuffer.scala
index 05fe40575f..7069895a62 100644
--- a/src/main/scala/li/cil/oc/client/gui/traits/DisplayBuffer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/traits/DisplayBuffer.scala
@@ -1,12 +1,10 @@
package li.cil.oc.client.gui.traits
-import li.cil.oc.client.renderer.gui.BufferRenderer
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.util.RenderState
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.gui.screen.Screen
-trait DisplayBuffer extends GuiScreen {
+trait DisplayBuffer extends Screen {
protected def bufferX: Int
protected def bufferY: Int
@@ -15,36 +13,21 @@ trait DisplayBuffer extends GuiScreen {
protected def bufferRows: Int
- protected var guiSizeChanged = false
-
- protected var currentWidth, currentHeight = -1
-
protected var scale = 0.0
- override def initGui() = {
- super.initGui()
- BufferRenderer.init(Minecraft.getMinecraft.renderEngine)
- guiSizeChanged = true
- }
-
- protected def drawBufferLayer() {
- val oldWidth = currentWidth
- val oldHeight = currentHeight
- currentWidth = bufferColumns
- currentHeight = bufferRows
- scale = changeSize(currentWidth, currentHeight, guiSizeChanged || oldWidth != currentWidth || oldHeight != currentHeight)
+ protected def drawBufferLayer(stack: MatrixStack) {
+ scale = changeSize(bufferColumns, bufferRows)
RenderState.checkError(getClass.getName + ".drawBufferLayer: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
- RenderState.disableEntityLighting()
- drawBuffer()
- GlStateManager.popMatrix()
+ stack.pushPose()
+ drawBuffer(stack)
+ stack.popPose()
RenderState.checkError(getClass.getName + ".drawBufferLayer: buffer layer")
}
- protected def drawBuffer(): Unit
+ protected def drawBuffer(stack: MatrixStack): Unit
- protected def changeSize(w: Double, h: Double, recompile: Boolean): Double
+ protected def changeSize(w: Double, h: Double): Double
}
diff --git a/src/main/scala/li/cil/oc/client/gui/traits/InputBuffer.scala b/src/main/scala/li/cil/oc/client/gui/traits/InputBuffer.scala
index e80873bdd3..4e9b7530ce 100644
--- a/src/main/scala/li/cil/oc/client/gui/traits/InputBuffer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/traits/InputBuffer.scala
@@ -1,16 +1,20 @@
package li.cil.oc.client.gui.traits
+import java.util.Arrays
+
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.api
import li.cil.oc.client.KeyBindings
import li.cil.oc.client.Textures
import li.cil.oc.integration.util.ItemSearch
import li.cil.oc.util.RenderState
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.client.gui.inventory.GuiContainer
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.screen.Screen
+import net.minecraft.client.gui.screen.inventory.ContainerScreen
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.input.Keyboard
+import net.minecraft.client.util.InputMappings
+import org.lwjgl.glfw.GLFW
import org.lwjgl.opengl.GL11
import scala.collection.mutable
@@ -28,98 +32,316 @@ trait InputBuffer extends DisplayBuffer {
private var showKeyboardMissing = 0L
- override def doesGuiPauseGame = false
+ private var hasQueuedKey = false
+ private var queuedKey = 0
+ private var queuedChar = '\u0000'
+ private var highSurrogate = '\u0000'
+
+ protected def pushQueuedKey(keyCode: Int): Unit = {
+ flushQueuedKey()
+ hasQueuedKey = true
+ queuedKey = keyCode
+ queuedChar = GLFWTranslator.keyToChar(keyCode)
+ }
+
+ protected def pushQueuedChar(char: Char): Unit = {
+ if (hasQueuedKey) {
+ if (!Character.isSurrogate(char)) queuedChar = char
+ // Flush either way as the next code point will be unrelated.
+ flushQueuedKey()
+ }
+ // text_input happens independent of key events
+ if (Character.isSurrogate(char)) {
+ // Convert two successive surrogates back into a code point.
+ if (Character.isHighSurrogate(char)) highSurrogate = char
+ else buffer.textInput(Character.toCodePoint(highSurrogate, char), null)
+ }
+ else buffer.textInput(char, null)
+ }
- override def initGui() = {
- super.initGui()
- Keyboard.enableRepeatEvents(true)
+ protected def flushQueuedKey(): Unit = {
+ if (hasQueuedKey) {
+ hasQueuedKey = false
+ if (!pressedKeys.contains(queuedKey)) {
+ val lwjglCode = GLFWTranslator.glfwToLWJGL(queuedKey)
+ if (lwjglCode > 0) {
+ pressedKeys(queuedKey) = queuedChar
+ if (buffer != null) buffer.keyDown(queuedChar, lwjglCode, null)
+ }
+ else if (queuedChar > 0) {
+ pressedKeys(queuedKey) = queuedChar
+ if (buffer != null) buffer.keyDown(queuedChar, 0, null)
+ }
+ }
+ }
}
- override protected def drawBufferLayer() {
- super.drawBufferLayer()
+ override def isPauseScreen = false
+
+ override protected def init() = {
+ super.init()
+ Minecraft.getInstance.keyboardHandler.setSendRepeatsToGui(true)
+ }
+
+ override protected def drawBufferLayer(stack: MatrixStack) {
+ super.drawBufferLayer(stack)
if (System.currentTimeMillis() - showKeyboardMissing < 1000) {
Textures.bind(Textures.GUI.KeyboardMissing)
- GlStateManager.disableDepth()
val x = bufferX + buffer.renderWidth - 16
val y = bufferY + buffer.renderHeight - 16
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y + 16, 0).tex(0, 1).endVertex()
- r.pos(x + 16, y + 16, 0).tex(1, 1).endVertex()
- r.pos(x + 16, y, 0).tex(1, 0).endVertex()
- r.pos(x, y, 0).tex(0, 0).endVertex()
- t.draw()
-
- GlStateManager.enableDepth()
+ r.vertex(stack.last.pose, x, y + 16, 0).uv(0, 1).endVertex()
+ r.vertex(stack.last.pose, x + 16, y + 16, 0).uv(1, 1).endVertex()
+ r.vertex(stack.last.pose, x + 16, y, 0).uv(1, 0).endVertex()
+ r.vertex(stack.last.pose, x, y, 0).uv(0, 0).endVertex()
+ t.end()
RenderState.checkError(getClass.getName + ".drawBufferLayer: keyboard icon")
}
}
- override def onGuiClosed() = {
- super.onGuiClosed()
- if (buffer != null) for ((code, char) <- pressedKeys) {
- buffer.keyUp(char, code, null)
- }
- Keyboard.enableRepeatEvents(false)
+ override def tick(): Unit = {
+ super.tick()
+ flushQueuedKey()
}
- override def handleKeyboardInput() {
- super.handleKeyboardInput()
+ override def removed() = {
+ super.removed()
+ Minecraft.getInstance.keyboardHandler.setSendRepeatsToGui(false)
+ if (buffer != null) {
+ flushQueuedKey()
+ for ((code, char) <- pressedKeys) {
+ val lwjglCode = GLFWTranslator.glfwToLWJGL(code)
+ if (lwjglCode > 0) buffer.keyUp(char, lwjglCode, null)
+ else buffer.keyUp(char, 0, null)
+ }
+ }
+ }
- if (this.isInstanceOf[GuiContainer] && ItemSearch.isInputFocused) return
+ def onInput(input: InputMappings.Input): Boolean = {
+ if (KeyBindings.clipboardPaste.isActiveAndMatches(input)) {
+ if (buffer != null) {
+ if (hasKeyboard) buffer.clipboard(Minecraft.getInstance.keyboardHandler.getClipboard, null)
+ else showKeyboardMissing = System.currentTimeMillis()
+ }
+ return true
+ }
+ false
+ }
- val code = Keyboard.getEventKey
- if (buffer != null && code != Keyboard.KEY_ESCAPE && code != Keyboard.KEY_F11) {
- if (hasKeyboard) {
- if (Keyboard.getEventKeyState) {
- val char = Keyboard.getEventCharacter
- if (!pressedKeys.contains(code) || !ignoreRepeat(char, code)) {
- buffer.keyDown(char, code, null)
- pressedKeys += code -> char
- }
- }
- else pressedKeys.remove(code) match {
- case Some(char) => buffer.keyUp(char, code, null)
- case _ => // Wasn't pressed while viewing the screen.
- }
+ override def charTyped(codePt: Char, mods: Int): Boolean = {
+ if (!this.isInstanceOf[ContainerScreen[_]] || !ItemSearch.isInputFocused) {
+ if (buffer != null) {
+ if (hasKeyboard) pushQueuedChar(codePt)
+ else showKeyboardMissing = System.currentTimeMillis()
+ return true
+ }
+ }
+ super.charTyped(codePt, mods)
+ }
- if (KeyBindings.isPastingClipboard) {
- buffer.clipboard(GuiScreen.getClipboardString, null)
- }
+ override def keyPressed(keyCode: Int, scanCode: Int, mods: Int): Boolean = {
+ if (!this.isInstanceOf[ContainerScreen[_]] || !ItemSearch.isInputFocused) {
+ if (keyCode == GLFW.GLFW_KEY_ESCAPE && shouldCloseOnEsc) {
+ onClose()
+ return true
}
- else {
- showKeyboardMissing = System.currentTimeMillis()
+ if (onInput(InputMappings.getKey(keyCode, scanCode))) return true
+ if (buffer != null && keyCode != GLFW.GLFW_KEY_UNKNOWN) {
+ if (hasKeyboard) pushQueuedKey(keyCode)
+ else showKeyboardMissing = System.currentTimeMillis()
+ return true
}
}
+ super.keyPressed(keyCode, scanCode, mods)
}
- override protected def mouseClicked(x: Int, y: Int, button: Int) {
- super.mouseClicked(x, y, button)
- val isMiddleMouseButton = button == 2
- val isBoundMouseButton = KeyBindings.isPastingClipboard
- if (buffer != null && (isMiddleMouseButton || isBoundMouseButton)) {
- if (hasKeyboard) {
- buffer.clipboard(GuiScreen.getClipboardString, null)
- }
- else {
- showKeyboardMissing = System.currentTimeMillis()
+ override def keyReleased(keyCode: Int, scanCode: Int, mods: Int): Boolean = {
+ if (!this.isInstanceOf[ContainerScreen[_]] || !ItemSearch.isInputFocused) {
+ flushQueuedKey()
+ pressedKeys.remove(keyCode) match {
+ case Some(char) => {
+ val lwjglCode = GLFWTranslator.glfwToLWJGL(keyCode)
+ if (lwjglCode > 0) {
+ buffer.keyUp(char, lwjglCode, null)
+ return true
+ }
+ else if (char > 0) {
+ buffer.keyUp(char, 0, null)
+ return true
+ }
+ }
+ case None =>
}
+ // Wasn't pressed while viewing the screen.
}
+ super.keyReleased(keyCode, scanCode, mods)
}
- private def ignoreRepeat(char: Char, code: Int) = {
- code == Keyboard.KEY_LCONTROL ||
- code == Keyboard.KEY_RCONTROL ||
- code == Keyboard.KEY_LMENU ||
- code == Keyboard.KEY_RMENU ||
- code == Keyboard.KEY_LSHIFT ||
- code == Keyboard.KEY_RSHIFT ||
- code == Keyboard.KEY_LMETA ||
- code == Keyboard.KEY_RMETA
+ override def mouseClicked(x: Double, y: Double, button: Int): Boolean = {
+ if (onInput(InputMappings.Type.MOUSE.getOrCreate(button))) return true
+ if (buffer != null && button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE) {
+ if (hasKeyboard) buffer.clipboard(Minecraft.getInstance.keyboardHandler.getClipboard, null)
+ else showKeyboardMissing = System.currentTimeMillis()
+ return true
+ }
+ super.mouseClicked(x, y, button)
+ }
+
+ private def ignoreRepeat(keyCode: Int) = {
+ keyCode == GLFW.GLFW_KEY_LEFT_CONTROL ||
+ keyCode == GLFW.GLFW_KEY_RIGHT_CONTROL ||
+ keyCode == GLFW.GLFW_KEY_MENU ||
+ keyCode == GLFW.GLFW_KEY_LEFT_ALT ||
+ keyCode == GLFW.GLFW_KEY_RIGHT_ALT ||
+ keyCode == GLFW.GLFW_KEY_LEFT_SHIFT ||
+ keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT ||
+ keyCode == GLFW.GLFW_KEY_LEFT_SUPER ||
+ keyCode == GLFW.GLFW_KEY_RIGHT_SUPER
+ }
+}
+
+object GLFWTranslator {
+ private val toLWJGL = new Array[Int](GLFW.GLFW_KEY_LAST + 1)
+ Arrays.fill(toLWJGL, -1)
+
+ /** Printable keys. */
+ toLWJGL(GLFW.GLFW_KEY_SPACE) = 0x39
+ toLWJGL(GLFW.GLFW_KEY_APOSTROPHE) = 0x28
+ toLWJGL(GLFW.GLFW_KEY_COMMA) = 0x33
+ toLWJGL(GLFW.GLFW_KEY_MINUS) = 0x0C
+ toLWJGL(GLFW.GLFW_KEY_PERIOD) = 0x34
+ toLWJGL(GLFW.GLFW_KEY_SLASH) = 0x35
+ toLWJGL(GLFW.GLFW_KEY_0) = 0x0B
+ toLWJGL(GLFW.GLFW_KEY_1) = 0x02
+ toLWJGL(GLFW.GLFW_KEY_2) = 0x03
+ toLWJGL(GLFW.GLFW_KEY_3) = 0x04
+ toLWJGL(GLFW.GLFW_KEY_4) = 0x05
+ toLWJGL(GLFW.GLFW_KEY_5) = 0x06
+ toLWJGL(GLFW.GLFW_KEY_6) = 0x07
+ toLWJGL(GLFW.GLFW_KEY_7) = 0x08
+ toLWJGL(GLFW.GLFW_KEY_8) = 0x09
+ toLWJGL(GLFW.GLFW_KEY_9) = 0x0A
+ toLWJGL(GLFW.GLFW_KEY_SEMICOLON) = 0x27
+ toLWJGL(GLFW.GLFW_KEY_EQUAL) = 0x0D
+ toLWJGL(GLFW.GLFW_KEY_A) = 0x1E
+ toLWJGL(GLFW.GLFW_KEY_B) = 0x30
+ toLWJGL(GLFW.GLFW_KEY_C) = 0x2E
+ toLWJGL(GLFW.GLFW_KEY_D) = 0x20
+ toLWJGL(GLFW.GLFW_KEY_E) = 0x12
+ toLWJGL(GLFW.GLFW_KEY_F) = 0x21
+ toLWJGL(GLFW.GLFW_KEY_G) = 0x22
+ toLWJGL(GLFW.GLFW_KEY_H) = 0x23
+ toLWJGL(GLFW.GLFW_KEY_I) = 0x17
+ toLWJGL(GLFW.GLFW_KEY_J) = 0x24
+ toLWJGL(GLFW.GLFW_KEY_K) = 0x25
+ toLWJGL(GLFW.GLFW_KEY_L) = 0x26
+ toLWJGL(GLFW.GLFW_KEY_M) = 0x32
+ toLWJGL(GLFW.GLFW_KEY_N) = 0x31
+ toLWJGL(GLFW.GLFW_KEY_O) = 0x18
+ toLWJGL(GLFW.GLFW_KEY_P) = 0x19
+ toLWJGL(GLFW.GLFW_KEY_Q) = 0x10
+ toLWJGL(GLFW.GLFW_KEY_R) = 0x13
+ toLWJGL(GLFW.GLFW_KEY_S) = 0x1F
+ toLWJGL(GLFW.GLFW_KEY_T) = 0x14
+ toLWJGL(GLFW.GLFW_KEY_U) = 0x16
+ toLWJGL(GLFW.GLFW_KEY_V) = 0x2F
+ toLWJGL(GLFW.GLFW_KEY_W) = 0x11
+ toLWJGL(GLFW.GLFW_KEY_X) = 0x2D
+ toLWJGL(GLFW.GLFW_KEY_Y) = 0x15
+ toLWJGL(GLFW.GLFW_KEY_Z) = 0x2C
+ toLWJGL(GLFW.GLFW_KEY_LEFT_BRACKET) = 0x1A
+ toLWJGL(GLFW.GLFW_KEY_BACKSLASH) = 0x2B
+ toLWJGL(GLFW.GLFW_KEY_RIGHT_BRACKET) = 0x1B
+ toLWJGL(GLFW.GLFW_KEY_GRAVE_ACCENT) = 0x29
+ toLWJGL(GLFW.GLFW_KEY_WORLD_1) = 0x00
+ toLWJGL(GLFW.GLFW_KEY_WORLD_2) = 0x00
+
+ /** Function keys. */
+ toLWJGL(GLFW.GLFW_KEY_ESCAPE) = 0x01
+ toLWJGL(GLFW.GLFW_KEY_ENTER) = 0x1C
+ toLWJGL(GLFW.GLFW_KEY_TAB) = 0x0F
+ toLWJGL(GLFW.GLFW_KEY_BACKSPACE) = 0x0E
+ toLWJGL(GLFW.GLFW_KEY_INSERT) = 0xD2
+ toLWJGL(GLFW.GLFW_KEY_DELETE) = 0xD3
+ toLWJGL(GLFW.GLFW_KEY_RIGHT) = 0xCD
+ toLWJGL(GLFW.GLFW_KEY_LEFT) = 0xCB
+ toLWJGL(GLFW.GLFW_KEY_DOWN) = 0xD0
+ toLWJGL(GLFW.GLFW_KEY_UP) = 0xC8
+ toLWJGL(GLFW.GLFW_KEY_PAGE_UP) = 0xC9
+ toLWJGL(GLFW.GLFW_KEY_PAGE_DOWN) = 0xD1
+ toLWJGL(GLFW.GLFW_KEY_HOME) = 0xC7
+ toLWJGL(GLFW.GLFW_KEY_END) = 0xCF
+ toLWJGL(GLFW.GLFW_KEY_CAPS_LOCK) = 0x3A
+ toLWJGL(GLFW.GLFW_KEY_SCROLL_LOCK) = 0x46
+ toLWJGL(GLFW.GLFW_KEY_NUM_LOCK) = 0x45
+ toLWJGL(GLFW.GLFW_KEY_PRINT_SCREEN) = 0xB7
+ toLWJGL(GLFW.GLFW_KEY_PAUSE) = 0xC5
+ toLWJGL(GLFW.GLFW_KEY_F1) = 0x3B
+ toLWJGL(GLFW.GLFW_KEY_F2) = 0x3C
+ toLWJGL(GLFW.GLFW_KEY_F3) = 0x3D
+ toLWJGL(GLFW.GLFW_KEY_F4) = 0x3E
+ toLWJGL(GLFW.GLFW_KEY_F5) = 0x3F
+ toLWJGL(GLFW.GLFW_KEY_F6) = 0x40
+ toLWJGL(GLFW.GLFW_KEY_F7) = 0x41
+ toLWJGL(GLFW.GLFW_KEY_F8) = 0x42
+ toLWJGL(GLFW.GLFW_KEY_F9) = 0x43
+ toLWJGL(GLFW.GLFW_KEY_F10) = 0x44
+ toLWJGL(GLFW.GLFW_KEY_F11) = 0x57
+ toLWJGL(GLFW.GLFW_KEY_F12) = 0x58
+ toLWJGL(GLFW.GLFW_KEY_F13) = 0x64
+ toLWJGL(GLFW.GLFW_KEY_F14) = 0x65
+ toLWJGL(GLFW.GLFW_KEY_F15) = 0x66
+ toLWJGL(GLFW.GLFW_KEY_F16) = 0x67
+ toLWJGL(GLFW.GLFW_KEY_F17) = 0x68
+ toLWJGL(GLFW.GLFW_KEY_F18) = 0x69
+ toLWJGL(GLFW.GLFW_KEY_F19) = 0x71
+ toLWJGL(GLFW.GLFW_KEY_F20) = -1
+ toLWJGL(GLFW.GLFW_KEY_F21) = -1
+ toLWJGL(GLFW.GLFW_KEY_F22) = -1
+ toLWJGL(GLFW.GLFW_KEY_F23) = -1
+ toLWJGL(GLFW.GLFW_KEY_F24) = -1
+ toLWJGL(GLFW.GLFW_KEY_F25) = -1
+ toLWJGL(GLFW.GLFW_KEY_KP_0) = 0x52
+ toLWJGL(GLFW.GLFW_KEY_KP_1) = 0x4F
+ toLWJGL(GLFW.GLFW_KEY_KP_2) = 0x50
+ toLWJGL(GLFW.GLFW_KEY_KP_3) = 0x51
+ toLWJGL(GLFW.GLFW_KEY_KP_4) = 0x4B
+ toLWJGL(GLFW.GLFW_KEY_KP_5) = 0x4C
+ toLWJGL(GLFW.GLFW_KEY_KP_6) = 0x4D
+ toLWJGL(GLFW.GLFW_KEY_KP_7) = 0x47
+ toLWJGL(GLFW.GLFW_KEY_KP_8) = 0x48
+ toLWJGL(GLFW.GLFW_KEY_KP_9) = 0x49
+ toLWJGL(GLFW.GLFW_KEY_KP_DECIMAL) = 0x53
+ toLWJGL(GLFW.GLFW_KEY_KP_DIVIDE) = 0xB5
+ toLWJGL(GLFW.GLFW_KEY_KP_MULTIPLY) = 0x37
+ toLWJGL(GLFW.GLFW_KEY_KP_SUBTRACT) = 0x4A
+ toLWJGL(GLFW.GLFW_KEY_KP_ADD) = 0x4E
+ toLWJGL(GLFW.GLFW_KEY_KP_ENTER) = 0x9C
+ toLWJGL(GLFW.GLFW_KEY_KP_EQUAL) = 0x8D
+ toLWJGL(GLFW.GLFW_KEY_LEFT_SHIFT) = 0x2A
+ toLWJGL(GLFW.GLFW_KEY_LEFT_CONTROL) = 0x1D
+ toLWJGL(GLFW.GLFW_KEY_LEFT_ALT) = 0x38
+ toLWJGL(GLFW.GLFW_KEY_LEFT_SUPER) = 0xDB
+ toLWJGL(GLFW.GLFW_KEY_RIGHT_SHIFT) = 0x36
+ toLWJGL(GLFW.GLFW_KEY_RIGHT_CONTROL) = 0x9D
+ toLWJGL(GLFW.GLFW_KEY_RIGHT_ALT) = 0xB8
+ toLWJGL(GLFW.GLFW_KEY_RIGHT_SUPER) = 0xDC
+ toLWJGL(GLFW.GLFW_KEY_MENU) = 0xDD
+
+ def glfwToLWJGL(keyCode: Int): Int = if (keyCode >= 0 && keyCode < toLWJGL.size) toLWJGL(keyCode) else -1
+
+ def keyToChar(keyCode: Int): Char = {
+ if (keyCode == GLFW.GLFW_KEY_ESCAPE) '\u001B'
+ else if (keyCode == GLFW.GLFW_KEY_ENTER) '\r'
+ else if (keyCode == GLFW.GLFW_KEY_TAB) '\t'
+ else if (keyCode == GLFW.GLFW_KEY_BACKSPACE) '\b'
+ else if (keyCode == GLFW.GLFW_KEY_KP_ENTER) '\r'
+ else '\u0000'
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/traits/LockedHotbar.scala b/src/main/scala/li/cil/oc/client/gui/traits/LockedHotbar.scala
index 57c9a8c2e9..37eb9cc1fd 100644
--- a/src/main/scala/li/cil/oc/client/gui/traits/LockedHotbar.scala
+++ b/src/main/scala/li/cil/oc/client/gui/traits/LockedHotbar.scala
@@ -1,18 +1,17 @@
package li.cil.oc.client.gui.traits
-import net.minecraft.client.gui.inventory.GuiContainer
-import net.minecraft.inventory.ClickType
-import net.minecraft.inventory.Slot
+import net.minecraft.client.gui.screen.inventory.ContainerScreen
+import net.minecraft.inventory.container.ClickType
+import net.minecraft.inventory.container.Container
+import net.minecraft.inventory.container.Slot
import net.minecraft.item.ItemStack
-trait LockedHotbar extends GuiContainer {
+trait LockedHotbar[C <: Container] extends ContainerScreen[C] {
def lockedStack: ItemStack
- override def handleMouseClick(slot: Slot, slotId: Int, mouseButton: Int, clickType: ClickType): Unit = {
- if (slot == null || !slot.getStack.isItemEqual(lockedStack)) {
- super.handleMouseClick(slot, slotId, mouseButton, clickType)
+ override def slotClicked(slot: Slot, slotId: Int, mouseButton: Int, clickType: ClickType): Unit = {
+ if (slot == null || !slot.getItem.sameItem(lockedStack)) {
+ super.slotClicked(slot, slotId, mouseButton, clickType)
}
}
-
- protected override def checkHotbarKeys(keyCode: Int) = false
}
diff --git a/src/main/scala/li/cil/oc/client/gui/traits/Window.scala b/src/main/scala/li/cil/oc/client/gui/traits/Window.scala
index 9ca7e0b09a..f3b3778a61 100644
--- a/src/main/scala/li/cil/oc/client/gui/traits/Window.scala
+++ b/src/main/scala/li/cil/oc/client/gui/traits/Window.scala
@@ -2,44 +2,40 @@ package li.cil.oc.client.gui.traits
import java.util
-import li.cil.oc.util.OldScaledResolution
-import net.minecraft.client.gui.Gui
-import net.minecraft.client.gui.GuiScreen
-import net.minecraft.client.gui.ScaledResolution
+import com.mojang.blaze3d.matrix.MatrixStack
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.AbstractGui
+import net.minecraft.client.gui.screen.Screen
import net.minecraft.util.ResourceLocation
-trait Window extends GuiScreen {
- var guiLeft = 0
- var guiTop = 0
- var xSize = 0
- var ySize = 0
+trait Window extends Screen {
+ var leftPos = 0
+ var topPos = 0
+ var imageWidth = 0
+ var imageHeight = 0
val windowWidth = 176
val windowHeight = 166
def backgroundImage: ResourceLocation
- protected def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
+ override def isPauseScreen = false
- override def doesGuiPauseGame = false
+ override protected def init(): Unit = {
+ super.init()
- override def initGui(): Unit = {
- super.initGui()
-
- val screenSize = new ScaledResolution(mc)
- val guiSize = new OldScaledResolution(mc, windowWidth, windowHeight)
- val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
- guiLeft = midX - guiSize.getScaledWidth / 2
- guiTop = midY - guiSize.getScaledHeight / 2
- xSize = guiSize.getScaledWidth
- ySize = guiSize.getScaledHeight
+ imageWidth = windowWidth
+ imageHeight = windowHeight
+ leftPos = (width - imageWidth) / 2
+ topPos = (height - imageHeight) / 2
}
- override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
- mc.renderEngine.bindTexture(backgroundImage)
- Gui.drawModalRectWithCustomSizedTexture(guiLeft, guiTop, 0, 0, xSize, ySize, windowWidth, windowHeight)
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int, dt: Float): Unit = {
+ Minecraft.getInstance.getTextureManager.bind(backgroundImage)
+ // Texture width and height are intentionally backwards.
+ AbstractGui.blit(stack, leftPos, topPos, getBlitOffset, 0, 0, imageWidth, imageHeight, windowHeight, windowWidth)
- super.drawScreen(mouseX, mouseY, dt)
+ super.render(stack, mouseX, mouseY, dt)
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala b/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala
index beb5ef240a..a1abc50fbb 100644
--- a/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala
+++ b/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala
@@ -1,5 +1,6 @@
package li.cil.oc.client.gui.widget
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.client.Textures
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
@@ -14,25 +15,25 @@ class ProgressBar(val x: Int, val y: Int) extends Widget {
var level = 0.0
- def draw() {
+ def draw(stack: MatrixStack) {
if (level > 0) {
val u0 = 0
- val u1 = level
+ val u1 = level.toFloat
val v0 = 0
val v1 = 1
val tx = owner.windowX + x
val ty = owner.windowY + y
- val w = width * level
+ val w = (width * level).toFloat
Textures.bind(barTexture)
val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = t.getBuilder
r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(tx, ty, owner.windowZ).tex(u0, v0).endVertex()
- r.pos(tx, ty + height, owner.windowZ).tex(u0, v1).endVertex()
- r.pos(tx + w, ty + height, owner.windowZ).tex(u1, v1).endVertex()
- r.pos(tx + w, ty, owner.windowZ).tex(u1, v0).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, tx, ty, owner.windowZ).uv(u0, v0).endVertex()
+ r.vertex(stack.last.pose, tx, ty + height, owner.windowZ).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, tx + w, ty + height, owner.windowZ).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, tx + w, ty, owner.windowZ).uv(u1, v0).endVertex()
+ t.end()
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala b/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala
index db15521376..9c55386ddd 100644
--- a/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala
+++ b/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala
@@ -1,5 +1,8 @@
package li.cil.oc.client.gui.widget
+import com.mojang.blaze3d.matrix.MatrixStack
+
+@Deprecated
abstract class Widget {
var owner: WidgetContainer = _
@@ -11,5 +14,5 @@ abstract class Widget {
def height: Int
- def draw(): Unit
+ def draw(stack: MatrixStack): Unit
}
diff --git a/src/main/scala/li/cil/oc/client/gui/widget/WidgetContainer.scala b/src/main/scala/li/cil/oc/client/gui/widget/WidgetContainer.scala
index e94089dac4..6b476e2888 100644
--- a/src/main/scala/li/cil/oc/client/gui/widget/WidgetContainer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/widget/WidgetContainer.scala
@@ -1,11 +1,14 @@
package li.cil.oc.client.gui.widget
+import com.mojang.blaze3d.matrix.MatrixStack
+
import scala.collection.mutable
+@Deprecated
trait WidgetContainer {
protected val widgets = mutable.ArrayBuffer.empty[Widget]
- def addWidget[T <: Widget](widget: T) = {
+ def addCustomWidget[T <: Widget](widget: T) = {
widgets += widget
widget.owner = this
widget
@@ -17,7 +20,7 @@ trait WidgetContainer {
def windowZ = 0f
- def drawWidgets() {
- widgets.foreach(_.draw())
+ def drawWidgets(stack: MatrixStack) {
+ widgets.foreach(_.draw(stack))
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala
index 9af67f8e5e..743913a9cd 100644
--- a/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala
@@ -1,17 +1,18 @@
package li.cil.oc.client.renderer
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.client.Textures
-import li.cil.oc.util.ExtendedAABB._
import li.cil.oc.util.ExtendedWorld._
-import li.cil.oc.util.{BlockPosition, RenderState}
-import li.cil.oc.{Constants, Settings, api, common}
+import li.cil.oc.util.BlockPosition
+import li.cil.oc.{Constants, Settings, api}
+import net.minecraft.client.Minecraft
import net.minecraft.client.renderer._
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.{RayTraceResult, Vec3d}
-import net.minecraftforge.client.event.DrawBlockHighlightEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.opengl.GL11
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraftforge.client.event.DrawHighlightEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import scala.util.Random
@@ -20,227 +21,70 @@ object HighlightRenderer {
lazy val tablet = api.Items.get(Constants.ItemName.Tablet)
+ val TexHologram = RenderTypes.createTexturedQuad("hologram_effect", Textures.Model.HologramEffect, DefaultVertexFormats.POSITION_TEX_COLOR, true)
+
@SubscribeEvent
- def onDrawBlockHighlight(e: DrawBlockHighlightEvent): Unit = if (e.getTarget != null && e.getTarget.getBlockPos != null) {
+ def onDrawBlockHighlight(e: DrawHighlightEvent.HighlightBlock): Unit = if (e.getTarget != null && e.getTarget.getBlockPos != null) {
val hitInfo = e.getTarget
- val world = e.getPlayer.getEntityWorld
+ val world = Minecraft.getInstance.level
val blockPos = BlockPosition(hitInfo.getBlockPos, world)
- if (hitInfo.typeOfHit == RayTraceResult.Type.BLOCK && api.Items.get(e.getPlayer.getHeldItemMainhand) == tablet) {
+ val stack = e.getMatrix
+ if (api.Items.get(Minecraft.getInstance.player.getItemInHand(Hand.MAIN_HAND)) == tablet) {
val isAir = world.isAirBlock(blockPos)
if (!isAir) {
- val block = world.getBlock(blockPos)
- val bounds = block.getSelectedBoundingBox(world.getBlockState(hitInfo.getBlockPos), world, hitInfo.getBlockPos).offset(-blockPos.x, -blockPos.y, -blockPos.z)
- val sideHit = hitInfo.sideHit
- val playerPos = new Vec3d(
- e.getPlayer.prevPosX + (e.getPlayer.posX - e.getPlayer.prevPosX) * e.getPartialTicks,
- e.getPlayer.prevPosY + (e.getPlayer.posY - e.getPlayer.prevPosY) * e.getPartialTicks,
- e.getPlayer.prevPosZ + (e.getPlayer.posZ - e.getPlayer.prevPosZ) * e.getPartialTicks)
- val renderPos = blockPos.offset(-playerPos.x, -playerPos.y, -playerPos.z)
-
- GlStateManager.pushMatrix()
- RenderState.pushAttrib()
- RenderState.makeItBlend()
- Textures.bind(Textures.Model.HologramEffect)
+ val shape = world.getBlockState(hitInfo.getBlockPos).getShape(world, hitInfo.getBlockPos, ISelectionContext.of(e.getInfo.getEntity))
+ val (minX, minY, minZ) = (shape.min(Direction.Axis.X).toFloat, shape.min(Direction.Axis.Y).toFloat, shape.min(Direction.Axis.Z).toFloat)
+ val (maxX, maxY, maxZ) = (shape.max(Direction.Axis.X).toFloat, shape.max(Direction.Axis.Y).toFloat, shape.max(Direction.Axis.Z).toFloat)
+ val sideHit = hitInfo.getDirection
+ val view = e.getInfo.getPosition
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
- GlStateManager.color(0.0F, 1.0F, 0.0F, 0.4F)
+ stack.pushPose()
- GlStateManager.translate(renderPos.x, renderPos.y, renderPos.z)
- GlStateManager.scale(1.002, 1.002, 1.002)
+ stack.translate(blockPos.x - view.x, blockPos.y - view.y, blockPos.z - view.z)
+ stack.scale(1.002f, 1.002f, 1.002f)
if (Settings.get.hologramFlickerFrequency > 0 && random.nextDouble() < Settings.get.hologramFlickerFrequency) {
- val (sx, sy, sz) = (1 - math.abs(sideHit.getFrontOffsetX), 1 - math.abs(sideHit.getFrontOffsetY), 1 - math.abs(sideHit.getFrontOffsetZ))
- GlStateManager.scale(1 + random.nextGaussian() * 0.01, 1 + random.nextGaussian() * 0.001, 1 + random.nextGaussian() * 0.01)
- GlStateManager.translate(random.nextGaussian() * 0.01 * sx, random.nextGaussian() * 0.01 * sy, random.nextGaussian() * 0.01 * sz)
+ val (sx, sy, sz) = (1 - math.abs(sideHit.getStepX), 1 - math.abs(sideHit.getStepY), 1 - math.abs(sideHit.getStepZ))
+ stack.scale(1f + (random.nextGaussian() * 0.01).toFloat, 1f + (random.nextGaussian() * 0.001).toFloat, 1f + (random.nextGaussian() * 0.01).toFloat)
+ stack.translate((random.nextGaussian() * 0.01 * sx).toFloat, (random.nextGaussian() * 0.01 * sy).toFloat, (random.nextGaussian() * 0.01 * sz).toFloat)
}
- val t = Tessellator.getInstance()
- val r = t.getBuffer
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = e.getBuffers.getBuffer(TexHologram)
sideHit match {
- case EnumFacing.UP =>
- r.pos(bounds.maxX, bounds.maxY + 0.002, bounds.maxZ).tex(bounds.maxZ * 16, bounds.maxX * 16).endVertex()
- r.pos(bounds.maxX, bounds.maxY + 0.002, bounds.minZ).tex(bounds.minZ * 16, bounds.maxX * 16).endVertex()
- r.pos(bounds.minX, bounds.maxY + 0.002, bounds.minZ).tex(bounds.minZ * 16, bounds.minX * 16).endVertex()
- r.pos(bounds.minX, bounds.maxY + 0.002, bounds.maxZ).tex(bounds.maxZ * 16, bounds.minX * 16).endVertex()
- case EnumFacing.DOWN =>
- r.pos(bounds.maxX, bounds.minY - 0.002, bounds.minZ).tex(bounds.minZ * 16, bounds.maxX * 16).endVertex()
- r.pos(bounds.maxX, bounds.minY - 0.002, bounds.maxZ).tex(bounds.maxZ * 16, bounds.maxX * 16).endVertex()
- r.pos(bounds.minX, bounds.minY - 0.002, bounds.maxZ).tex(bounds.maxZ * 16, bounds.minX * 16).endVertex()
- r.pos(bounds.minX, bounds.minY - 0.002, bounds.minZ).tex(bounds.minZ * 16, bounds.minX * 16).endVertex()
- case EnumFacing.EAST =>
- r.pos(bounds.maxX + 0.002, bounds.maxY, bounds.minZ).tex(bounds.minZ * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.maxX + 0.002, bounds.maxY, bounds.maxZ).tex(bounds.maxZ * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.maxX + 0.002, bounds.minY, bounds.maxZ).tex(bounds.maxZ * 16, bounds.minY * 16).endVertex()
- r.pos(bounds.maxX + 0.002, bounds.minY, bounds.minZ).tex(bounds.minZ * 16, bounds.minY * 16).endVertex()
- case EnumFacing.WEST =>
- r.pos(bounds.minX - 0.002, bounds.maxY, bounds.maxZ).tex(bounds.maxZ * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.minX - 0.002, bounds.maxY, bounds.minZ).tex(bounds.minZ * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.minX - 0.002, bounds.minY, bounds.minZ).tex(bounds.minZ * 16, bounds.minY * 16).endVertex()
- r.pos(bounds.minX - 0.002, bounds.minY, bounds.maxZ).tex(bounds.maxZ * 16, bounds.minY * 16).endVertex()
- case EnumFacing.SOUTH =>
- r.pos(bounds.maxX, bounds.maxY, bounds.maxZ + 0.002).tex(bounds.maxX * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.minX, bounds.maxY, bounds.maxZ + 0.002).tex(bounds.minX * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.minX, bounds.minY, bounds.maxZ + 0.002).tex(bounds.minX * 16, bounds.minY * 16).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.maxZ + 0.002).tex(bounds.maxX * 16, bounds.minY * 16).endVertex()
+ case Direction.UP =>
+ r.vertex(stack.last.pose, maxX, maxY + 0.002f, maxZ).uv(maxZ * 16, maxX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY + 0.002f, minZ).uv(minZ * 16, maxX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, maxY + 0.002f, minZ).uv(minZ * 16, minX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, maxY + 0.002f, maxZ).uv(maxZ * 16, minX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ case Direction.DOWN =>
+ r.vertex(stack.last.pose, maxX, minY - 0.002f, minZ).uv(minZ * 16, maxX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX, minY - 0.002f, maxZ).uv(maxZ * 16, maxX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, minY - 0.002f, maxZ).uv(maxZ * 16, minX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, minY - 0.002f, minZ).uv(minZ * 16, minX * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ case Direction.EAST =>
+ r.vertex(stack.last.pose, maxX + 0.002f, maxY, minZ).uv(minZ * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX + 0.002f, maxY, maxZ).uv(maxZ * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX + 0.002f, minY, maxZ).uv(maxZ * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX + 0.002f, minY, minZ).uv(minZ * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ case Direction.WEST =>
+ r.vertex(stack.last.pose, minX - 0.002f, maxY, maxZ).uv(maxZ * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX - 0.002f, maxY, minZ).uv(minZ * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX - 0.002f, minY, minZ).uv(minZ * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX - 0.002f, minY, maxZ).uv(maxZ * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ case Direction.SOUTH =>
+ r.vertex(stack.last.pose, maxX, maxY, maxZ + 0.002f).uv(maxX * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, maxZ + 0.002f).uv(minX * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, minY, maxZ + 0.002f).uv(minX * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, maxZ + 0.002f).uv(maxX * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
case _ =>
- r.pos(bounds.minX, bounds.maxY, bounds.minZ - 0.002).tex(bounds.minX * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.maxX, bounds.maxY, bounds.minZ - 0.002).tex(bounds.maxX * 16, bounds.maxY * 16).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.minZ - 0.002).tex(bounds.maxX * 16, bounds.minY * 16).endVertex()
- r.pos(bounds.minX, bounds.minY, bounds.minZ - 0.002).tex(bounds.minX * 16, bounds.minY * 16).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, minZ - 0.002f).uv(minX * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY, minZ - 0.002f).uv(maxX * 16, maxY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, minZ - 0.002f).uv(maxX * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
+ r.vertex(stack.last.pose, minX, minY, minZ - 0.002f).uv(minX * 16, minY * 16).color(0.0F, 1.0F, 0.0F, 0.4F).endVertex()
}
- t.draw()
- RenderState.disableBlend()
- RenderState.popAttrib()
- GlStateManager.popMatrix()
+ stack.popPose()
}
}
-
- if (hitInfo.typeOfHit == RayTraceResult.Type.BLOCK) e.getPlayer.getEntityWorld.getTileEntity(hitInfo.getBlockPos) match {
- case print: common.tileentity.Print if print.shapes.nonEmpty =>
- val pos = new Vec3d(
- e.getPlayer.prevPosX + (e.getPlayer.posX - e.getPlayer.prevPosX) * e.getPartialTicks,
- e.getPlayer.prevPosY + (e.getPlayer.posY - e.getPlayer.prevPosY) * e.getPartialTicks,
- e.getPlayer.prevPosZ + (e.getPlayer.posZ - e.getPlayer.prevPosZ) * e.getPartialTicks)
- val expansion = 0.002f
-
- // See RenderGlobal.drawSelectionBox.
- GlStateManager.enableBlend()
- OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 1)
- GlStateManager.color(0, 0, 0, 0.4f)
- GlStateManager.glLineWidth(2)
- GlStateManager.disableTexture2D()
- GlStateManager.depthMask(false)
-
- for (shape <- print.shapes) {
- val bounds = shape.bounds.rotateTowards(print.facing)
- RenderGlobal.drawSelectionBoundingBox(bounds.grow(expansion, expansion, expansion)
- .offset(blockPos.x, blockPos.y, blockPos.z)
- .offset(-pos.x, -pos.y, -pos.z), 0, 0, 0, 0x66/0xFFf.toFloat)
- }
-
- GlStateManager.depthMask(true)
- GlStateManager.enableTexture2D()
- GlStateManager.disableBlend()
-
- e.setCanceled(true)
- case cable: common.tileentity.Cable =>
- // See RenderGlobal.drawSelectionBox.
- GlStateManager.enableBlend()
- OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 1)
- GlStateManager.color(0, 0, 0, 0.4f)
- GlStateManager.glLineWidth(2)
- GlStateManager.disableTexture2D()
- GlStateManager.depthMask(false)
- GlStateManager.pushMatrix()
-
- val player = e.getPlayer
- GlStateManager.translate(
- blockPos.x - (player.lastTickPosX + (player.posX - player.lastTickPosX) * e.getPartialTicks),
- blockPos.y - (player.lastTickPosY + (player.posY - player.lastTickPosY) * e.getPartialTicks),
- blockPos.z - (player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * e.getPartialTicks)
- )
-
- val mask = common.block.Cable.neighbors(world, hitInfo.getBlockPos)
- val tesselator = Tessellator.getInstance
- val buffer = tesselator.getBuffer
-
- buffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION)
- Cable.drawOverlay(buffer, mask)
- tesselator.draw()
-
- GlStateManager.popMatrix()
- GlStateManager.depthMask(true)
- GlStateManager.enableTexture2D()
- GlStateManager.disableBlend()
-
- e.setCanceled(true)
- case _ =>
- }
}
-
- private object Cable {
- private final val EXPAND = 0.002f
- private final val MIN = common.block.Cable.MIN - EXPAND
- private final val MAX = common.block.Cable.MAX + EXPAND
-
- def drawOverlay(buffer: BufferBuilder, mask: Int): Unit = {
- // Draw the cable arms
- for (side <- EnumFacing.values) {
- if (((1 << side.getIndex) & mask) != 0) {
- val offset = if (side.getAxisDirection == EnumFacing.AxisDirection.NEGATIVE) -EXPAND else 1 + EXPAND
- val centre = if (side.getAxisDirection == EnumFacing.AxisDirection.NEGATIVE) MIN else MAX
-
- // Draw the arm end quad
- drawLineAdjacent(buffer, side.getAxis, offset, MIN, MIN, MIN, MAX)
- drawLineAdjacent(buffer, side.getAxis, offset, MIN, MAX, MAX, MAX)
- drawLineAdjacent(buffer, side.getAxis, offset, MAX, MAX, MAX, MIN)
- drawLineAdjacent(buffer, side.getAxis, offset, MAX, MIN, MIN, MIN)
-
- // Draw the connecting lines to the middle
- drawLineAlong(buffer, side.getAxis, MIN, MIN, offset, centre)
- drawLineAlong(buffer, side.getAxis, MAX, MIN, offset, centre)
- drawLineAlong(buffer, side.getAxis, MAX, MAX, offset, centre)
- drawLineAlong(buffer, side.getAxis, MIN, MAX, offset, centre)
- }
- }
-
- // Draw the cable core
- drawCore(buffer, mask, EnumFacing.WEST, EnumFacing.DOWN, EnumFacing.Axis.Z)
- drawCore(buffer, mask, EnumFacing.WEST, EnumFacing.UP, EnumFacing.Axis.Z)
- drawCore(buffer, mask, EnumFacing.EAST, EnumFacing.DOWN, EnumFacing.Axis.Z)
- drawCore(buffer, mask, EnumFacing.EAST, EnumFacing.UP, EnumFacing.Axis.Z)
-
- drawCore(buffer, mask, EnumFacing.WEST, EnumFacing.NORTH, EnumFacing.Axis.Y)
- drawCore(buffer, mask, EnumFacing.WEST, EnumFacing.SOUTH, EnumFacing.Axis.Y)
- drawCore(buffer, mask, EnumFacing.EAST, EnumFacing.NORTH, EnumFacing.Axis.Y)
- drawCore(buffer, mask, EnumFacing.EAST, EnumFacing.SOUTH, EnumFacing.Axis.Y)
-
- drawCore(buffer, mask, EnumFacing.DOWN, EnumFacing.NORTH, EnumFacing.Axis.X)
- drawCore(buffer, mask, EnumFacing.DOWN, EnumFacing.SOUTH, EnumFacing.Axis.X)
- drawCore(buffer, mask, EnumFacing.UP, EnumFacing.NORTH, EnumFacing.Axis.X)
- drawCore(buffer, mask, EnumFacing.UP, EnumFacing.SOUTH, EnumFacing.Axis.X)
- }
-
- /** Draw part of the core object */
- private def drawCore(buffer: BufferBuilder, mask: Int, a: EnumFacing, b: EnumFacing, other: EnumFacing.Axis): Unit = {
- if (((mask >> a.ordinal) & 1) != ((mask >> b.ordinal) & 1)) return
-
- val offA = if (a.getAxisDirection == EnumFacing.AxisDirection.NEGATIVE) MIN else MAX
- val offB = if (b.getAxisDirection == EnumFacing.AxisDirection.NEGATIVE) MIN else MAX
- drawLineAlong(buffer, other, offA, offB, MIN, MAX)
- }
-
- /** Draw a line parallel to an axis */
- private def drawLineAlong(buffer: BufferBuilder, axis: EnumFacing.Axis, offA: Double, offB: Double, start: Double, end: Double): Unit = {
- axis match {
- case EnumFacing.Axis.X =>
- buffer.pos(start, offA, offB).endVertex()
- buffer.pos(end, offA, offB).endVertex()
- case EnumFacing.Axis.Y =>
- buffer.pos(offA, start, offB).endVertex()
- buffer.pos(offA, end, offB).endVertex()
- case EnumFacing.Axis.Z =>
- buffer.pos(offA, offB, start).endVertex()
- buffer.pos(offA, offB, end).endVertex()
- }
- }
-
- /** Draw a line perpendicular to an axis */
- private def drawLineAdjacent(buffer: BufferBuilder, axis: EnumFacing.Axis, offset: Double, startA: Double, startB: Double, endA: Double, endB: Double): Unit = {
- axis match {
- case EnumFacing.Axis.X =>
- buffer.pos(offset, startA, startB).endVertex()
- buffer.pos(offset, endA, endB).endVertex()
- case EnumFacing.Axis.Y =>
- buffer.pos(startA, offset, startB).endVertex()
- buffer.pos(endA, offset, endB).endVertex()
- case EnumFacing.Axis.Z =>
- buffer.pos(startA, startB, offset).endVertex()
- buffer.pos(endA, endB, offset).endVertex()
- }
- }
- }
-
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/MFUTargetRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/MFUTargetRenderer.scala
index 91850577b5..dd7f6f150f 100644
--- a/src/main/scala/li/cil/oc/client/renderer/MFUTargetRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/MFUTargetRenderer.scala
@@ -1,63 +1,60 @@
package li.cil.oc.client.renderer
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.RenderType
import net.minecraft.item.ItemStack
+import net.minecraft.util.Hand
+import net.minecraft.util.ResourceLocation
+import net.minecraft.util.math.vector.Vector4f
+import net.minecraft.util.math.vector.Matrix4f
import net.minecraftforge.client.event.RenderWorldLastEvent
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.opengl.GL11
+import net.minecraftforge.eventbus.api.SubscribeEvent
object MFUTargetRenderer {
- private val color = 0x00FF00
+ private val (drawRed, drawGreen, drawBlue) = (0.0f, 1.0f, 0.0f)
+
private lazy val mfu = api.Items.get(Constants.ItemName.MFU)
@SubscribeEvent
def onRenderWorldLastEvent(e: RenderWorldLastEvent) {
- val mc = Minecraft.getMinecraft
+ val mc = Minecraft.getInstance
val player = mc.player
if (player == null) return
- player.getHeldItemMainhand match {
- case stack: ItemStack if api.Items.get(stack) == mfu && stack.hasTagCompound =>
- val data = stack.getTagCompound
- if (data.hasKey(Settings.namespace + "coord", NBT.TAG_INT_ARRAY)) {
- val Array(x, y, z, dimension, side) = data.getIntArray(Settings.namespace + "coord")
- if (player.getEntityWorld.provider.getDimension != dimension) return
- if (player.getDistance(x, y, z) > 64) return
-
- val bounds = BlockPosition(x, y, z).bounds.grow(0.1, 0.1, 0.1)
+ player.getItemInHand(Hand.MAIN_HAND) match {
+ case stack: ItemStack if api.Items.get(stack) == mfu && stack.hasTag =>
+ val data = stack.getTag
+ if (data.contains(Settings.namespace + "coord", NBT.TAG_INT_ARRAY)) {
+ val dimension = new ResourceLocation(data.getString(Settings.namespace + "dimension"))
+ if (!player.level.dimension.location.equals(dimension)) return
+ val Array(x, y, z, side) = data.getIntArray(Settings.namespace + "coord")
+ if (player.distanceToSqr(x, y, z) > 64 * 64) return
- val px = player.lastTickPosX + (player.posX - player.lastTickPosX) * e.getPartialTicks
- val py = player.lastTickPosY + (player.posY - player.lastTickPosY) * e.getPartialTicks
- val pz = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * e.getPartialTicks
+ val bounds = BlockPosition(x, y, z).bounds.inflate(0.1, 0.1, 0.1)
RenderState.checkError(getClass.getName + ".onRenderWorldLastEvent: entering (aka: wasntme)")
- GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
- GL11.glPushMatrix()
- GL11.glTranslated(-px, -py, -pz)
- RenderState.makeItBlend()
- GL11.glDisable(GL11.GL_LIGHTING)
- GL11.glDisable(GL11.GL_TEXTURE_2D)
- GL11.glDisable(GL11.GL_DEPTH_TEST)
- GL11.glDisable(GL11.GL_CULL_FACE)
+ val matrix = e.getMatrixStack
+ matrix.pushPose()
+ val camPos = Minecraft.getInstance.gameRenderer.getMainCamera.getPosition
+ matrix.translate(-camPos.x, -camPos.y, -camPos.z)
- GL11.glColor4f(
- ((color >> 16) & 0xFF) / 255f,
- ((color >> 8) & 0xFF) / 255f,
- ((color >> 0) & 0xFF) / 255f,
- 0.25f)
- GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE)
- drawBox(bounds.minX, bounds.minY, bounds.minZ, bounds.maxX, bounds.maxY, bounds.maxZ)
- GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL)
- drawFace(bounds.minX, bounds.minY, bounds.minZ, bounds.maxX, bounds.maxY, bounds.maxZ, side)
+ RenderSystem.disableDepthTest() // Default state for depth test is disabled, but it's enabled here so we have to change it manually.
+ val buffer = Minecraft.getInstance.renderBuffers.bufferSource
+ drawBox(matrix.last.pose, buffer.getBuffer(RenderTypes.MFU_LINES), bounds.minX.toFloat, bounds.minY.toFloat, bounds.minZ.toFloat,
+ bounds.maxX.toFloat, bounds.maxY.toFloat, bounds.maxZ.toFloat, drawRed, drawGreen, drawBlue)
+ drawFace(matrix.last.pose, buffer.getBuffer(RenderTypes.MFU_QUADS), bounds.minX.toFloat, bounds.minY.toFloat, bounds.minZ.toFloat,
+ bounds.maxX.toFloat, bounds.maxY.toFloat, bounds.maxZ.toFloat, side, drawRed, drawGreen, drawBlue)
+ buffer.endBatch()
- GL11.glPopMatrix()
- GL11.glPopAttrib()
+ matrix.popPose()
RenderState.checkError(getClass.getName + ".onRenderWorldLastEvent: leaving")
}
@@ -65,89 +62,70 @@ object MFUTargetRenderer {
}
}
- private def drawBox(minX: Double, minY: Double, minZ: Double, maxX: Double, maxY: Double, maxZ: Double) {
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glEnd()
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glEnd()
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glEnd()
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glEnd()
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glEnd()
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glEnd()
+ def drawBox(matrix: Matrix4f, builder: IVertexBuilder, minX: Float, minY: Float, minZ: Float, maxX: Float, maxY: Float, maxZ: Float, r: Float, g: Float, b: Float) {
+ // Bottom square.
+ builder.vertex(matrix, minX, minY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, minY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, minY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, minY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, minY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, minY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, minY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, minY, minZ).color(r, g, b, 0.5f).endVertex()
+
+ // Vertical bars.
+ builder.vertex(matrix, minX, minY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, maxY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, minY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, maxY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, minY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, maxY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, minY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, maxY, maxZ).color(r, g, b, 0.5f).endVertex()
+
+ // Top square.
+ builder.vertex(matrix, maxX, maxY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, maxY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, maxY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, maxY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, maxY, maxZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, maxY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, minX, maxY, minZ).color(r, g, b, 0.5f).endVertex()
+ builder.vertex(matrix, maxX, maxY, minZ).color(r, g, b, 0.5f).endVertex()
}
- private def drawFace(minX: Double, minY: Double, minZ: Double, maxX: Double, maxY: Double, maxZ: Double, side: Int): Unit = {
+ private def drawFace(matrix: Matrix4f, builder: IVertexBuilder, minX: Float, minY: Float, minZ: Float, maxX: Float, maxY: Float, maxZ: Float, side: Int, r: Float, g: Float, b: Float): Unit = {
side match {
case 0 => // Down
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glEnd()
+ builder.vertex(matrix, minX, minY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, minY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, minY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, minY, minZ).color(r, g, b, 0.25f).endVertex()
case 1 => // Up
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glEnd()
+ builder.vertex(matrix, maxX, maxY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, maxY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, maxY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, maxY, minZ).color(r, g, b, 0.25f).endVertex()
case 2 => // North
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glEnd()
+ builder.vertex(matrix, minX, minY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, minY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, maxY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, maxY, minZ).color(r, g, b, 0.25f).endVertex()
case 3 => // South
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glEnd()
+ builder.vertex(matrix, maxX, maxY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, minY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, minY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, maxY, maxZ).color(r, g, b, 0.25f).endVertex()
case 4 => // East
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glEnd()
+ builder.vertex(matrix, minX, minY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, maxY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, maxY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, minX, minY, maxZ).color(r, g, b, 0.25f).endVertex()
case 5 => // West
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glEnd()
+ builder.vertex(matrix, maxX, minY, minZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, minY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, maxY, maxZ).color(r, g, b, 0.25f).endVertex()
+ builder.vertex(matrix, maxX, maxY, minZ).color(r, g, b, 0.25f).endVertex()
case _ => // WTF?
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/PetRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/PetRenderer.scala
index fb1d5b2eef..b062debe4d 100644
--- a/src/main/scala/li/cil/oc/client/renderer/PetRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/PetRenderer.scala
@@ -4,18 +4,22 @@ import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import com.google.common.cache.CacheBuilder
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.api.event.RobotRenderEvent
import li.cil.oc.client.renderer.tileentity.RobotRenderer
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
import net.minecraft.entity.Entity
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.util.math.vector.Vector3f
import net.minecraftforge.client.event.RenderPlayerEvent
-import net.minecraftforge.fml.common.eventhandler.EventPriority
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
+import net.minecraftforge.eventbus.api.EventPriority
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.event.TickEvent.ClientTickEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
object PetRenderer {
@@ -35,7 +39,8 @@ object PetRenderer {
"076541f1-f10a-46de-a127-dfab8adfbb75" ->(0.2, 1.0, 0.1), // vifino
"e7e90198-0ccf-4662-a827-192ec8f4419d" ->(0.0, 0.2, 0.6), // Izaya
"f514ee69-7bbb-4e46-9e94-d8176324cec2" ->(0.098, 0.471, 0.784), // Wobbo
- "f812c043-78ba-4324-82ae-e8f05c52ae6e" ->(0.1, 0.8, 0.5) // payonel
+ "f812c043-78ba-4324-82ae-e8f05c52ae6e" ->(0.1, 0.8, 0.5), // payonel
+ "1db17ee7-8830-4bac-8018-de154340aae6" ->(0.0, 0.5, 1.0) // Kosmos
)
private val petLocations = com.google.common.cache.CacheBuilder.newBuilder().
@@ -47,45 +52,36 @@ object PetRenderer {
@SubscribeEvent
def onPlayerRender(e: RenderPlayerEvent.Pre) {
- val uuid = e.getEntityPlayer.getUniqueID.toString
+ val uuid = e.getPlayer.getUUID.toString
if (hidden.contains(uuid) || !entitledPlayers.contains(uuid)) return
rendering = Some(entitledPlayers(uuid))
- val worldTime = e.getEntityPlayer.getEntityWorld.getTotalWorldTime
- val timeJitter = e.getEntityPlayer.hashCode ^ 0xFF
+ val worldTime = e.getPlayer.level.getGameTime
+ val timeJitter = e.getPlayer.hashCode ^ 0xFF
val offset = timeJitter + worldTime / 20.0
val hover = (math.sin(timeJitter + (worldTime + e.getPartialRenderTick) / 20.0) * 0.03).toFloat
- val location = petLocations.get(e.getEntityPlayer, new Callable[PetLocation] {
- override def call() = new PetLocation(e.getEntityPlayer)
+ val location = petLocations.get(e.getPlayer, new Callable[PetLocation] {
+ override def call() = new PetLocation(e.getPlayer)
})
- GlStateManager.pushMatrix()
- RenderState.pushAttrib()
- val localPos = Minecraft.getMinecraft.player.getPositionEyes(e.getPartialRenderTick)
- val playerPos = e.getEntityPlayer.getPositionEyes(e.getPartialRenderTick)
- val correction = 1.62 - (if (e.getEntityPlayer.isSneaking) 0.125 else 0)
- GlStateManager.translate(
- playerPos.x - localPos.x,
- playerPos.y - localPos.y + correction,
- playerPos.z - localPos.z)
+ val stack = e.getMatrixStack
+ stack.pushPose()
+ val self = Minecraft.getInstance.player
+ val other = e.getPlayer
+ val px = other.xOld + (other.getX - other.xOld) * e.getPartialRenderTick
+ val py = other.yOld + (other.getY - other.yOld) * e.getPartialRenderTick + other.getEyeHeight(other.getPose)
+ val pz = other.zOld + (other.getZ - other.zOld) * e.getPartialRenderTick
+ stack.translate(px - self.getX, py - self.getY, pz - self.getZ)
- RenderState.enableEntityLighting()
- GlStateManager.disableBlend()
- GlStateManager.enableRescaleNormal()
- GlStateManager.color(1, 1, 1, 1)
+ location.applyInterpolatedTransformations(stack, e.getPartialRenderTick)
- location.applyInterpolatedTransformations(e.getPartialRenderTick)
+ stack.scale(0.3f, 0.3f, 0.3f)
+ stack.translate(0, hover, 0)
- GlStateManager.scale(0.3f, 0.3f, 0.3f)
- GlStateManager.translate(0, hover, 0)
+ RobotRenderer.renderChassis(stack, e.getBuffers, e.getLight, offset, isRunningOverride = true)
- RobotRenderer.renderChassis(null, offset, isRunningOverride = true)
-
- GlStateManager.disableRescaleNormal()
-
- RenderState.popAttrib()
- GlStateManager.popMatrix()
+ stack.popPose()
rendering = None
}
@@ -93,7 +89,10 @@ object PetRenderer {
@SubscribeEvent(priority = EventPriority.LOWEST)
def onRobotRender(e: RobotRenderEvent) {
rendering match {
- case Some((r, g, b)) => GlStateManager.color(r.toFloat, g.toFloat, b.toFloat)
+ case Some((r, g, b)) => {
+ e.setLightColor(r.toFloat, g.toFloat, b.toFloat)
+ e.multiplyColors(r.toFloat, g.toFloat, b.toFloat)
+ }
case _ =>
}
}
@@ -102,7 +101,7 @@ object PetRenderer {
var x = 0.0
var y = 0.0
var z = 0.0
- var yaw = owner.rotationYaw
+ var yaw = owner.yRot
var lastX = x
var lastY = y
@@ -110,10 +109,10 @@ object PetRenderer {
var lastYaw = yaw
def update() {
- val dx = owner.lastTickPosX - owner.posX
- val dy = owner.lastTickPosY - owner.posY
- val dz = owner.lastTickPosZ - owner.posZ
- val dYaw = owner.rotationYaw - yaw
+ val dx = owner.xOld - owner.getX
+ val dy = owner.yOld - owner.getY
+ val dz = owner.zOld - owner.getZ
+ val dYaw = owner.yRot - yaw
lastX = x
lastY = y
lastZ = z
@@ -127,23 +126,23 @@ object PetRenderer {
yaw += dYaw * 0.2f
}
- def applyInterpolatedTransformations(dt: Float) {
+ def applyInterpolatedTransformations(stack: MatrixStack, dt: Float) {
val ix = lastX + (x - lastX) * dt
val iy = lastY + (y - lastY) * dt
val iz = lastZ + (z - lastZ) * dt
val iYaw = lastYaw + (yaw - lastYaw) * dt
- GlStateManager.translate(ix, iy, iz)
+ stack.translate(ix, iy, iz)
if (!isForInventory) {
- GlStateManager.rotate(-iYaw, 0, 1, 0)
+ stack.mulPose(Vector3f.YP.rotationDegrees(-iYaw))
}
else {
- GlStateManager.rotate(-owner.rotationYaw, 0, 1, 0)
+ stack.mulPose(Vector3f.YP.rotationDegrees(-owner.yRot))
}
- GlStateManager.translate(0.3, -0.1, -0.2)
+ stack.translate(0.3, -0.1, -0.2)
}
- private def isForInventory = Minecraft.getMinecraft.currentScreen != null && owner == Minecraft.getMinecraft.player
+ private def isForInventory = Minecraft.getInstance.screen != null && owner == Minecraft.getInstance.player
}
@SubscribeEvent
diff --git a/src/main/scala/li/cil/oc/client/renderer/RenderCache.java b/src/main/scala/li/cil/oc/client/renderer/RenderCache.java
new file mode 100644
index 0000000000..435384e36f
--- /dev/null
+++ b/src/main/scala/li/cil/oc/client/renderer/RenderCache.java
@@ -0,0 +1,113 @@
+package li.cil.oc.client.renderer
+;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.IVertexBuilder;
+import com.mojang.datafixers.util.Pair;
+import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.BufferBuilder.DrawState;
+import net.minecraft.client.renderer.GLAllocation;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.Tessellator;
+import org.lwjgl.system.MemoryUtil;
+
+public class RenderCache implements IRenderTypeBuffer {
+ public static class DrawEntry {
+ private final RenderType type;
+ private final DrawState state;
+ private final ByteBuffer data;
+
+ public DrawEntry(RenderType type, DrawState state, ByteBuffer data, boolean copy) {
+ this.type = type;
+ this.state = state;
+ if (copy)
+ {
+ int bufferCap = state.format().getVertexSize() * state.vertexCount();
+ ByteBuffer temp = GLAllocation.createByteBuffer(bufferCap);
+ temp.put(data).flip();
+ data = temp;
+ }
+ this.data = data;
+ }
+
+ public RenderType type() {
+ return type;
+ }
+
+ public DrawState state() {
+ return state;
+ }
+
+ public ByteBuffer data() {
+ return data;
+ }
+ }
+
+ private final List cached;
+ private RenderType activeType;
+ private BufferBuilder activeBuilder;
+
+ public RenderCache() {
+ cached = new ArrayList<>();
+ }
+
+ public boolean isEmpty() {
+ return cached.isEmpty();
+ }
+
+ public void clear() {
+ cached.clear();
+ }
+
+ private void flush(RenderType type) {
+ if (type == activeType) {
+ activeBuilder.end();
+ Pair rendered = activeBuilder.popNextBuffer();
+ if (rendered.getSecond().hasRemaining()) {
+ cached.add(new DrawEntry(type, rendered.getFirst(), rendered.getSecond(), true));
+ }
+ activeType = null;
+ }
+ }
+
+ @Override
+ public IVertexBuilder getBuffer(RenderType type) {
+ if (type == null) throw new NullPointerException(); // Same as vanilla.
+ if (activeType != null) {
+ if (activeType == type) return activeBuilder;
+ flush(activeType);
+ }
+ activeType = type;
+ activeBuilder = Tessellator.getInstance().getBuilder();
+ activeBuilder.clear();
+ activeBuilder.begin(type.mode(), type.format());
+ return activeBuilder;
+ }
+
+ public void finish() {
+ // Flush the last active type (if any) so it gets rendered too.
+ if (activeType != null) flush(activeType);
+ }
+
+ public void render(MatrixStack stack) {
+ // Apply transform globally so we don't have to update stored vertices.
+ RenderSystem.pushMatrix();
+ RenderSystem.multMatrix(stack.last().pose());
+
+ cached.forEach(frame -> {
+ frame.type().setupRenderState();
+ DrawState state = frame.state();
+ state.format().setupBufferState(MemoryUtil.memAddress(frame.data()));
+ RenderSystem.drawArrays(state.mode(), 0, state.vertexCount());
+ state.format().clearBufferState();
+ frame.type().clearRenderState();
+ });
+
+ RenderSystem.popMatrix();
+ }
+}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/client/renderer/RenderTypes.java b/src/main/scala/li/cil/oc/client/renderer/RenderTypes.java
new file mode 100644
index 0000000000..2817d7ff77
--- /dev/null
+++ b/src/main/scala/li/cil/oc/client/renderer/RenderTypes.java
@@ -0,0 +1,152 @@
+package li.cil.oc.client.renderer;
+
+import java.util.OptionalDouble;
+
+import com.google.common.collect.ImmutableList;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.platform.GlStateManager;
+import li.cil.oc.OpenComputers;
+import li.cil.oc.client.Textures;
+import net.minecraft.client.renderer.RenderState.LineState;
+import net.minecraft.client.renderer.RenderState.TextureState;
+import net.minecraft.client.renderer.RenderState.TexturingState;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.RenderType.State;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.renderer.vertex.VertexFormat;
+import net.minecraft.client.renderer.vertex.VertexFormatElement;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+
+public class RenderTypes extends RenderType {
+ public static final VertexFormat POSITION_TEX_NORMAL = new VertexFormat(new ImmutableList.Builder()
+ .add(DefaultVertexFormats.ELEMENT_POSITION)
+ .add(DefaultVertexFormats.ELEMENT_UV0)
+ .add(DefaultVertexFormats.ELEMENT_NORMAL)
+ .add(DefaultVertexFormats.ELEMENT_PADDING)
+ .build());
+
+ public static final TextureState ROBOT_CHASSIS_TEXTURE = new TextureState(Textures.Model$.MODULE$.Robot(), false, false);
+
+ public static final RenderType ROBOT_CHASSIS = create(OpenComputers.ID() + ":robot_chassis",
+ DefaultVertexFormats.BLOCK, GL11.GL_TRIANGLES, 1024, State.builder()
+ .setTextureState(ROBOT_CHASSIS_TEXTURE)
+ .setDiffuseLightingState(DIFFUSE_LIGHTING)
+ .setLightmapState(LIGHTMAP)
+ .createCompositeState(true));
+
+ public static final RenderType ROBOT_LIGHT = create(OpenComputers.ID() + ":robot_light",
+ DefaultVertexFormats.POSITION_COLOR_TEX, GL11.GL_QUADS, 256, State.builder()
+ .setTextureState(ROBOT_CHASSIS_TEXTURE)
+ .setTransparencyState(LIGHTNING_TRANSPARENCY)
+ .createCompositeState(true));
+
+ private static final RenderType createUpgrade(String name, ResourceLocation texture) {
+ return create(OpenComputers.ID() + ":upgrade_" + name,
+ POSITION_TEX_NORMAL, GL11.GL_QUADS, 1024, State.builder()
+ .setTextureState(new TextureState(texture, false, false))
+ .createCompositeState(true));
+ }
+
+ public static final RenderType UPGRADE_CRAFTING = createUpgrade("crafting", Textures.Model$.MODULE$.UpgradeCrafting());
+
+ public static final RenderType UPGRADE_GENERATOR = createUpgrade("generator", Textures.Model$.MODULE$.UpgradeGenerator());
+
+ public static final RenderType UPGRADE_INVENTORY = createUpgrade("inventory", Textures.Model$.MODULE$.UpgradeInventory());
+
+ public static final RenderType MFU_LINES = create(OpenComputers.ID() + ":mfu_lines",
+ DefaultVertexFormats.POSITION_COLOR, GL11.GL_LINES, 1024, State.builder()
+ .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
+ .setDepthTestState(NO_DEPTH_TEST)
+ .setOutputState(TRANSLUCENT_TARGET)
+ .setLineState(new LineState(OptionalDouble.of(2.0)))
+ .createCompositeState(false));
+
+ public static final RenderType MFU_QUADS = create(OpenComputers.ID() + ":mfu_quads",
+ DefaultVertexFormats.POSITION_COLOR, GL11.GL_QUADS, 256, State.builder()
+ .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
+ .setDepthTestState(NO_DEPTH_TEST)
+ .setCullState(NO_CULL)
+ .setOutputState(TRANSLUCENT_TARGET)
+ .setWriteMaskState(COLOR_WRITE)
+ .createCompositeState(false));
+
+ public static final RenderType BLOCK_OVERLAY = create(OpenComputers.ID() + ":overlay_block",
+ DefaultVertexFormats.POSITION_TEX, GL11.GL_QUADS, 1024, State.builder()
+ .setTextureState(BLOCK_SHEET_MIPPED)
+ .setTransparencyState(LIGHTNING_TRANSPARENCY)
+ .setAlphaState(DEFAULT_ALPHA)
+ .createCompositeState(false));
+
+ public static final RenderType BLOCK_OVERLAY_COLOR = create(OpenComputers.ID() + ":overlay_block",
+ DefaultVertexFormats.POSITION_COLOR_TEX, GL11.GL_QUADS, 1024, State.builder()
+ .setTextureState(BLOCK_SHEET_MIPPED)
+ .setTransparencyState(LIGHTNING_TRANSPARENCY)
+ .setAlphaState(DEFAULT_ALPHA)
+ .createCompositeState(false));
+
+ public static final RenderType FONT_QUAD = create(OpenComputers.ID() + ":font_quad",
+ DefaultVertexFormats.POSITION_COLOR, GL11.GL_QUADS, 1024, State.builder()
+ .setWriteMaskState(COLOR_WRITE)
+ .createCompositeState(false));
+
+ private static class CustomTextureState extends TexturingState {
+ public CustomTextureState(int id) {
+ super("custom_tex_" + id, () -> {
+ // Should already be enabled, but vanilla does it too.
+ RenderSystem.enableTexture();
+ RenderSystem.bindTexture(id);
+ }, () -> {});
+ }
+ }
+
+ private static class LinearTexturingState extends TexturingState {
+ public LinearTexturingState(boolean linear) {
+ super(linear ? "lin_font_texturing" : "near_font_texturing", () -> {
+ // Texture is already bound, only have to make set minify filter.
+ if (linear) GlStateManager._texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+ else GlStateManager._texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ }, () -> {
+ // Nothing to do, the texture was already unbound.
+ });
+ }
+ }
+
+ private static final LinearTexturingState NEAR = new LinearTexturingState(false);
+ private static final LinearTexturingState LINEAR = new LinearTexturingState(true);
+
+ public static final RenderType createFontTex(String name, ResourceLocation texture, boolean linear) {
+ return create(OpenComputers.ID() + ":font_stat_" + name,
+ DefaultVertexFormats.POSITION_COLOR_TEX, GL11.GL_QUADS, 1024, State.builder()
+ // First parameter is blur (i.e. linear filter).
+ // We can't use it because it's also MAG_FILTER.
+ .setTextureState(new TextureState(texture, false, false))
+ .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
+ .setAlphaState(DEFAULT_ALPHA)
+ .setTexturingState(linear ? LINEAR : NEAR)
+ .createCompositeState(false));
+ }
+
+ public static final RenderType createFontTex(int id) {
+ return create(OpenComputers.ID() + ":font_dyn_" + id,
+ DefaultVertexFormats.POSITION_COLOR_TEX, GL11.GL_QUADS, 1024, State.builder()
+ .setTexturingState(new CustomTextureState(id))
+ .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
+ .setAlphaState(DEFAULT_ALPHA)
+ .createCompositeState(false));
+ }
+
+ public static final RenderType createTexturedQuad(String name, ResourceLocation texture, VertexFormat format, boolean additive) {
+ return create(OpenComputers.ID() + ":tex_quad_" + name,
+ format, GL11.GL_QUADS, 1024, State.builder()
+ .setTextureState(new TextureState(texture, false, false))
+ .setTransparencyState(additive ? LIGHTNING_TRANSPARENCY : TRANSLUCENT_TRANSPARENCY)
+ .setAlphaState(DEFAULT_ALPHA)
+ .createCompositeState(false));
+ }
+
+ private RenderTypes() {
+ super(null, null, 0, 0, false, false, null, null);
+ throw new Error();
+ }
+}
diff --git a/src/main/scala/li/cil/oc/client/renderer/TextBufferRenderCache.scala b/src/main/scala/li/cil/oc/client/renderer/TextBufferRenderCache.scala
index e025e22283..9843f3bade 100644
--- a/src/main/scala/li/cil/oc/client/renderer/TextBufferRenderCache.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/TextBufferRenderCache.scala
@@ -1,113 +1,49 @@
package li.cil.oc.client.renderer
-import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import com.google.common.cache.CacheBuilder
-import com.google.common.cache.RemovalListener
-import com.google.common.cache.RemovalNotification
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.Settings
import li.cil.oc.client.renderer.font.TextBufferRenderData
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GLAllocation
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.tileentity.TileEntity
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
-import org.lwjgl.opengl.GL11
+import net.minecraftforge.event.TickEvent.ClientTickEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
-object TextBufferRenderCache extends Callable[Int] with RemovalListener[TileEntity, Int] {
+object TextBufferRenderCache {
val renderer =
if (Settings.get.fontRenderer == "texture") new font.StaticFontRenderer()
else new font.DynamicFontRenderer()
private val cache = com.google.common.cache.CacheBuilder.newBuilder().
expireAfterAccess(2, TimeUnit.SECONDS).
- removalListener(this).
- asInstanceOf[CacheBuilder[TextBufferRenderData, Int]].
- build[TextBufferRenderData, Int]()
-
- // To allow access in cache entry init.
- private var currentBuffer: TextBufferRenderData = _
+ build[TextBufferRenderData, RenderCache]()
// ----------------------------------------------------------------------- //
// Rendering
// ----------------------------------------------------------------------- //
- def render(buffer: TextBufferRenderData) {
- currentBuffer = buffer
- compileOrDraw(cache.get(currentBuffer, this))
- }
-
- private def compileOrDraw(list: Int) = {
- if (currentBuffer.dirty) {
- RenderState.checkError(getClass.getName + ".compileOrDraw: entering (aka: wasntme)")
+ def render(stack: MatrixStack, buffer: TextBufferRenderData) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- for (line <- currentBuffer.data.buffer) {
+ val cached = cache.get(buffer, () => new RenderCache)
+ if (buffer.dirty || cached.isEmpty) {
+ for (line <- buffer.data.buffer) {
renderer.generateChars(line)
}
- val doCompile = !RenderState.compilingDisplayList
- if (doCompile) {
- currentBuffer.dirty = false
- GL11.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE)
-
- RenderState.checkError(getClass.getName + ".compileOrDraw: glNewList")
- }
-
- renderer.drawBuffer(currentBuffer.data, currentBuffer.viewport._1, currentBuffer.viewport._2)
-
- RenderState.checkError(getClass.getName + ".compileOrDraw: drawString")
-
- if (doCompile) {
- GL11.glEndList()
-
- RenderState.checkError(getClass.getName + ".compileOrDraw: glEndList")
- }
-
- RenderState.checkError(getClass.getName + ".compileOrDraw: leaving")
-
- true
- }
- else {
- GL11.glCallList(list)
- GlStateManager.enableTexture2D()
- GlStateManager.depthMask(true)
- GlStateManager.color(1, 1, 1, 1)
-
- // Because display lists and the GlStateManager don't like each other, apparently.
- GL11.glEnable(GL11.GL_TEXTURE_2D)
- RenderState.bindTexture(0)
- GL11.glDepthMask(true)
- GL11.glColor4f(1, 1, 1, 1)
+ buffer.dirty = false
- RenderState.disableBlend()
+ cached.clear()
+ renderer.drawBuffer(new MatrixStack(), cached, buffer.data, buffer.viewport._1, buffer.viewport._2)
+ cached.finish()
- RenderState.checkError(getClass.getName + ".compileOrDraw: glCallList")
+ RenderState.checkError(getClass.getName + ".render: compiled buffer")
}
- }
-
- // ----------------------------------------------------------------------- //
- // Cache
- // ----------------------------------------------------------------------- //
-
- def call = {
- RenderState.checkError(getClass.getName + ".call: entering (aka: wasntme)")
-
- val list = GLAllocation.generateDisplayLists(1)
- currentBuffer.dirty = true // Force compilation.
-
- RenderState.checkError(getClass.getName + ".call: leaving")
-
- list
- }
-
- def onRemoval(e: RemovalNotification[TileEntity, Int]) {
- RenderState.checkError(getClass.getName + ".onRemoval: entering (aka: wasntme)")
- GLAllocation.deleteDisplayLists(e.getValue)
+ cached.render(stack)
- RenderState.checkError(getClass.getName + ".onRemoval: leaving")
+ RenderState.checkError(getClass.getName + ".render: leaving")
}
// ----------------------------------------------------------------------- //
diff --git a/src/main/scala/li/cil/oc/client/renderer/WirelessNetworkDebugRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/WirelessNetworkDebugRenderer.scala
index a0968c505e..21a653c1d6 100644
--- a/src/main/scala/li/cil/oc/client/renderer/WirelessNetworkDebugRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/WirelessNetworkDebugRenderer.scala
@@ -1,14 +1,15 @@
package li.cil.oc.client.renderer
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Settings
import li.cil.oc.server.network.WirelessNetwork
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.util.math.vector.Vector4f
+import net.minecraft.util.math.vector.Matrix4f
import net.minecraft.world.World
import net.minecraftforge.client.event.RenderWorldLastEvent
-import net.minecraftforge.fml.common.ObfuscationReflectionHelper
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.opengl.GL11
object WirelessNetworkDebugRenderer {
@@ -19,63 +20,70 @@ object WirelessNetworkDebugRenderer {
if (Settings.rTreeDebugRenderer) {
RenderState.checkError(getClass.getName + ".onRenderWorldLastEvent: entering (aka: wasntme)")
- val world = ObfuscationReflectionHelper.getPrivateValue(classOf[net.minecraft.client.renderer.RenderGlobal], e.getContext, "theWorld", "field_72769_h", "r").asInstanceOf[World]
- WirelessNetwork.dimensions.get(world.provider.getDimension) match {
+ val world = Minecraft.getInstance.level
+ WirelessNetwork.dimensions.get(world.dimension) match {
case Some(tree) =>
- val mc = Minecraft.getMinecraft
- val player = mc.player
- val px = player.lastTickPosX + (player.posX - player.lastTickPosX) * e.getPartialTicks
- val py = player.lastTickPosY + (player.posY - player.lastTickPosY) * e.getPartialTicks
- val pz = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * e.getPartialTicks
+ val player = Minecraft.getInstance.player
+ val px = player.xOld + (player.getX - player.xOld) * e.getPartialTicks
+ val py = player.yOld + (player.getY - player.yOld) * e.getPartialTicks
+ val pz = player.zOld + (player.getZ - player.zOld) * e.getPartialTicks
+ val stack = e.getMatrixStack
RenderState.pushAttrib()
- GlStateManager.pushMatrix()
- GL11.glTranslated(-px, -py, -pz)
+ stack.pushPose()
+ stack.translate(-px, -py, -pz)
RenderState.makeItBlend()
GL11.glDisable(GL11.GL_LIGHTING)
GL11.glDisable(GL11.GL_TEXTURE_2D)
GL11.glDisable(GL11.GL_DEPTH_TEST)
GL11.glDisable(GL11.GL_CULL_FACE)
- def drawBox(minX: Double, minY: Double, minZ: Double, maxX: Double, maxY: Double, maxZ: Double) {
+ def glVertex(matrix: Matrix4f, temp: Vector4f, x: Float, y: Float, z: Float) {
+ temp.set(x, y, z, 1)
+ temp.transform(matrix)
+ GL11.glVertex3f(temp.x, temp.y, temp.z)
+ }
+
+ def drawBox(matrix: Matrix4f, temp: Vector4f, minX: Float, minY: Float, minZ: Float, maxX: Float, maxY: Float, maxZ: Float) {
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(maxX, minY, minZ)
+ glVertex(matrix, temp, minX, minY, minZ)
+ glVertex(matrix, temp, minX, minY, maxZ)
+ glVertex(matrix, temp, maxX, minY, maxZ)
+ glVertex(matrix, temp, maxX, minY, minZ)
GL11.glEnd()
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glVertex3d(minX, maxY, minZ)
+ glVertex(matrix, temp, minX, minY, minZ)
+ glVertex(matrix, temp, maxX, minY, minZ)
+ glVertex(matrix, temp, maxX, maxY, minZ)
+ glVertex(matrix, temp, minX, maxY, minZ)
GL11.glEnd()
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, maxY, minZ)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glVertex3d(minX, maxY, minZ)
+ glVertex(matrix, temp, maxX, maxY, minZ)
+ glVertex(matrix, temp, maxX, maxY, maxZ)
+ glVertex(matrix, temp, minX, maxY, maxZ)
+ glVertex(matrix, temp, minX, maxY, minZ)
GL11.glEnd()
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(minX, minY, maxZ)
- GL11.glVertex3d(minX, maxY, maxZ)
+ glVertex(matrix, temp, maxX, maxY, maxZ)
+ glVertex(matrix, temp, maxX, minY, maxZ)
+ glVertex(matrix, temp, minX, minY, maxZ)
+ glVertex(matrix, temp, minX, maxY, maxZ)
GL11.glEnd()
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(minX, minY, minZ)
- GL11.glVertex3d(minX, maxY, minZ)
- GL11.glVertex3d(minX, maxY, maxZ)
- GL11.glVertex3d(minX, minY, maxZ)
+ glVertex(matrix, temp, minX, minY, minZ)
+ glVertex(matrix, temp, minX, maxY, minZ)
+ glVertex(matrix, temp, minX, maxY, maxZ)
+ glVertex(matrix, temp, minX, minY, maxZ)
GL11.glEnd()
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex3d(maxX, minY, minZ)
- GL11.glVertex3d(maxX, minY, maxZ)
- GL11.glVertex3d(maxX, maxY, maxZ)
- GL11.glVertex3d(maxX, maxY, minZ)
+ glVertex(matrix, temp, maxX, minY, minZ)
+ glVertex(matrix, temp, maxX, minY, maxZ)
+ glVertex(matrix, temp, maxX, maxY, maxZ)
+ glVertex(matrix, temp, maxX, maxY, minZ)
GL11.glEnd()
}
+ val temp = new Vector4f()
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE)
for (((min, max), level) <- tree.allBounds) {
val (minX, minY, minZ) = min
@@ -86,13 +94,13 @@ object WirelessNetworkDebugRenderer {
((color >> 8) & 0xFF) / 255f,
((color >> 0) & 0xFF) / 255f,
0.25f)
- val size = 0.5 - level * 0.05
- drawBox(minX - size, minY - size, minZ - size, maxX + size, maxY + size, maxZ + size)
+ val size = 0.5f - level * 0.05f
+ drawBox(stack.last.pose, temp, minX.toFloat - size, minY.toFloat - size, minZ.toFloat - size, maxX.toFloat + size, maxY.toFloat + size, maxZ.toFloat + size)
}
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL)
RenderState.popAttrib()
- GlStateManager.popMatrix()
+ stack.popPose()
case _ =>
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/CableModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/CableModel.scala
index a84053bd0d..d8fa5d5684 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/CableModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/CableModel.scala
@@ -4,120 +4,110 @@ import java.util
import java.util.Collections
import li.cil.oc.client.Textures
-import li.cil.oc.common.block
+import li.cil.oc.common.block.property.PropertyCableConnection
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.Mods
-import li.cil.oc.util.BlockPosition
import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.ItemColorizer
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.item.EnumDyeColor
+import net.minecraft.block.BlockState
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.entity.LivingEntity
+import net.minecraft.item.DyeColor
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.World
-import net.minecraftforge.common.property.IExtendedBlockState
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraftforge.client.model.data.IModelData
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.bufferAsJavaList
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
-object CableModel extends CableModel
-
-class CableModel extends SmartBlockModelBase {
+object CableModel extends SmartBlockModelBase {
override def getOverrides: ItemOverrideList = ItemOverride
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] =
- state match {
- case extended: IExtendedBlockState =>
- val neighbors = extended.getValue(block.Cable.NeighborsProp)
- val color = extended.getValue(block.Cable.ColorProp)
- val isCableSide = extended.getValue(block.Cable.IsSideCableProp)
- (neighbors,color,isCableSide) match {
- case (neighbourMask: Integer, color: Integer, isCableOnSideMask: Integer) =>
- val faces = mutable.ArrayBuffer.empty[BakedQuad]
-
- faces ++= bakeQuads(Middle, cableTexture, color)
- for (side <- EnumFacing.values) {
- val connected = (neighbourMask & (1 << side.getIndex)) != 0
- val isCableOnSide = (isCableOnSideMask & (1 << side.getIndex)) != 0
- val (plug, shortBody, longBody) = Connected(side.getIndex)
- if (connected) {
- if (isCableOnSide) {
- faces ++= bakeQuads(longBody, cableTexture, color)
- }
- else {
- faces ++= bakeQuads(shortBody, cableTexture, color)
- faces ++= bakeQuads(plug, cableCapTexture, None)
- }
- }
- else if (((1 << side.getOpposite.getIndex) & neighbourMask) == neighbourMask || neighbourMask == 0) {
- faces ++= bakeQuads(Disconnected(side.getIndex), cableCapTexture, None)
- }
- }
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random, data: IModelData): util.List[BakedQuad] = {
+ data match {
+ case cable: tileentity.Cable if side == null =>
+ val color = cable.getColor
+ val faces = mutable.ArrayBuffer.empty[BakedQuad]
- bufferAsJavaList(faces)
- case _ => super.getQuads(state, side, rand)
+ faces ++= bakeQuads(Middle, cableTexture, color)
+ val directions = Direction.values
+ val numConnected = directions.count(d => state.getValue(PropertyCableConnection.BY_DIRECTION.get(d)) != PropertyCableConnection.Shape.NONE)
+ for (side <- directions) {
+ val shape = state.getValue(PropertyCableConnection.BY_DIRECTION.get(side))
+ val connected = shape != PropertyCableConnection.Shape.NONE
+ val isCableOnSide = shape == PropertyCableConnection.Shape.CABLE
+ val (plug, shortBody, longBody) = Connected(side.get3DDataValue)
+ if (connected) {
+ if (isCableOnSide) {
+ faces ++= bakeQuads(longBody, cableTexture, color)
+ }
+ else {
+ faces ++= bakeQuads(shortBody, cableTexture, color)
+ faces ++= bakeQuads(plug, cableCapTexture, None)
+ }
+ }
+ else {
+ val otherConn = state.getValue(PropertyCableConnection.BY_DIRECTION.get(side.getOpposite)) != PropertyCableConnection.Shape.NONE
+ if ((otherConn && numConnected == 1) || numConnected == 0) {
+ faces ++= bakeQuads(Disconnected(side.get3DDataValue), cableCapTexture, None)
+ }
+ }
}
- case _ => super.getQuads(state, side, rand)
- }
- protected def isCable(pos: BlockPosition) = {
- pos.world match {
- case Some(world) =>
- world.getTileEntity(pos).isInstanceOf[tileentity.Cable]
- case _ => false
+ bufferAsJavaList(faces)
+ case _ => super.getQuads(state, side, rand)
}
}
- protected final val Middle = makeBox(new Vec3d(6 / 16f, 6 / 16f, 6 / 16f), new Vec3d(10 / 16f, 10 / 16f, 10 / 16f))
+ protected final val Middle = makeBox(new Vector3d(6 / 16f, 6 / 16f, 6 / 16f), new Vector3d(10 / 16f, 10 / 16f, 10 / 16f))
// Per side, always plug + short cable + long cable (no plug).
protected final val Connected = Array(
- (makeBox(new Vec3d(5 / 16f, 0 / 16f, 5 / 16f), new Vec3d(11 / 16f, 1 / 16f, 11 / 16f)),
- makeBox(new Vec3d(6 / 16f, 1 / 16f, 6 / 16f), new Vec3d(10 / 16f, 6 / 16f, 10 / 16f)),
- makeBox(new Vec3d(6 / 16f, 0 / 16f, 6 / 16f), new Vec3d(10 / 16f, 6 / 16f, 10 / 16f))),
- (makeBox(new Vec3d(5 / 16f, 15 / 16f, 5 / 16f), new Vec3d(11 / 16f, 16 / 16f, 11 / 16f)),
- makeBox(new Vec3d(6 / 16f, 10 / 16f, 6 / 16f), new Vec3d(10 / 16f, 15 / 16f, 10 / 16f)),
- makeBox(new Vec3d(6 / 16f, 10 / 16f, 6 / 16f), new Vec3d(10 / 16f, 16 / 16f, 10 / 16f))),
- (makeBox(new Vec3d(5 / 16f, 5 / 16f, 0 / 16f), new Vec3d(11 / 16f, 11 / 16f, 1 / 16f)),
- makeBox(new Vec3d(6 / 16f, 6 / 16f, 1 / 16f), new Vec3d(10 / 16f, 10 / 16f, 6 / 16f)),
- makeBox(new Vec3d(6 / 16f, 6 / 16f, 0 / 16f), new Vec3d(10 / 16f, 10 / 16f, 6 / 16f))),
- (makeBox(new Vec3d(5 / 16f, 5 / 16f, 15 / 16f), new Vec3d(11 / 16f, 11 / 16f, 16 / 16f)),
- makeBox(new Vec3d(6 / 16f, 6 / 16f, 10 / 16f), new Vec3d(10 / 16f, 10 / 16f, 15 / 16f)),
- makeBox(new Vec3d(6 / 16f, 6 / 16f, 10 / 16f), new Vec3d(10 / 16f, 10 / 16f, 16 / 16f))),
- (makeBox(new Vec3d(0 / 16f, 5 / 16f, 5 / 16f), new Vec3d(1 / 16f, 11 / 16f, 11 / 16f)),
- makeBox(new Vec3d(1 / 16f, 6 / 16f, 6 / 16f), new Vec3d(6 / 16f, 10 / 16f, 10 / 16f)),
- makeBox(new Vec3d(0 / 16f, 6 / 16f, 6 / 16f), new Vec3d(6 / 16f, 10 / 16f, 10 / 16f))),
- (makeBox(new Vec3d(15 / 16f, 5 / 16f, 5 / 16f), new Vec3d(16 / 16f, 11 / 16f, 11 / 16f)),
- makeBox(new Vec3d(10 / 16f, 6 / 16f, 6 / 16f), new Vec3d(15 / 16f, 10 / 16f, 10 / 16f)),
- makeBox(new Vec3d(10 / 16f, 6 / 16f, 6 / 16f), new Vec3d(16 / 16f, 10 / 16f, 10 / 16f)))
+ (makeBox(new Vector3d(5 / 16f, 0 / 16f, 5 / 16f), new Vector3d(11 / 16f, 1 / 16f, 11 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 1 / 16f, 6 / 16f), new Vector3d(10 / 16f, 6 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 0 / 16f, 6 / 16f), new Vector3d(10 / 16f, 6 / 16f, 10 / 16f))),
+ (makeBox(new Vector3d(5 / 16f, 15 / 16f, 5 / 16f), new Vector3d(11 / 16f, 16 / 16f, 11 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 10 / 16f, 6 / 16f), new Vector3d(10 / 16f, 15 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 10 / 16f, 6 / 16f), new Vector3d(10 / 16f, 16 / 16f, 10 / 16f))),
+ (makeBox(new Vector3d(5 / 16f, 5 / 16f, 0 / 16f), new Vector3d(11 / 16f, 11 / 16f, 1 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 6 / 16f, 1 / 16f), new Vector3d(10 / 16f, 10 / 16f, 6 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 6 / 16f, 0 / 16f), new Vector3d(10 / 16f, 10 / 16f, 6 / 16f))),
+ (makeBox(new Vector3d(5 / 16f, 5 / 16f, 15 / 16f), new Vector3d(11 / 16f, 11 / 16f, 16 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 6 / 16f, 10 / 16f), new Vector3d(10 / 16f, 10 / 16f, 15 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 6 / 16f, 10 / 16f), new Vector3d(10 / 16f, 10 / 16f, 16 / 16f))),
+ (makeBox(new Vector3d(0 / 16f, 5 / 16f, 5 / 16f), new Vector3d(1 / 16f, 11 / 16f, 11 / 16f)),
+ makeBox(new Vector3d(1 / 16f, 6 / 16f, 6 / 16f), new Vector3d(6 / 16f, 10 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(0 / 16f, 6 / 16f, 6 / 16f), new Vector3d(6 / 16f, 10 / 16f, 10 / 16f))),
+ (makeBox(new Vector3d(15 / 16f, 5 / 16f, 5 / 16f), new Vector3d(16 / 16f, 11 / 16f, 11 / 16f)),
+ makeBox(new Vector3d(10 / 16f, 6 / 16f, 6 / 16f), new Vector3d(15 / 16f, 10 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(10 / 16f, 6 / 16f, 6 / 16f), new Vector3d(16 / 16f, 10 / 16f, 10 / 16f)))
)
// Per side, cap only.
protected final val Disconnected = Array(
- makeBox(new Vec3d(6 / 16f, 5 / 16f, 6 / 16f), new Vec3d(10 / 16f, 6 / 16f, 10 / 16f)),
- makeBox(new Vec3d(6 / 16f, 10 / 16f, 6 / 16f), new Vec3d(10 / 16f, 11 / 16f, 10 / 16f)),
- makeBox(new Vec3d(6 / 16f, 6 / 16f, 5 / 16f), new Vec3d(10 / 16f, 10 / 16f, 6 / 16f)),
- makeBox(new Vec3d(6 / 16f, 6 / 16f, 10 / 16f), new Vec3d(10 / 16f, 10 / 16f, 11 / 16f)),
- makeBox(new Vec3d(5 / 16f, 6 / 16f, 6 / 16f), new Vec3d(6 / 16f, 10 / 16f, 10 / 16f)),
- makeBox(new Vec3d(10 / 16f, 6 / 16f, 6 / 16f), new Vec3d(11 / 16f, 10 / 16f, 10 / 16f))
+ makeBox(new Vector3d(6 / 16f, 5 / 16f, 6 / 16f), new Vector3d(10 / 16f, 6 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 10 / 16f, 6 / 16f), new Vector3d(10 / 16f, 11 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 6 / 16f, 5 / 16f), new Vector3d(10 / 16f, 10 / 16f, 6 / 16f)),
+ makeBox(new Vector3d(6 / 16f, 6 / 16f, 10 / 16f), new Vector3d(10 / 16f, 10 / 16f, 11 / 16f)),
+ makeBox(new Vector3d(5 / 16f, 6 / 16f, 6 / 16f), new Vector3d(6 / 16f, 10 / 16f, 10 / 16f)),
+ makeBox(new Vector3d(10 / 16f, 6 / 16f, 6 / 16f), new Vector3d(11 / 16f, 10 / 16f, 10 / 16f))
)
protected def cableTexture = Array.fill(6)(Textures.getSprite(Textures.Block.Cable))
protected def cableCapTexture = Array.fill(6)(Textures.getSprite(Textures.Block.CableCap))
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
+ object ItemOverride extends ItemOverrideList {
class ItemModel(val stack: ItemStack) extends SmartBlockModelBase {
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
- val color = if (ItemColorizer.hasColor(stack)) ItemColorizer.getColor(stack) else Color.rgbValues(EnumDyeColor.SILVER)
+ val color = if (ItemColorizer.hasColor(stack)) ItemColorizer.getColor(stack) else Color.rgbValues(DyeColor.LIGHT_GRAY)
faces ++= bakeQuads(Middle, cableTexture, Some(color))
faces ++= bakeQuads(Connected(0)._2, cableTexture, Some(color))
@@ -129,7 +119,7 @@ class CableModel extends SmartBlockModelBase {
}
}
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = new ItemModel(stack)
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = new ItemModel(stack)
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/DroneModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/DroneModel.scala
index 42a7f104ec..5f8c87dce2 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/DroneModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/DroneModel.scala
@@ -4,42 +4,42 @@ import java.util
import java.util.Collections
import li.cil.oc.client.Textures
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.entity.EntityLivingBase
+import net.minecraft.block.BlockState
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.World
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3d
-import scala.collection.convert.WrapAsJava.bufferAsJavaList
import scala.collection.mutable
+import scala.jdk.CollectionConverters._
object DroneModel extends SmartBlockModelBase {
override def getOverrides: ItemOverrideList = ItemOverride
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
- faces ++= Boxes.flatMap(box => bakeQuads(box, Array.fill(6)(droneTexture), None))
+ faces ++= Boxes.flatMap(box => bakeQuads(box, Array.fill(6)(droneTexture), None).toSeq)
- bufferAsJavaList(faces)
+ faces.asJava
}
protected def droneTexture = Textures.getSprite(Textures.Item.DroneItem)
protected def Boxes = Array(
- makeBox(new Vec3d(1f / 16f, 7f / 16f, 1f / 16f), new Vec3d(7f / 16f, 8f / 16f, 7f / 16f)),
- makeBox(new Vec3d(1f / 16f, 7f / 16f, 9f / 16f), new Vec3d(7f / 16f, 8f / 16f, 15f / 16f)),
- makeBox(new Vec3d(9f / 16f, 7f / 16f, 1f / 16f), new Vec3d(15f / 16f, 8f / 16f, 7f / 16f)),
- makeBox(new Vec3d(9f / 16f, 7f / 16f, 9f / 16f), new Vec3d(15f / 16f, 8f / 16f, 15f / 16f)),
- rotateBox(makeBox(new Vec3d(6f / 16f, 6f / 16f, 6f / 16f), new Vec3d(10f / 16f, 9f / 16f, 10f / 16f)), 45)
+ makeBox(new Vector3d(1f / 16f, 7f / 16f, 1f / 16f), new Vector3d(7f / 16f, 8f / 16f, 7f / 16f)),
+ makeBox(new Vector3d(1f / 16f, 7f / 16f, 9f / 16f), new Vector3d(7f / 16f, 8f / 16f, 15f / 16f)),
+ makeBox(new Vector3d(9f / 16f, 7f / 16f, 1f / 16f), new Vector3d(15f / 16f, 8f / 16f, 7f / 16f)),
+ makeBox(new Vector3d(9f / 16f, 7f / 16f, 9f / 16f), new Vector3d(15f / 16f, 8f / 16f, 15f / 16f)),
+ rotateBox(makeBox(new Vector3d(6f / 16f, 6f / 16f, 6f / 16f), new Vector3d(10f / 16f, 9f / 16f, 10f / 16f)), 45)
)
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = DroneModel
+ object ItemOverride extends ItemOverrideList {
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = DroneModel
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/ModelInitialization.scala b/src/main/scala/li/cil/oc/client/renderer/block/ModelInitialization.scala
index bbfd5ddc42..30e80adde1 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/ModelInitialization.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/ModelInitialization.scala
@@ -1,81 +1,77 @@
package li.cil.oc.client.renderer.block
+import java.util.Random
+
import li.cil.oc.Constants
+import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.item.CustomModel
-import li.cil.oc.common.item.Delegator
-import li.cil.oc.common.item.traits.Delegate
-import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
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.block.statemap.StateMapperBase
+import net.minecraft.client.renderer.BlockModelShapes
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.client.renderer.model.ModelResourceLocation
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.entity.LivingEntity
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
-import net.minecraft.util.ResourceLocation
-import net.minecraft.util.registry.RegistrySimple
+import net.minecraft.util.IItemProvider
+import net.minecraft.util.Direction
import net.minecraftforge.client.event.{ModelBakeEvent, ModelRegistryEvent}
-import net.minecraftforge.client.model.{ModelLoader, ModelLoaderRegistry}
-import net.minecraftforge.common.MinecraftForge
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.client.model.data.IDynamicBakedModel
+import net.minecraftforge.client.model.data.IModelData
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
object ModelInitialization {
- final val CableBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Cable, "normal")
+ final val CableBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Cable, "")
final val CableItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Cable, "inventory")
- final val NetSplitterBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.NetSplitter, "normal")
+ final val NetSplitterBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.NetSplitter, "")
final val NetSplitterItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.NetSplitter, "inventory")
- final val PrintBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Print, "normal")
+ final val PrintBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Print, "")
final val PrintItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Print, "inventory")
- final val RobotBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Robot, "normal")
+ final val RobotBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Robot, "")
final val RobotItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Robot, "inventory")
- final val RobotAfterimageBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.RobotAfterimage, "normal")
- final val RobotAfterimageItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.RobotAfterimage, "inventory")
- final val RackBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Rack, "normal")
+ final val RobotAfterimageBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.RobotAfterimage, "")
+ final val RackBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Rack, "")
private val meshableItems = mutable.ArrayBuffer.empty[Item]
- private val itemDelegates = mutable.ArrayBuffer.empty[(String, Delegate)]
- private val itemDelegatesCustom = mutable.ArrayBuffer.empty[Delegate with CustomModel]
+ private val modelRemappings = mutable.Map.empty[ModelResourceLocation, ModelResourceLocation]
def preInit(): Unit = {
- MinecraftForge.EVENT_BUS.register(this)
-
registerModel(Constants.BlockName.Cable, CableBlockLocation, CableItemLocation)
registerModel(Constants.BlockName.NetSplitter, NetSplitterBlockLocation, NetSplitterItemLocation)
registerModel(Constants.BlockName.Print, PrintBlockLocation, PrintItemLocation)
registerModel(Constants.BlockName.Robot, RobotBlockLocation, RobotItemLocation)
- registerModel(Constants.BlockName.RobotAfterimage, RobotAfterimageBlockLocation, RobotAfterimageItemLocation)
+ registerModel(Constants.BlockName.RobotAfterimage, RobotAfterimageBlockLocation, null)
}
@SubscribeEvent
def onModelRegistration(event: ModelRegistryEvent): Unit = {
- registerItems()
- registerSubItems()
- registerSubItemsCustom()
- }
-
- // ----------------------------------------------------------------------- //
-
- def registerModel(instance: Delegate, id: String): Unit = {
- instance match {
- case customModel: CustomModel => itemDelegatesCustom += customModel
- case _ => itemDelegates += id -> instance
+ val shaper = Minecraft.getInstance.getItemRenderer.getItemModelShaper
+ for (item <- meshableItems) {
+ item match {
+ case custom: CustomModel => custom.registerModelLocations()
+ case _ => {
+ Option(api.Items.get(new ItemStack(item))) match {
+ case Some(descriptor) =>
+ val location = Settings.resourceDomain + ":" + descriptor.name()
+ shaper.register(item, new ModelResourceLocation(location, "inventory"))
+ case _ =>
+ }
+ }
+ }
}
}
- def registerModel(instance: Item, id: String): Unit = {
- meshableItems += instance
- }
+ // ----------------------------------------------------------------------- //
- def registerModel(instance: Block, id: String): Unit = {
- val item = Item.getItemFromBlock(instance)
- registerModel(item, id)
+ def registerModel(instance: IItemProvider, id: String): Unit = {
+ meshableItems += instance.asItem
}
// ----------------------------------------------------------------------- //
@@ -85,48 +81,12 @@ object ModelInitialization {
val block = descriptor.block()
val stack = descriptor.createItemStack(1)
- ModelLoader.setCustomModelResourceLocation(stack.getItem, stack.getMetadata, itemLocation)
- ModelLoader.setCustomStateMapper(block, new StateMapperBase {
- override def getModelResourceLocation(state: IBlockState): ModelResourceLocation = blockLocation
- })
- }
-
- private def registerItems(): Unit = {
- val meshDefinition = new ItemMeshDefinition {
- override def getModelLocation(stack: ItemStack): ModelResourceLocation = {
- Option(api.Items.get(stack)) match {
- case Some(descriptor) =>
- val location = Settings.resourceDomain + ":" + descriptor.name()
- new ModelResourceLocation(location, "inventory")
- case _ => null
- }
- }
+ if (!stack.isEmpty) {
+ val shaper = Minecraft.getInstance.getItemRenderer.getItemModelShaper
+ shaper.register(stack.getItem, itemLocation)
}
-
- for (item <- meshableItems) {
- ModelLoader.setCustomMeshDefinition(item, meshDefinition)
- }
- meshableItems.clear()
- }
-
- private def registerSubItems(): Unit = {
- for ((id, item) <- itemDelegates) {
- val location = Settings.resourceDomain + ":" + id
- ModelLoader.setCustomModelResourceLocation(item.parent, item.itemId, new ModelResourceLocation(location, "inventory"))
- ModelBakery.registerItemVariants(item.parent, new ResourceLocation(location))
- }
- itemDelegates.clear()
- }
-
- private def registerSubItemsCustom(): Unit = {
- for (item <- itemDelegatesCustom) {
- ModelLoader.setCustomMeshDefinition(item.parent, new ItemMeshDefinition {
- override def getModelLocation(stack: ItemStack): ModelResourceLocation = Delegator.subItem(stack) match {
- case Some(subItem: CustomModel) => subItem.getModelLocation(stack)
- case _ => null
- }
- })
- item.registerModelLocations()
+ block.getStateDefinition.getPossibleStates.foreach {
+ modelRemappings += BlockModelShapes.stateToModelLocation(_) -> blockLocation
}
}
@@ -134,22 +94,56 @@ object ModelInitialization {
@SubscribeEvent
def onModelBake(e: ModelBakeEvent): Unit = {
- val registry = e.getModelRegistry.asInstanceOf[RegistrySimple[ModelResourceLocation, IBakedModel]]
-
- registry.putObject(CableBlockLocation, CableModel)
- registry.putObject(CableItemLocation, CableModel)
- registry.putObject(NetSplitterBlockLocation, NetSplitterModel)
- registry.putObject(NetSplitterItemLocation, NetSplitterModel)
- registry.putObject(PrintBlockLocation, PrintModel)
- registry.putObject(PrintItemLocation, PrintModel)
- registry.putObject(RobotBlockLocation, RobotModel)
- registry.putObject(RobotItemLocation, RobotModel)
- registry.putObject(RobotAfterimageBlockLocation, NullModel)
- registry.putObject(RobotAfterimageItemLocation, NullModel)
-
- for (item <- itemDelegatesCustom) {
- item.bakeModels(e)
+ val registry = e.getModelRegistry
+
+ registry.put(CableBlockLocation, CableModel)
+ registry.put(CableItemLocation, CableModel)
+ registry.put(NetSplitterBlockLocation, NetSplitterModel)
+ registry.put(NetSplitterItemLocation, NetSplitterModel)
+ registry.put(PrintBlockLocation, PrintModel)
+ registry.put(PrintItemLocation, PrintModel)
+ registry.put(RobotBlockLocation, RobotModel)
+ registry.put(RobotItemLocation, RobotModel)
+ registry.put(RobotAfterimageBlockLocation, NullModel)
+
+ for (item <- meshableItems) item match {
+ case custom: CustomModel => {
+ custom.bakeModels(e)
+ val originalLocation = new ModelResourceLocation(custom.getRegistryName, "inventory")
+ registry.get(originalLocation) match {
+ case original: IBakedModel => {
+ val overrides = new ItemOverrideList {
+ override def resolve(base: IBakedModel, stack: ItemStack, world: ClientWorld, holder: LivingEntity) =
+ Option(custom.getModelLocation(stack)).map(registry).getOrElse(original)
+ }
+ val fake = new IDynamicBakedModel {
+ @Deprecated
+ override def getQuads(state: BlockState, dir: Direction, rand: Random, data: IModelData) = original.getQuads(state, dir, rand, data)
+
+ override def useAmbientOcclusion() = original.useAmbientOcclusion
+
+ override def isGui3d() = original.isGui3d
+
+ override def usesBlockLight() = original.usesBlockLight
+
+ override def isCustomRenderer() = original.isCustomRenderer
+
+ @Deprecated
+ override def getParticleIcon() = original.getParticleIcon
+
+ @Deprecated
+ override def getTransforms() = original.getTransforms
+
+ override def getOverrides() = overrides
+ }
+ registry.put(originalLocation, fake)
+ }
+ case _ =>
+ }
+ }
+ case _ =>
}
+ meshableItems.clear()
val modelOverrides = Map[String, IBakedModel => IBakedModel](
Constants.BlockName.ScreenTier1 -> (_ => ScreenModel),
@@ -158,17 +152,19 @@ object ModelInitialization {
Constants.BlockName.Rack -> (parent => new ServerRackModel(parent))
)
- registry.getKeys.collect {
- case location: ModelResourceLocation => registry.getObject(location) match {
- case parent: IBakedModel =>
- for ((name, model) <- modelOverrides) {
- val pattern = s"^${Settings.resourceDomain}:$name#.*"
- if (location.toString.matches(pattern)) {
- registry.putObject(location, model(parent))
- }
+ registry.keySet.toArray.foreach {
+ case location: ModelResourceLocation => {
+ for ((name, model) <- modelOverrides) {
+ val pattern = s"^${Settings.resourceDomain}:$name#.*"
+ if (location.toString.matches(pattern)) {
+ registry.put(location, model(registry.get(location)))
}
- case _ =>
+ }
}
+ case _ =>
+ }
+ for ((real, virtual) <- modelRemappings) {
+ registry.put(real, registry.get(virtual))
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/NetSplitterModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/NetSplitterModel.scala
index f446e4895a..6f29ea7cf4 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/NetSplitterModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/NetSplitterModel.scala
@@ -3,72 +3,78 @@ package li.cil.oc.client.renderer.block
import java.util
import java.util.Collections
+import li.cil.oc.OpenComputers
import li.cil.oc.client.Textures
import li.cil.oc.common.block
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.entity.EntityLivingBase
+import net.minecraft.block.BlockState
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.client.renderer.texture.AtlasTexture
+import net.minecraft.client.renderer.texture.TextureAtlasSprite
+import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.World
+import net.minecraft.inventory.container.PlayerContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.ResourceLocation
+import net.minecraft.util.math.vector.Vector3d
import net.minecraftforge.client.event.TextureStitchEvent
-import net.minecraftforge.common.property.IExtendedBlockState
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.client.model.data.IModelData
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsJava.bufferAsJavaList
+import scala.collection.JavaConverters.bufferAsJavaList
import scala.collection.mutable
object NetSplitterModel extends SmartBlockModelBase {
override def getOverrides: ItemOverrideList = ItemOverride
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] =
- state match {
- case extended: IExtendedBlockState =>
- extended.getValue(block.property.PropertyTile.Tile) match {
- case t: tileentity.NetSplitter =>
- val faces = mutable.ArrayBuffer.empty[BakedQuad]
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random, data: IModelData): util.List[BakedQuad] =
+ data match {
+ case t: tileentity.NetSplitter =>
+ val faces = mutable.ArrayBuffer.empty[BakedQuad]
- faces ++= BaseModel
- addSideQuads(faces, EnumFacing.values().map(t.isSideOpen))
+ faces ++= BaseModel
+ addSideQuads(faces, Direction.values().map(t.isSideOpen))
- bufferAsJavaList(faces)
- case _ => super.getQuads(state, side, rand)
- }
+ bufferAsJavaList(faces)
case _ => super.getQuads(state, side, rand)
}
- protected def splitterTexture = Array(
- Textures.getSprite(Textures.Block.NetSplitterTop),
- Textures.getSprite(Textures.Block.NetSplitterTop),
- Textures.getSprite(Textures.Block.NetSplitterSide),
- Textures.getSprite(Textures.Block.NetSplitterSide),
- Textures.getSprite(Textures.Block.NetSplitterSide),
- Textures.getSprite(Textures.Block.NetSplitterSide)
+ private def getSprite(location: ResourceLocation, atlas: Option[AtlasTexture]): TextureAtlasSprite = atlas match {
+ case Some(atls) => atls.getSprite(location)
+ case None => Textures.getSprite(location)
+ }
+
+ protected def splitterTexture(atlas: Option[AtlasTexture]) = Array(
+ getSprite(Textures.Block.NetSplitterTop, atlas),
+ getSprite(Textures.Block.NetSplitterTop, atlas),
+ getSprite(Textures.Block.NetSplitterSide, atlas),
+ getSprite(Textures.Block.NetSplitterSide, atlas),
+ getSprite(Textures.Block.NetSplitterSide, atlas),
+ getSprite(Textures.Block.NetSplitterSide, atlas)
)
- protected def GenerateBaseModel() = {
+ protected def GenerateBaseModel(atlas: AtlasTexture) = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
// Bottom.
- faces ++= bakeQuads(makeBox(new Vec3d(0 / 16f, 0 / 16f, 5 / 16f), new Vec3d(5 / 16f, 5 / 16f, 11 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(11 / 16f, 0 / 16f, 5 / 16f), new Vec3d(16 / 16f, 5 / 16f, 11 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 0 / 16f, 0 / 16f), new Vec3d(11 / 16f, 5 / 16f, 5 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 0 / 16f, 11 / 16f), new Vec3d(11 / 16f, 5 / 16f, 16 / 16f)), splitterTexture, None)
+ faces ++= bakeQuads(makeBox(new Vector3d(0 / 16f, 0 / 16f, 5 / 16f), new Vector3d(5 / 16f, 5 / 16f, 11 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(11 / 16f, 0 / 16f, 5 / 16f), new Vector3d(16 / 16f, 5 / 16f, 11 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 0 / 16f, 0 / 16f), new Vector3d(11 / 16f, 5 / 16f, 5 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 0 / 16f, 11 / 16f), new Vector3d(11 / 16f, 5 / 16f, 16 / 16f)), splitterTexture(Some(atlas)), None)
// Corners.
- faces ++= bakeQuads(makeBox(new Vec3d(0 / 16f, 0 / 16f, 0 / 16f), new Vec3d(5 / 16f, 16 / 16f, 5 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(11 / 16f, 0 / 16f, 0 / 16f), new Vec3d(16 / 16f, 16 / 16f, 5 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(0 / 16f, 0 / 16f, 11 / 16f), new Vec3d(5 / 16f, 16 / 16f, 16 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(11 / 16f, 0 / 16f, 11 / 16f), new Vec3d(16 / 16f, 16 / 16f, 16 / 16f)), splitterTexture, None)
+ faces ++= bakeQuads(makeBox(new Vector3d(0 / 16f, 0 / 16f, 0 / 16f), new Vector3d(5 / 16f, 16 / 16f, 5 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(11 / 16f, 0 / 16f, 0 / 16f), new Vector3d(16 / 16f, 16 / 16f, 5 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(0 / 16f, 0 / 16f, 11 / 16f), new Vector3d(5 / 16f, 16 / 16f, 16 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(11 / 16f, 0 / 16f, 11 / 16f), new Vector3d(16 / 16f, 16 / 16f, 16 / 16f)), splitterTexture(Some(atlas)), None)
// Top.
- faces ++= bakeQuads(makeBox(new Vec3d(0 / 16f, 11 / 16f, 5 / 16f), new Vec3d(5 / 16f, 16 / 16f, 11 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(11 / 16f, 11 / 16f, 5 / 16f), new Vec3d(16 / 16f, 16 / 16f, 11 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 11 / 16f, 0 / 16f), new Vec3d(11 / 16f, 16 / 16f, 5 / 16f)), splitterTexture, None)
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 11 / 16f, 11 / 16f), new Vec3d(11 / 16f, 16 / 16f, 16 / 16f)), splitterTexture, None)
+ faces ++= bakeQuads(makeBox(new Vector3d(0 / 16f, 11 / 16f, 5 / 16f), new Vector3d(5 / 16f, 16 / 16f, 11 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(11 / 16f, 11 / 16f, 5 / 16f), new Vector3d(16 / 16f, 16 / 16f, 11 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 11 / 16f, 0 / 16f), new Vector3d(11 / 16f, 16 / 16f, 5 / 16f)), splitterTexture(Some(atlas)), None)
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 11 / 16f, 11 / 16f), new Vector3d(11 / 16f, 16 / 16f, 16 / 16f)), splitterTexture(Some(atlas)), None)
faces.toArray
}
@@ -77,46 +83,42 @@ object NetSplitterModel extends SmartBlockModelBase {
@SubscribeEvent
def onTextureStitch(e: TextureStitchEvent.Post): Unit = {
- BaseModel = GenerateBaseModel()
+ if (e.getMap.location.equals(PlayerContainer.BLOCK_ATLAS)) BaseModel = GenerateBaseModel(e.getMap)
}
protected def addSideQuads(faces: mutable.ArrayBuffer[BakedQuad], openSides: Array[Boolean]): Unit = {
- val down = openSides(EnumFacing.DOWN.ordinal())
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, if (down) 0 / 16f else 2 / 16f, 5 / 16f), new Vec3d(11 / 16f, 5 / 16f, 11 / 16f)), splitterTexture, None)
+ val down = openSides(Direction.DOWN.ordinal())
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, if (down) 0 / 16f else 2 / 16f, 5 / 16f), new Vector3d(11 / 16f, 5 / 16f, 11 / 16f)), splitterTexture(None), None)
- val up = openSides(EnumFacing.UP.ordinal())
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 11 / 16f, 5 / 16f), new Vec3d(11 / 16f, if (up) 16 / 16f else 14f / 16f, 11 / 16f)), splitterTexture, None)
+ val up = openSides(Direction.UP.ordinal())
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 11 / 16f, 5 / 16f), new Vector3d(11 / 16f, if (up) 16 / 16f else 14f / 16f, 11 / 16f)), splitterTexture(None), None)
- val north = openSides(EnumFacing.NORTH.ordinal())
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 5 / 16f, if (north) 0 / 16f else 2 / 16f), new Vec3d(11 / 16f, 11 / 16f, 5 / 16f)), splitterTexture, None)
+ val north = openSides(Direction.NORTH.ordinal())
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 5 / 16f, if (north) 0 / 16f else 2 / 16f), new Vector3d(11 / 16f, 11 / 16f, 5 / 16f)), splitterTexture(None), None)
- val south = openSides(EnumFacing.SOUTH.ordinal())
- faces ++= bakeQuads(makeBox(new Vec3d(5 / 16f, 5 / 16f, 11 / 16f), new Vec3d(11 / 16f, 11 / 16f, if (south) 16 / 16f else 14 / 16f)), splitterTexture, None)
+ val south = openSides(Direction.SOUTH.ordinal())
+ faces ++= bakeQuads(makeBox(new Vector3d(5 / 16f, 5 / 16f, 11 / 16f), new Vector3d(11 / 16f, 11 / 16f, if (south) 16 / 16f else 14 / 16f)), splitterTexture(None), None)
- val west = openSides(EnumFacing.WEST.ordinal())
- faces ++= bakeQuads(makeBox(new Vec3d(if (west) 0 / 16f else 2 / 16f, 5 / 16f, 5 / 16f), new Vec3d(5 / 16f, 11 / 16f, 11 / 16f)), splitterTexture, None)
+ val west = openSides(Direction.WEST.ordinal())
+ faces ++= bakeQuads(makeBox(new Vector3d(if (west) 0 / 16f else 2 / 16f, 5 / 16f, 5 / 16f), new Vector3d(5 / 16f, 11 / 16f, 11 / 16f)), splitterTexture(None), None)
- val east = openSides(EnumFacing.EAST.ordinal())
- faces ++= bakeQuads(makeBox(new Vec3d(11 / 16f, 5 / 16f, 5 / 16f), new Vec3d(if (east) 16 / 16f else 14 / 16f, 11 / 16f, 11 / 16f)), splitterTexture, None)
+ val east = openSides(Direction.EAST.ordinal())
+ faces ++= bakeQuads(makeBox(new Vector3d(11 / 16f, 5 / 16f, 5 / 16f), new Vector3d(if (east) 16 / 16f else 14 / 16f, 11 / 16f, 11 / 16f)), splitterTexture(None), None)
}
- class ItemModel(val stack: ItemStack) extends SmartBlockModelBase {
- val data = new PrintData(stack)
-
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
+ object ItemModel extends SmartBlockModelBase {
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
- Textures.Block.bind()
-
faces ++= BaseModel
- addSideQuads(faces, EnumFacing.values().map(_ => false))
+ addSideQuads(faces, Direction.values().map(_ => false))
bufferAsJavaList(faces)
}
}
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = new ItemModel(stack)
+ object ItemOverride extends ItemOverrideList {
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = ItemModel
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/PrintModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/PrintModel.scala
index 7c8159ad1b..0978978c0e 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/PrintModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/PrintModel.scala
@@ -13,52 +13,54 @@ import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedAABB
import li.cil.oc.util.ExtendedAABB._
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.item.EnumDyeColor
+import net.minecraft.block.BlockState
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.client.renderer.texture.MissingTextureSprite
+import net.minecraft.client.renderer.texture.TextureAtlasSprite
+import net.minecraft.entity.LivingEntity
+import net.minecraft.item.DyeColor
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.world.World
-import net.minecraftforge.common.property.IExtendedBlockState
+import net.minecraft.util.Direction
+import net.minecraft.util.ResourceLocation
+import net.minecraftforge.client.model.data.IModelData
-import scala.collection.convert.WrapAsJava.bufferAsJavaList
+import scala.collection.JavaConverters.bufferAsJavaList
import scala.collection.mutable
object PrintModel extends SmartBlockModelBase {
override def getOverrides: ItemOverrideList = ItemOverride
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] =
- state match {
- case extended: IExtendedBlockState =>
- extended.getValue(block.property.PropertyTile.Tile) match {
- case t: tileentity.Print =>
- val faces = mutable.ArrayBuffer.empty[BakedQuad]
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random, data: IModelData): util.List[BakedQuad] =
+ data match {
+ case t: tileentity.Print =>
+ val faces = mutable.ArrayBuffer.empty[BakedQuad]
- for (shape <- t.shapes if !Strings.isNullOrEmpty(shape.texture)) {
- val bounds = shape.bounds.rotateTowards(t.facing)
- val texture = resolveTexture(shape.texture)
- faces ++= bakeQuads(makeBox(bounds.min, bounds.max), Array.fill(6)(texture), shape.tint.getOrElse(White))
- }
-
- bufferAsJavaList(faces)
- case _ => super.getQuads(state, side, rand)
+ for (shape <- t.shapes if !Strings.isNullOrEmpty(shape.texture)) {
+ val bounds = shape.bounds.rotateTowards(t.facing)
+ val texture = resolveTexture(shape.texture)
+ faces ++= bakeQuads(makeBox(bounds.minVec, bounds.maxVec), Array.fill(6)(texture), shape.tint.getOrElse(White))
}
+
+ bufferAsJavaList(faces)
case _ => super.getQuads(state, side, rand)
}
- private def resolveTexture(name: String) = {
- val texture = Textures.getSprite(name)
- if (texture.getIconName == "missingno") Textures.getSprite("minecraft:blocks/" + name)
+ private def resolveTexture(name: String): TextureAtlasSprite = try {
+ val texture = Textures.getSprite(new ResourceLocation(name))
+ if (texture.getName == MissingTextureSprite.getLocation) Textures.getSprite(new ResourceLocation("minecraft:blocks/" + name))
else texture
}
+ catch {
+ case _: Throwable => Textures.getSprite(MissingTextureSprite.getLocation)
+ }
class ItemModel(val stack: ItemStack) extends SmartBlockModelBase {
val data = new PrintData(stack)
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
val shapes =
@@ -69,20 +71,20 @@ object PrintModel extends SmartBlockModelBase {
for (shape <- shapes) {
val bounds = shape.bounds
val texture = resolveTexture(shape.texture)
- faces ++= bakeQuads(makeBox(bounds.min, bounds.max), Array.fill(6)(texture), shape.tint.getOrElse(White))
+ faces ++= bakeQuads(makeBox(bounds.minVec, bounds.maxVec), Array.fill(6)(texture), shape.tint.getOrElse(White))
}
if (shapes.isEmpty) {
val bounds = ExtendedAABB.unitBounds
val texture = resolveTexture(Settings.resourceDomain + ":blocks/white")
- faces ++= bakeQuads(makeBox(bounds.min, bounds.max), Array.fill(6)(texture), Color.rgbValues(EnumDyeColor.LIME))
+ faces ++= bakeQuads(makeBox(bounds.minVec, bounds.maxVec), Array.fill(6)(texture), Color.rgbValues(DyeColor.LIME))
}
bufferAsJavaList(faces)
}
}
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = new ItemModel(stack)
+ object ItemOverride extends ItemOverrideList {
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = new ItemModel(stack)
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/RobotModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/RobotModel.scala
index 4ec49b7587..cfaa2a82d7 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/RobotModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/RobotModel.scala
@@ -4,17 +4,16 @@ import java.util
import java.util.Collections
import li.cil.oc.client.Textures
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.EntityLivingBase
+import net.minecraft.block.BlockState
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.world.World
+import net.minecraft.util.Direction
-import scala.collection.convert.WrapAsJava.bufferAsJavaList
+import scala.collection.JavaConverters.bufferAsJavaList
import scala.collection.mutable
object RobotModel extends SmartBlockModelBase {
@@ -56,30 +55,30 @@ object RobotModel extends SmartBlockModelBase {
(x - 0.5f) * 1.4f + 0.5f,
(y - 0.5f) * 1.4f + 0.5f,
(z - 0.5f) * 1.4f + 0.5f,
- EnumFacing.UP, robotTexture, robotTexture.getInterpolatedU(u * 16), robotTexture.getInterpolatedV(v * 16),
+ Direction.UP, robotTexture, robotTexture.getU(u * 16), robotTexture.getV(v * 16),
White)
}.toArray
}
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
- faces += new BakedQuad(quad(top, top1, top2), tint, EnumFacing.NORTH, robotTexture, true, DefaultVertexFormats.ITEM)
- faces += new BakedQuad(quad(top, top2, top3), tint, EnumFacing.EAST, robotTexture, true, DefaultVertexFormats.ITEM)
- faces += new BakedQuad(quad(top, top3, top4), tint, EnumFacing.SOUTH, robotTexture, true, DefaultVertexFormats.ITEM)
- faces += new BakedQuad(quad(top, top4, top1), tint, EnumFacing.WEST, robotTexture, true, DefaultVertexFormats.ITEM)
+ faces += new BakedQuad(quad(top, top1, top2), tint, Direction.NORTH, robotTexture, true)
+ faces += new BakedQuad(quad(top, top2, top3), tint, Direction.EAST, robotTexture, true)
+ faces += new BakedQuad(quad(top, top3, top4), tint, Direction.SOUTH, robotTexture, true)
+ faces += new BakedQuad(quad(top, top4, top1), tint, Direction.WEST, robotTexture, true)
- faces += new BakedQuad(quad(bottom, bottom1, bottom2), tint, EnumFacing.NORTH, robotTexture, true, DefaultVertexFormats.ITEM)
- faces += new BakedQuad(quad(bottom, bottom2, bottom3), tint, EnumFacing.EAST, robotTexture, true, DefaultVertexFormats.ITEM)
- faces += new BakedQuad(quad(bottom, bottom3, bottom4), tint, EnumFacing.SOUTH, robotTexture, true, DefaultVertexFormats.ITEM)
- faces += new BakedQuad(quad(bottom, bottom4, bottom1), tint, EnumFacing.WEST, robotTexture, true, DefaultVertexFormats.ITEM)
+ faces += new BakedQuad(quad(bottom, bottom1, bottom2), tint, Direction.NORTH, robotTexture, true)
+ faces += new BakedQuad(quad(bottom, bottom2, bottom3), tint, Direction.EAST, robotTexture, true)
+ faces += new BakedQuad(quad(bottom, bottom3, bottom4), tint, Direction.SOUTH, robotTexture, true)
+ faces += new BakedQuad(quad(bottom, bottom4, bottom1), tint, Direction.WEST, robotTexture, true)
bufferAsJavaList(faces)
}
}
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = ItemModel
+ object ItemOverride extends ItemOverrideList {
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = ItemModel
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/ScreenModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/ScreenModel.scala
index 5069923f19..2526256b4e 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/ScreenModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/ScreenModel.scala
@@ -10,71 +10,68 @@ import li.cil.oc.common.Tier
import li.cil.oc.common.block
import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.entity.EntityLivingBase
+import net.minecraft.block.BlockState
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.world.World
-import net.minecraftforge.common.property.IExtendedBlockState
+import net.minecraft.util.Direction
+import net.minecraftforge.client.model.data.IModelData
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.seqAsJavaList
+import scala.collection.convert.ImplicitConversionsToJava._
object ScreenModel extends SmartBlockModelBase {
override def getOverrides: ItemOverrideList = ItemOverride
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
- val safeSide = if (side != null) side else EnumFacing.SOUTH
- state match {
- case extended: IExtendedBlockState =>
- extended.getValue(block.property.PropertyTile.Tile) match {
- case screen: tileentity.Screen =>
- val facing = screen.toLocal(safeSide)
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random, data: IModelData): util.List[BakedQuad] = {
+ val safeSide = if (side != null) side else Direction.SOUTH
+ data match {
+ case screen: tileentity.Screen =>
+ val facing = screen.toLocal(safeSide)
- val (x, y) = screen.localPosition
- var px = xy2part(x, screen.width - 1)
- var py = xy2part(y, screen.height - 1)
- if ((safeSide == EnumFacing.DOWN || screen.facing == EnumFacing.DOWN) && safeSide != screen.facing) {
- px = 2 - px
- py = 2 - py
- }
- val rotation =
- if (safeSide == EnumFacing.UP) screen.yaw.getHorizontalIndex
- else if (safeSide == EnumFacing.DOWN) -screen.yaw.getHorizontalIndex
- else 0
+ val (x, y) = screen.localPosition
+ var px = xy2part(x, screen.width - 1)
+ var py = xy2part(y, screen.height - 1)
+ if ((safeSide == Direction.DOWN || screen.facing == Direction.DOWN) && safeSide != screen.facing) {
+ px = 2 - px
+ py = 2 - py
+ }
+ val rotation =
+ if (safeSide == Direction.UP) screen.yaw.get2DDataValue
+ else if (safeSide == Direction.DOWN) -screen.yaw.get2DDataValue
+ else 0
- def pitch = if (screen.pitch == EnumFacing.NORTH) 0 else 1
- val texture =
- if (screen.width == 1 && screen.height == 1) {
- if (facing == EnumFacing.SOUTH)
- Textures.Block.Screen.SingleFront(pitch)
- else
- Textures.Block.Screen.Single(safeSide.getIndex)
- }
- else if (screen.width == 1) {
- if (facing == EnumFacing.SOUTH)
- Textures.Block.Screen.VerticalFront(pitch)(py)
- else
- Textures.Block.Screen.Vertical(pitch)(py)(facing.getIndex)
- }
- else if (screen.height == 1) {
- if (facing == EnumFacing.SOUTH)
- Textures.Block.Screen.HorizontalFront(pitch)(px)
- else
- Textures.Block.Screen.Horizontal(pitch)(px)(facing.getIndex)
- }
- else {
- if (facing == EnumFacing.SOUTH)
- Textures.Block.Screen.MultiFront(pitch)(py)(px)
- else
- Textures.Block.Screen.Multi(pitch)(py)(px)(facing.getIndex)
- }
+ def pitch = if (screen.pitch == Direction.NORTH) 0 else 1
+ val texture =
+ if (screen.width == 1 && screen.height == 1) {
+ if (facing == Direction.SOUTH)
+ Textures.Block.Screen.SingleFront(pitch)
+ else
+ Textures.Block.Screen.Single(safeSide.get3DDataValue)
+ }
+ else if (screen.width == 1) {
+ if (facing == Direction.SOUTH)
+ Textures.Block.Screen.VerticalFront(pitch)(py)
+ else
+ Textures.Block.Screen.Vertical(pitch)(py)(facing.get3DDataValue)
+ }
+ else if (screen.height == 1) {
+ if (facing == Direction.SOUTH)
+ Textures.Block.Screen.HorizontalFront(pitch)(px)
+ else
+ Textures.Block.Screen.Horizontal(pitch)(px)(facing.get3DDataValue)
+ }
+ else {
+ if (facing == Direction.SOUTH)
+ Textures.Block.Screen.MultiFront(pitch)(py)(px)
+ else
+ Textures.Block.Screen.Multi(pitch)(py)(px)(facing.get3DDataValue)
+ }
- seqAsJavaList(Seq(bakeQuad(safeSide, Textures.getSprite(texture), Some(screen.getColor), rotation)))
- case _ => super.getQuads(state, safeSide, rand)
- }
+ seqAsJavaList(Seq(bakeQuad(safeSide, Textures.getSprite(texture), Some(screen.getColor), rotation)))
case _ => super.getQuads(state, safeSide, rand)
}
}
@@ -88,18 +85,18 @@ object ScreenModel extends SmartBlockModelBase {
case _ => Color.byTier(Tier.One)
}
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = {
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = {
val result =
- if (side == EnumFacing.NORTH || side == null)
+ if (side == Direction.NORTH || side == null)
Textures.Block.Screen.SingleFront(0)
else
Textures.Block.Screen.Single(side.ordinal())
- seqAsJavaList(Seq(bakeQuad(if (side != null) side else EnumFacing.SOUTH, Textures.getSprite(result), Some(Color.rgbValues(color)), 0)))
+ seqAsJavaList(Seq(bakeQuad(if (side != null) side else Direction.SOUTH, Textures.getSprite(result), Some(Color.rgbValues(color)), 0)))
}
}
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = new ItemModel(stack)
+ object ItemOverride extends ItemOverrideList {
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = new ItemModel(stack)
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/ServerRackModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/ServerRackModel.scala
index 9b9e12740b..0632457781 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/ServerRackModel.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/ServerRackModel.scala
@@ -8,56 +8,52 @@ import li.cil.oc.api.event.RackMountableRenderEvent
import li.cil.oc.client.Textures
import li.cil.oc.common.block
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.block.model.BakedQuad
-import net.minecraft.client.renderer.block.model.IBakedModel
-import net.minecraft.client.renderer.block.model.ItemOverrideList
-import net.minecraft.entity.EntityLivingBase
+import net.minecraft.block.BlockState
+import net.minecraft.client.world.ClientWorld
+import net.minecraft.client.renderer.model.BakedQuad
+import net.minecraft.client.renderer.model.IBakedModel
+import net.minecraft.client.renderer.model.ItemOverrideList
+import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.World
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3d
import net.minecraftforge.common.MinecraftForge
-import net.minecraftforge.common.property.IExtendedBlockState
+import net.minecraftforge.client.model.data.IModelData
-import scala.collection.convert.WrapAsJava.bufferAsJavaList
+import scala.collection.JavaConverters.bufferAsJavaList
import scala.collection.mutable
class ServerRackModel(val parent: IBakedModel) extends SmartBlockModelBase {
override def getOverrides: ItemOverrideList = ItemOverride
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] =
- state match {
- case extended: IExtendedBlockState =>
- extended.getValue(block.property.PropertyTile.Tile) match {
- case rack: tileentity.Rack =>
- val facing = rack.facing
- val faces = mutable.ArrayBuffer.empty[BakedQuad]
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random, data: IModelData): util.List[BakedQuad] =
+ data match {
+ case rack: tileentity.Rack =>
+ val facing = rack.facing
+ val faces = mutable.ArrayBuffer.empty[BakedQuad]
- for (side <- EnumFacing.values if side != facing) {
- faces ++= bakeQuads(Case(side.getIndex), serverRackTexture, None)
- }
+ for (side <- Direction.values if side != facing) {
+ faces ++= bakeQuads(Case(side.get3DDataValue), serverRackTexture, None)
+ }
- val textures = serverTexture
- val defaultFront = Textures.getSprite(Textures.Block.RackFront)
- for (slot <- 0 until 4) rack.getMountable(slot) match {
- case mountable: RackMountable =>
- val event = new RackMountableRenderEvent.Block(rack, slot, rack.lastData(slot), side)
- MinecraftForge.EVENT_BUS.post(event)
- if (!event.isCanceled) {
- if (event.getFrontTextureOverride != null) {
- (2 until 6).foreach(textures(_) = event.getFrontTextureOverride)
- } else {
- (2 until 6).foreach(textures(_) = defaultFront)
- }
- faces ++= bakeQuads(Servers(slot), textures, None)
- }
- case _ =>
+ val textures = serverTexture
+ val defaultFront = Textures.getSprite(Textures.Block.RackFront)
+ for (slot <- 0 until 4) rack.getMountable(slot) match {
+ case mountable: RackMountable =>
+ val event = new RackMountableRenderEvent.Block(rack, slot, rack.lastData(slot), side)
+ MinecraftForge.EVENT_BUS.post(event)
+ if (!event.isCanceled) {
+ if (event.getFrontTextureOverride != null) {
+ (2 until 6).foreach(textures(_) = event.getFrontTextureOverride)
+ } else {
+ (2 until 6).foreach(textures(_) = defaultFront)
+ }
+ faces ++= bakeQuads(Servers(slot), textures, None)
}
-
- bufferAsJavaList(faces)
- case _ => super.getQuads(state, side, rand)
+ case _ =>
}
+
+ bufferAsJavaList(faces)
case _ => super.getQuads(state, side, rand)
}
@@ -80,23 +76,23 @@ class ServerRackModel(val parent: IBakedModel) extends SmartBlockModelBase {
)
protected final val Case = Array(
- makeBox(new Vec3d(0 / 16f, 0 / 16f, 0 / 16f), new Vec3d(16 / 16f, 2 / 16f, 16 / 16f)),
- makeBox(new Vec3d(0 / 16f, 14 / 16f, 0 / 16f), new Vec3d(16 / 16f, 16 / 16f, 16 / 16f)),
- makeBox(new Vec3d(0 / 16f, 2 / 16f, 0 / 16f), new Vec3d(16 / 16f, 14 / 16f, 0.99f / 16f)),
- makeBox(new Vec3d(0 / 16f, 2 / 16f, 15.01f / 16f), new Vec3d(16 / 16f, 14 / 16f, 16 / 16f)),
- makeBox(new Vec3d(0 / 16f, 2 / 16f, 0 / 16f), new Vec3d(0.99f / 16f, 14 / 16f, 16 / 16f)),
- makeBox(new Vec3d(15.01f / 16f, 2 / 16f, 0 / 16f), new Vec3d(16 / 16f, 14f / 16f, 16 / 16f))
+ makeBox(new Vector3d(0 / 16f, 0 / 16f, 0 / 16f), new Vector3d(16 / 16f, 2 / 16f, 16 / 16f)),
+ makeBox(new Vector3d(0 / 16f, 14 / 16f, 0 / 16f), new Vector3d(16 / 16f, 16 / 16f, 16 / 16f)),
+ makeBox(new Vector3d(0 / 16f, 2 / 16f, 0 / 16f), new Vector3d(16 / 16f, 14 / 16f, 0.99f / 16f)),
+ makeBox(new Vector3d(0 / 16f, 2 / 16f, 15.01f / 16f), new Vector3d(16 / 16f, 14 / 16f, 16 / 16f)),
+ makeBox(new Vector3d(0 / 16f, 2 / 16f, 0 / 16f), new Vector3d(0.99f / 16f, 14 / 16f, 16 / 16f)),
+ makeBox(new Vector3d(15.01f / 16f, 2 / 16f, 0 / 16f), new Vector3d(16 / 16f, 14f / 16f, 16 / 16f))
)
protected final val Servers = Array(
- makeBox(new Vec3d(0.5f / 16f, 11 / 16f, 0.5f / 16f), new Vec3d(15.5f / 16f, 14 / 16f, 15.5f / 16f)),
- makeBox(new Vec3d(0.5f / 16f, 8 / 16f, 0.5f / 16f), new Vec3d(15.5f / 16f, 11 / 16f, 15.5f / 16f)),
- makeBox(new Vec3d(0.5f / 16f, 5 / 16f, 0.5f / 16f), new Vec3d(15.5f / 16f, 8 / 16f, 15.5f / 16f)),
- makeBox(new Vec3d(0.5f / 16f, 2 / 16f, 0.5f / 16f), new Vec3d(15.5f / 16f, 5 / 16f, 15.5f / 16f))
+ makeBox(new Vector3d(0.5f / 16f, 11 / 16f, 0.5f / 16f), new Vector3d(15.5f / 16f, 14 / 16f, 15.5f / 16f)),
+ makeBox(new Vector3d(0.5f / 16f, 8 / 16f, 0.5f / 16f), new Vector3d(15.5f / 16f, 11 / 16f, 15.5f / 16f)),
+ makeBox(new Vector3d(0.5f / 16f, 5 / 16f, 0.5f / 16f), new Vector3d(15.5f / 16f, 8 / 16f, 15.5f / 16f)),
+ makeBox(new Vector3d(0.5f / 16f, 2 / 16f, 0.5f / 16f), new Vector3d(15.5f / 16f, 5 / 16f, 15.5f / 16f))
)
- object ItemOverride extends ItemOverrideList(Collections.emptyList()) {
- override def handleItemState(originalModel: IBakedModel, stack: ItemStack, world: World, entity: EntityLivingBase): IBakedModel = parent
+ object ItemOverride extends ItemOverrideList {
+ override def resolve(originalModel: IBakedModel, stack: ItemStack, world: ClientWorld, entity: LivingEntity): IBakedModel = parent
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/block/SmartBlockModelBase.scala b/src/main/scala/li/cil/oc/client/renderer/block/SmartBlockModelBase.scala
index 88479d1899..6d65bfdd55 100644
--- a/src/main/scala/li/cil/oc/client/renderer/block/SmartBlockModelBase.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/block/SmartBlockModelBase.scala
@@ -4,32 +4,37 @@ import java.util
import java.util.Collections
import li.cil.oc.client.Textures
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.block.model._
+import net.minecraft.client.renderer.model._
import net.minecraft.client.renderer.texture.TextureAtlasSprite
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.Vec3d
-import org.lwjgl.util.vector.Vector3f
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.util.math.vector.Vector3f
trait SmartBlockModelBase extends IBakedModel {
- override def getOverrides: ItemOverrideList = ItemOverrideList.NONE
+ override def getOverrides: ItemOverrideList = ItemOverrideList.EMPTY
- override def getQuads(state: IBlockState, side: EnumFacing, rand: Long): util.List[BakedQuad] = Collections.emptyList()
+ @Deprecated
+ override def getQuads(state: BlockState, side: Direction, rand: util.Random): util.List[BakedQuad] = Collections.emptyList()
- override def isAmbientOcclusion = true
+ override def useAmbientOcclusion = true
override def isGui3d = true
- override def isBuiltInRenderer = false
+ override def usesBlockLight = true
+
+ override def isCustomRenderer = false
// Note: we don't care about the actual texture here, we just need the block
// texture atlas. So any of our textures we know is loaded into it will do.
- override def getParticleTexture = Textures.getSprite(Textures.Block.GenericTop)
+ @Deprecated
+ override def getParticleIcon = Textures.getSprite(Textures.Block.GenericTop)
- override def getItemCameraTransforms = DefaultBlockCameraTransforms
+ @Deprecated
+ override def getTransforms = DefaultBlockCameraTransforms
+ @Deprecated
protected final val DefaultBlockCameraTransforms = {
val gui = new ItemTransformVec3f(new Vector3f(30, 225, 0), new Vector3f(0, 0, 0), new Vector3f(0.625f, 0.625f, 0.625f))
val ground = new ItemTransformVec3f(new Vector3f(0, 0, 0), new Vector3f(0, 3, 0), new Vector3f(0.25f, 0.25f, 0.25f))
@@ -39,46 +44,46 @@ trait SmartBlockModelBase extends IBakedModel {
val firstperson_lefthand = new ItemTransformVec3f(new Vector3f(0, 225, 0), new Vector3f(0, 0, 0), new Vector3f(0.40f, 0.40f, 0.40f))
// scale(0.0625f): see ItemTransformVec3f.Deserializer.deserialize.
- gui.translation.scale(0.0625f)
- ground.translation.scale(0.0625f)
- fixed.translation.scale(0.0625f)
- thirdperson_righthand.translation.scale(0.0625f)
- firstperson_righthand.translation.scale(0.0625f)
- firstperson_lefthand.translation.scale(0.0625f)
+ gui.translation.mul(0.0625f)
+ ground.translation.mul(0.0625f)
+ fixed.translation.mul(0.0625f)
+ thirdperson_righthand.translation.mul(0.0625f)
+ firstperson_righthand.translation.mul(0.0625f)
+ firstperson_lefthand.translation.mul(0.0625f)
new ItemCameraTransforms(
- ItemTransformVec3f.DEFAULT,
+ ItemTransformVec3f.NO_TRANSFORM,
thirdperson_righthand,
firstperson_lefthand,
firstperson_righthand,
- ItemTransformVec3f.DEFAULT,
+ ItemTransformVec3f.NO_TRANSFORM,
gui,
ground,
fixed)
}
- protected def missingModel = Minecraft.getMinecraft.getRenderItem.getItemModelMesher.getModelManager.getMissingModel
+ protected def missingModel = Minecraft.getInstance.getModelManager.getMissingModel
// Standard faces for a unit cube.
protected final val UnitCube = Array(
- Array(new Vec3d(0, 0, 1), new Vec3d(0, 0, 0), new Vec3d(1, 0, 0), new Vec3d(1, 0, 1)),
- Array(new Vec3d(0, 1, 0), new Vec3d(0, 1, 1), new Vec3d(1, 1, 1), new Vec3d(1, 1, 0)),
- Array(new Vec3d(1, 1, 0), new Vec3d(1, 0, 0), new Vec3d(0, 0, 0), new Vec3d(0, 1, 0)),
- Array(new Vec3d(0, 1, 1), new Vec3d(0, 0, 1), new Vec3d(1, 0, 1), new Vec3d(1, 1, 1)),
- Array(new Vec3d(0, 1, 0), new Vec3d(0, 0, 0), new Vec3d(0, 0, 1), new Vec3d(0, 1, 1)),
- Array(new Vec3d(1, 1, 1), new Vec3d(1, 0, 1), new Vec3d(1, 0, 0), new Vec3d(1, 1, 0))
+ Array(new Vector3d(0, 0, 1), new Vector3d(0, 0, 0), new Vector3d(1, 0, 0), new Vector3d(1, 0, 1)),
+ Array(new Vector3d(0, 1, 0), new Vector3d(0, 1, 1), new Vector3d(1, 1, 1), new Vector3d(1, 1, 0)),
+ Array(new Vector3d(1, 1, 0), new Vector3d(1, 0, 0), new Vector3d(0, 0, 0), new Vector3d(0, 1, 0)),
+ Array(new Vector3d(0, 1, 1), new Vector3d(0, 0, 1), new Vector3d(1, 0, 1), new Vector3d(1, 1, 1)),
+ Array(new Vector3d(0, 1, 0), new Vector3d(0, 0, 0), new Vector3d(0, 0, 1), new Vector3d(0, 1, 1)),
+ Array(new Vector3d(1, 1, 1), new Vector3d(1, 0, 1), new Vector3d(1, 0, 0), new Vector3d(1, 1, 0))
)
// Planes perpendicular to facings. Negative values mean we mirror along that,
// axis which is done to mirror back faces and the y axis (because up is
// positive but for our texture coordinates down is positive).
protected final val Planes = Array(
- (new Vec3d(1, 0, 0), new Vec3d(0, 0, -1)),
- (new Vec3d(1, 0, 0), new Vec3d(0, 0, 1)),
- (new Vec3d(-1, 0, 0), new Vec3d(0, -1, 0)),
- (new Vec3d(1, 0, 0), new Vec3d(0, -1, 0)),
- (new Vec3d(0, 0, 1), new Vec3d(0, -1, 0)),
- (new Vec3d(0, 0, -1), new Vec3d(0, -1, 0))
+ (new Vector3d(1, 0, 0), new Vector3d(0, 0, -1)),
+ (new Vector3d(1, 0, 0), new Vector3d(0, 0, 1)),
+ (new Vector3d(-1, 0, 0), new Vector3d(0, -1, 0)),
+ (new Vector3d(1, 0, 0), new Vector3d(0, -1, 0)),
+ (new Vector3d(0, 0, 1), new Vector3d(0, -1, 0)),
+ (new Vector3d(0, 0, -1), new Vector3d(0, -1, 0))
)
protected final val White = 0xFFFFFF
@@ -87,34 +92,34 @@ trait SmartBlockModelBase extends IBakedModel {
* Generates a list of arrays, each containing the four vertices making up a
* face of the box with the specified size.
*/
- protected def makeBox(from: Vec3d, to: Vec3d) = {
+ protected def makeBox(from: Vector3d, to: Vector3d) = {
val minX = math.min(from.x, to.x)
val minY = math.min(from.y, to.y)
val minZ = math.min(from.z, to.z)
val maxX = math.max(from.x, to.x)
val maxY = math.max(from.y, to.y)
val maxZ = math.max(from.z, to.z)
- UnitCube.map(face => face.map(vertex => new Vec3d(
+ UnitCube.map(face => face.map(vertex => new Vector3d(
math.max(minX, math.min(maxX, vertex.x)),
math.max(minY, math.min(maxY, vertex.y)),
math.max(minZ, math.min(maxZ, vertex.z)))))
}
- protected def rotateVector(v: Vec3d, angle: Double, axis: Vec3d) = {
+ protected def rotateVector(v: Vector3d, angle: Double, axis: Vector3d) = {
// vrot = v * cos(angle) + (axis x v) * sin(angle) + axis * (axis dot v)(1 - cos(angle))
- def scale(v: Vec3d, s: Double) = new Vec3d(v.x * s, v.y * s, v.z * s)
+ def scale(v: Vector3d, s: Double) = v.scale(s)
val cosAngle = math.cos(angle)
val sinAngle = math.sin(angle)
scale(v, cosAngle).
- add(scale(axis.crossProduct(v), sinAngle)).
- add(scale(axis, axis.dotProduct(v) * (1 - cosAngle)))
+ add(scale(axis.cross(v), sinAngle)).
+ add(scale(axis, axis.dot(v) * (1 - cosAngle)))
}
- protected def rotateFace(face: Array[Vec3d], angle: Double, axis: Vec3d, around: Vec3d = new Vec3d(0.5, 0.5, 0.5)) = {
+ protected def rotateFace(face: Array[Vector3d], angle: Double, axis: Vector3d, around: Vector3d = new Vector3d(0.5, 0.5, 0.5)) = {
face.map(v => rotateVector(v.subtract(around), angle, axis).add(around))
}
- protected def rotateBox(box: Array[Array[Vec3d]], angle: Double, axis: Vec3d = new Vec3d(0, 1, 0), around: Vec3d = new Vec3d(0.5, 0.5, 0.5)) = {
+ protected def rotateBox(box: Array[Array[Vector3d]], angle: Double, axis: Vector3d = new Vector3d(0, 1, 0), around: Vector3d = new Vector3d(0.5, 0.5, 0.5)) = {
box.map(face => rotateFace(face, angle, axis, around))
}
@@ -123,7 +128,7 @@ trait SmartBlockModelBase extends IBakedModel {
*
* Usually used to generate the quads for a cube previously generated using makeBox().
*/
- protected def bakeQuads(box: Array[Array[Vec3d]], texture: Array[TextureAtlasSprite], color: Option[Int]): Array[BakedQuad] = {
+ protected def bakeQuads(box: Array[Array[Vector3d]], texture: Array[TextureAtlasSprite], color: Option[Int]): Array[BakedQuad] = {
val colorRGB = color.getOrElse(White)
bakeQuads(box, texture, colorRGB)
}
@@ -133,33 +138,33 @@ trait SmartBlockModelBase extends IBakedModel {
*
* Usually used to generate the quads for a cube previously generated using makeBox().
*/
- protected def bakeQuads(box: Array[Array[Vec3d]], texture: Array[TextureAtlasSprite], colorRGB: Int): Array[BakedQuad] = {
- EnumFacing.values.map(side => {
- val vertices = box(side.getIndex)
- val data = quadData(vertices, side, texture(side.getIndex), colorRGB, 0)
- new BakedQuad(data, -1, side, texture(side.getIndex), true, DefaultVertexFormats.ITEM)
+ protected def bakeQuads(box: Array[Array[Vector3d]], texture: Array[TextureAtlasSprite], colorRGB: Int): Array[BakedQuad] = {
+ Direction.values.map(side => {
+ val vertices = box(side.get3DDataValue)
+ val data = quadData(vertices, side, texture(side.get3DDataValue), colorRGB, 0)
+ new BakedQuad(data, -1, side, texture(side.get3DDataValue), true)
})
}
/**
* Create a single BakedQuad of a unit cube's specified side.
*/
- protected def bakeQuad(side: EnumFacing, texture: TextureAtlasSprite, color: Option[Int], rotation: Int) = {
+ protected def bakeQuad(side: Direction, texture: TextureAtlasSprite, color: Option[Int], rotation: Int) = {
val colorRGB = color.getOrElse(White)
- val vertices = UnitCube(side.getIndex)
+ val vertices = UnitCube(side.get3DDataValue)
val data = quadData(vertices, side, texture, colorRGB, rotation)
- new BakedQuad(data, -1, side, texture, true, DefaultVertexFormats.ITEM)
+ new BakedQuad(data, -1, side, texture, true)
}
// Generate raw data used for a BakedQuad based on the specified facing, vertices, texture and rotation.
// The UV coordinates are generated from the positions of the vertices, i.e. they are simply cube-
// mapped. This is good enough for us.
- protected def quadData(vertices: Array[Vec3d], facing: EnumFacing, texture: TextureAtlasSprite, colorRGB: Int, rotation: Int): Array[Int] = {
- val (uAxis, vAxis) = Planes(facing.getIndex)
+ protected def quadData(vertices: Array[Vector3d], facing: Direction, texture: TextureAtlasSprite, colorRGB: Int, rotation: Int): Array[Int] = {
+ val (uAxis, vAxis) = Planes(facing.get3DDataValue)
val rot = (rotation + 4) % 4
vertices.flatMap(vertex => {
- var u = vertex.dotProduct(uAxis)
- var v = vertex.dotProduct(vAxis)
+ var u = vertex.dot(uAxis)
+ var v = vertex.dot(vAxis)
if (uAxis.x + uAxis.y + uAxis.z < 0) u = 1 + u
if (vAxis.x + vAxis.y + vAxis.z < 0) v = 1 + v
for (i <- 0 until rot) {
@@ -168,15 +173,15 @@ trait SmartBlockModelBase extends IBakedModel {
u = v
v = (-(tmp - 0.5)) + 0.5
}
- rawData(vertex.x, vertex.y, vertex.z, facing, texture, texture.getInterpolatedU(u * 16), texture.getInterpolatedV(v * 16), colorRGB)
+ rawData(vertex.x, vertex.y, vertex.z, facing, texture, texture.getU(u * 16), texture.getV(v * 16), colorRGB)
})
}
// See FaceBakery#storeVertexData.
- protected def rawData(x: Double, y: Double, z: Double, face: EnumFacing, texture: TextureAtlasSprite, u: Float, v: Float, colorRGB: Int) = {
- val vx = (face.getFrontOffsetX * 127) & 0xFF
- val vy = (face.getFrontOffsetY * 127) & 0xFF
- val vz = (face.getFrontOffsetZ * 127) & 0xFF
+ protected def rawData(x: Double, y: Double, z: Double, face: Direction, texture: TextureAtlasSprite, u: Float, v: Float, colorRGB: Int) = {
+ val vx = (face.getStepX * 127) & 0xFF
+ val vy = (face.getStepY * 127) & 0xFF
+ val vz = (face.getStepZ * 127) & 0xFF
Array(
java.lang.Float.floatToRawIntBits(x.toFloat),
@@ -185,12 +190,12 @@ trait SmartBlockModelBase extends IBakedModel {
getFaceShadeColor(face, colorRGB),
java.lang.Float.floatToRawIntBits(u),
java.lang.Float.floatToRawIntBits(v),
- vx | (vy << 0x08) | (vz << 0x10)
+ 0, vx | (vy << 0x08) | (vz << 0x10)
)
}
// See FaceBakery.
- protected def getFaceShadeColor(face: EnumFacing, colorRGB: Int): Int = {
+ protected def getFaceShadeColor(face: Direction, colorRGB: Int): Int = {
val brightness = getFaceBrightness(face)
val b = (colorRGB >> 16) & 0xFF
val g = (colorRGB >> 8) & 0xFF
@@ -200,12 +205,12 @@ trait SmartBlockModelBase extends IBakedModel {
private def shade(value: Int, brightness: Float) = (brightness * value).toInt max 0 min 255
- protected def getFaceBrightness(face: EnumFacing): Float = {
+ protected def getFaceBrightness(face: Direction): Float = {
face match {
- case EnumFacing.DOWN => 0.5f
- case EnumFacing.UP => 1.0f
- case EnumFacing.NORTH | EnumFacing.SOUTH => 0.8f
- case EnumFacing.WEST | EnumFacing.EAST => 0.6f
+ case Direction.DOWN => 0.5f
+ case Direction.UP => 1.0f
+ case Direction.NORTH | Direction.SOUTH => 0.8f
+ case Direction.WEST | Direction.EAST => 0.6f
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/entity/DroneRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/entity/DroneRenderer.scala
index 3f4d1ab441..a6a7132373 100644
--- a/src/main/scala/li/cil/oc/client/renderer/entity/DroneRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/entity/DroneRenderer.scala
@@ -1,27 +1,50 @@
package li.cil.oc.client.renderer.entity
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import li.cil.oc.common.entity.Drone
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.entity.Render
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.RenderType
+import net.minecraft.client.renderer.entity.EntityRenderer
+import net.minecraft.client.renderer.entity.EntityRendererManager
+import net.minecraft.client.renderer.texture.OverlayTexture
+import net.minecraft.util.math.MathHelper
+import net.minecraftforge.fml.client.registry.IRenderFactory
-object DroneRenderer extends Render[Drone](Minecraft.getMinecraft.getRenderManager) {
+object DroneRenderer extends IRenderFactory[Drone] {
val model = new ModelQuadcopter()
- override def doRender(entity: Drone, x: Double, y: Double, z: Double, yaw: Float, dt: Float) {
- bindEntityTexture(entity)
- GlStateManager.pushMatrix()
- RenderState.pushAttrib()
+ override def createRenderFor(manager: EntityRendererManager) = new DroneRenderer(manager)
+}
- GlStateManager.translate(x, y + 2 / 16f, z)
+class DroneRenderer(manager: EntityRendererManager) extends EntityRenderer[Drone](manager) {
+ override def render(entity: Drone, yaw: Float, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int): Unit = {
+ val renderType = getRenderType(entity)
+ if (renderType != null) {
+ stack.pushPose()
+ stack.translate(0, 2f / 16f, 0)
+ val builder = buffer.getBuffer(renderType)
+ DroneRenderer.model.prepareMobModel(entity, 0, 0, dt)
+ val xRot = MathHelper.rotLerp(dt, entity.xRotO, entity.xRot)
+ val yRot = MathHelper.rotLerp(dt, entity.yRotO, entity.yRot)
+ DroneRenderer.model.setupAnim(entity, 0, 0, entity.tickCount, yRot, xRot)
+ DroneRenderer.model.renderToBuffer(stack, builder, light, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1)
+ stack.popPose()
+ }
+ super.render(entity, yaw, dt, stack, buffer, light)
+ }
- model.render(entity, 0, 0, 0, 0, 0, dt)
+ override def getTextureLocation(entity: Drone) = Textures.Model.Drone
- RenderState.popAttrib()
- GlStateManager.popMatrix()
+ def getRenderType(entity: Drone): RenderType = {
+ val mc = Minecraft.getInstance
+ val texture = getTextureLocation(entity)
+ if (!entity.isInvisible) DroneRenderer.model.renderType(texture)
+ else if (!entity.isInvisibleTo(mc.player)) RenderType.itemEntityTranslucentCull(texture)
+ else if (mc.shouldEntityAppearGlowing(entity)) RenderType.outline(texture)
+ else null
}
-
- override def getEntityTexture(entity: Drone) = Textures.Model.Drone
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala b/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala
index 6b8e51d110..434d645e32 100644
--- a/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala
@@ -1,179 +1,115 @@
package li.cil.oc.client.renderer.entity
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.common.entity.Drone
-import li.cil.oc.util.RenderState
-import net.minecraft.client.model.ModelBase
-import net.minecraft.client.model.ModelRenderer
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.Entity
-import net.minecraft.util.math.Vec3d
-import org.lwjgl.opengl.GL11
-
-final class ModelQuadcopter extends ModelBase {
- val body = new ModelRenderer(this, "body")
- val wing0 = new ModelRenderer(this, "wing0")
- val wing1 = new ModelRenderer(this, "wing1")
- val wing2 = new ModelRenderer(this, "wing2")
- val wing3 = new ModelRenderer(this, "wing3")
- val light0 = new ModelRenderer(this, "light0")
- val light1 = new ModelRenderer(this, "light1")
- val light2 = new ModelRenderer(this, "light2")
- val light3 = new ModelRenderer(this, "light3")
-
- textureWidth = 64
- textureHeight = 32
-
- setTextureOffset("body.middle", 0, 23)
- setTextureOffset("body.top", 0, 1)
- setTextureOffset("body.bottom", 0, 17)
- setTextureOffset("wing0.flap0", 0, 9)
- setTextureOffset("wing0.pin0", 0, 27)
- setTextureOffset("wing1.flap1", 0, 9)
- setTextureOffset("wing1.pin1", 0, 27)
- setTextureOffset("wing2.flap2", 0, 9)
- setTextureOffset("wing2.pin2", 0, 27)
- setTextureOffset("wing3.flap3", 0, 9)
- setTextureOffset("wing3.pin3", 0, 27)
-
- setTextureOffset("light0.flap0", 24, 0)
- setTextureOffset("light1.flap1", 24, 0)
- setTextureOffset("light2.flap2", 24, 0)
- setTextureOffset("light3.flap3", 24, 0)
-
- body.addBox("top", -3, 1, -3, 6, 1, 6).rotateAngleY = math.toRadians(45).toFloat
- body.addBox("middle", -1, 0, -1, 2, 1, 2).rotateAngleY = math.toRadians(45).toFloat
- body.addBox("bottom", -2, -1, -2, 4, 1, 4).rotateAngleY = math.toRadians(45).toFloat
- wing0.addBox("flap0", 1, 0, -7, 6, 1, 6)
- wing0.addBox("pin0", 2, -1, -3, 1, 3, 1)
- wing1.addBox("flap1", 1, 0, 1, 6, 1, 6)
- wing1.addBox("pin1", 2, -1, 2, 1, 3, 1)
- wing2.addBox("flap2", -7, 0, 1, 6, 1, 6)
- wing2.addBox("pin2", -3, -1, 2, 1, 3, 1)
- wing3.addBox("flap3", -7, 0, -7, 6, 1, 6)
- wing3.addBox("pin3", -3, -1, -3, 1, 3, 1)
-
- light0.addBox("flap0", 1, 0, -7, 6, 1, 6)
- light1.addBox("flap1", 1, 0, 1, 6, 1, 6)
- light2.addBox("flap2", -7, 0, 1, 6, 1, 6)
- light3.addBox("flap3", -7, 0, -7, 6, 1, 6)
-
- private val scale = 1 / 16f
- private val up = new Vec3d(0, 1, 0)
-
- private def doRender(drone: Drone, dt: Float) {
+import net.minecraft.client.renderer.LightTexture
+import net.minecraft.client.renderer.entity.model.EntityModel
+import net.minecraft.client.renderer.model.ModelRenderer
+import net.minecraft.client.renderer.texture.OverlayTexture
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.util.math.vector.Vector3f
+
+final class ModelQuadcopter extends EntityModel[Drone] {
+ val body = new ModelRenderer(this)
+ val wing0 = new ModelRenderer(this)
+ val wing1 = new ModelRenderer(this)
+ val wing2 = new ModelRenderer(this)
+ val wing3 = new ModelRenderer(this)
+ val light0 = new ModelRenderer(this)
+ val light1 = new ModelRenderer(this)
+ val light2 = new ModelRenderer(this)
+ val light3 = new ModelRenderer(this)
+
+ texWidth = 64
+ texHeight = 32
+
+ body.texOffs(0, 23).addBox(-3, 1, -3, 6, 1, 6).yRot = math.toRadians(45).toFloat // top
+ body.texOffs(0, 1).addBox(-1, 0, -1, 2, 1, 2).yRot = math.toRadians(45).toFloat // middle
+ body.texOffs(0, 17).addBox(-2, -1, -2, 4, 1, 4).yRot = math.toRadians(45).toFloat // bottom
+ wing0.texOffs(0, 9).addBox(1, 0, -7, 6, 1, 6) // flap0
+ wing0.texOffs(0, 27).addBox(2, -1, -3, 1, 3, 1) // pin0
+ wing1.texOffs(0, 9).addBox(1, 0, 1, 6, 1, 6) // flap1
+ wing1.texOffs(0, 27).addBox(2, -1, 2, 1, 3, 1) // pin1
+ wing2.texOffs(0, 9).addBox(-7, 0, 1, 6, 1, 6) // flap2
+ wing2.texOffs(0, 27).addBox(-3, -1, 2, 1, 3, 1) // pin2
+ wing3.texOffs(0, 9).addBox(-7, 0, -7, 6, 1, 6) // flap3
+ wing3.texOffs(0, 27).addBox(-3, -1, -3, 1, 3, 1) // pin3
+
+ light0.texOffs(24, 0).addBox(1, 0, -7, 6, 1, 6) // flap0
+ light1.texOffs(24, 0).addBox(1, 0, 1, 6, 1, 6) // flap1
+ light2.texOffs(24, 0).addBox(-7, 0, 1, 6, 1, 6) // flap2
+ light3.texOffs(24, 0).addBox(-7, 0, -7, 6, 1, 6) // flap3
+
+ private val up = new Vector3d(0, 1, 0)
+
+ private def doRender(drone: Drone, dt: Float, stack: MatrixStack, builder: IVertexBuilder, light: Int, overlay: Int, r: Float, g: Float, b: Float, a: Float) {
+ stack.pushPose()
if (drone.isRunning) {
val timeJitter = drone.hashCode() ^ 0xFF
- GlStateManager.translate(0, (math.sin(timeJitter + (drone.getEntityWorld.getTotalWorldTime + dt) / 20.0) * (1 / 16f)).toFloat, 0)
+ stack.translate(0, (math.sin(timeJitter + (drone.level.getGameTime + dt) / 20.0) * (1 / 16f)).toFloat, 0)
}
- val velocity = new Vec3d(drone.motionX, drone.motionY, drone.motionZ)
- val direction = velocity.normalize()
- if (direction.dotProduct(up) < 0.99) {
+ val direction = drone.getDeltaMovement.normalize()
+ if (direction.dot(up) < 0.99) {
// Flying sideways.
- val rotationAxis = direction.crossProduct(up)
- val relativeSpeed = velocity.lengthVector().toFloat / drone.maxVelocity
- GlStateManager.rotate(relativeSpeed * -20, rotationAxis.x.toFloat, rotationAxis.y.toFloat, rotationAxis.z.toFloat)
+ val rotationAxis = direction.cross(up)
+ val relativeSpeed = drone.getDeltaMovement.length().toFloat / drone.maxVelocity
+ stack.mulPose(new Vector3f(rotationAxis).rotationDegrees(relativeSpeed * -20))
}
- GlStateManager.rotate(drone.bodyAngle, 0, 1, 0)
+ stack.mulPose(Vector3f.YP.rotationDegrees(drone.bodyAngle))
+ body.render(stack, builder, light, overlay, r, g, b, a)
- body.render(scale)
+ wing0.xRot = drone.flapAngles(0)(0)
+ wing0.zRot = drone.flapAngles(0)(1)
+ wing1.xRot = drone.flapAngles(1)(0)
+ wing1.zRot = drone.flapAngles(1)(1)
+ wing2.xRot = drone.flapAngles(2)(0)
+ wing2.zRot = drone.flapAngles(2)(1)
+ wing3.xRot = drone.flapAngles(3)(0)
+ wing3.zRot = drone.flapAngles(3)(1)
- wing0.rotateAngleX = drone.flapAngles(0)(0)
- wing0.rotateAngleZ = drone.flapAngles(0)(1)
- wing1.rotateAngleX = drone.flapAngles(1)(0)
- wing1.rotateAngleZ = drone.flapAngles(1)(1)
- wing2.rotateAngleX = drone.flapAngles(2)(0)
- wing2.rotateAngleZ = drone.flapAngles(2)(1)
- wing3.rotateAngleX = drone.flapAngles(3)(0)
- wing3.rotateAngleZ = drone.flapAngles(3)(1)
-
- wing0.render(scale)
- wing1.render(scale)
- wing2.render(scale)
- wing3.render(scale)
+ wing0.render(stack, builder, light, overlay, r, g, b, a)
+ wing1.render(stack, builder, light, overlay, r, g, b, a)
+ wing2.render(stack, builder, light, overlay, r, g, b, a)
+ wing3.render(stack, builder, light, overlay, r, g, b, a)
if (drone.isRunning) {
- RenderState.disableEntityLighting()
- GlStateManager.depthFunc(GL11.GL_LEQUAL)
-
- light0.rotateAngleX = drone.flapAngles(0)(0)
- light0.rotateAngleZ = drone.flapAngles(0)(1)
- light1.rotateAngleX = drone.flapAngles(1)(0)
- light1.rotateAngleZ = drone.flapAngles(1)(1)
- light2.rotateAngleX = drone.flapAngles(2)(0)
- light2.rotateAngleZ = drone.flapAngles(2)(1)
- light3.rotateAngleX = drone.flapAngles(3)(0)
- light3.rotateAngleZ = drone.flapAngles(3)(1)
-
- // Additive blending for the lights.
- RenderState.makeItBlend()
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
+ light0.xRot = drone.flapAngles(0)(0)
+ light0.zRot = drone.flapAngles(0)(1)
+ light1.xRot = drone.flapAngles(1)(0)
+ light1.zRot = drone.flapAngles(1)(1)
+ light2.xRot = drone.flapAngles(2)(0)
+ light2.zRot = drone.flapAngles(2)(1)
+ light3.xRot = drone.flapAngles(3)(0)
+ light3.zRot = drone.flapAngles(3)(1)
val lightColor = drone.lightColor
- val r = (lightColor >>> 16) & 0xFF
- val g = (lightColor >>> 8) & 0xFF
- val b = (lightColor >>> 0) & 0xFF
- GlStateManager.color(r / 255f, g / 255f, b / 255f)
-
- light0.render(scale)
- light1.render(scale)
- light2.render(scale)
- light3.render(scale)
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
- GlStateManager.color(1, 1, 1, 1)
+ val rr = r * ((lightColor >>> 16) & 0xFF) / 255f
+ val gg = g * ((lightColor >>> 8) & 0xFF) / 255f
+ val bb = b * ((lightColor >>> 0) & 0xFF) / 255f
+ val fullLight = LightTexture.pack(15, 15)
+
+ light0.render(stack, builder, fullLight, OverlayTexture.NO_OVERLAY, rr, gg, bb, a)
+ light1.render(stack, builder, fullLight, OverlayTexture.NO_OVERLAY, rr, gg, bb, a)
+ light2.render(stack, builder, fullLight, OverlayTexture.NO_OVERLAY, rr, gg, bb, a)
+ light3.render(stack, builder, fullLight, OverlayTexture.NO_OVERLAY, rr, gg, bb, a)
}
+ stack.popPose()
}
- // For inventory rendering.
- def render() {
- body.render(scale)
-
- val tilt = math.toRadians(2).toFloat
- wing0.rotateAngleX = tilt
- wing0.rotateAngleZ = tilt
- wing1.rotateAngleX = -tilt
- wing1.rotateAngleZ = tilt
- wing2.rotateAngleX = -tilt
- wing2.rotateAngleZ = -tilt
- wing3.rotateAngleX = tilt
- wing3.rotateAngleZ = -tilt
-
- wing0.render(scale)
- wing1.render(scale)
- wing2.render(scale)
- wing3.render(scale)
-
- RenderState.disableEntityLighting()
- GlStateManager.depthFunc(GL11.GL_LEQUAL)
-
- light0.rotateAngleX = tilt
- light0.rotateAngleZ = tilt
- light1.rotateAngleX = -tilt
- light1.rotateAngleZ = tilt
- light2.rotateAngleX = -tilt
- light2.rotateAngleZ = -tilt
- light3.rotateAngleX = tilt
- light3.rotateAngleZ = -tilt
-
-
- RenderState.makeItBlend()
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
- GlStateManager.color(0x66 / 255f, 0xDD / 255f, 0x55 / 255f)
-
- light0.render(scale)
- light1.render(scale)
- light2.render(scale)
- light3.render(scale)
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
- GlStateManager.color(1, 1, 1, 1)
+ private var cachedEntity: Drone = null
+ private var cachedDt = 0.0f
+
+ override def setupAnim(drone: Drone, f1: Float, f2: Float, f3: Float, f4: Float, f5: Float): Unit = {}
+
+ override def prepareMobModel(drone: Drone, f1: Float, f2: Float, dt: Float): Unit = {
+ cachedEntity = drone
+ cachedDt = dt
}
- override def render(entity: Entity, f1: Float, f2: Float, f3: Float, f4: Float, f5: Float, f6: Float): Unit = {
- doRender(entity.asInstanceOf[Drone], f6)
+ override def renderToBuffer(stack: MatrixStack, builder: IVertexBuilder, light: Int, overlay: Int, r: Float, g: Float, b: Float, a: Float): Unit = {
+ doRender(cachedEntity, cachedDt, stack, builder, light: Int, overlay: Int, r: Float, g: Float, b: Float, a: Float)
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/font/DynamicFontRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/font/DynamicFontRenderer.scala
index 1e178b7052..109286eb7b 100644
--- a/src/main/scala/li/cil/oc/client/renderer/font/DynamicFontRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/font/DynamicFontRenderer.scala
@@ -1,14 +1,20 @@
package li.cil.oc.client.renderer.font
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.Settings
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.client.renderer.font.DynamicFontRenderer.CharTexture
import li.cil.oc.util.FontUtils
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.resources.IReloadableResourceManager
-import net.minecraft.client.resources.IResourceManager
-import net.minecraft.client.resources.IResourceManagerReloadListener
+import net.minecraft.client.renderer.RenderType
+import net.minecraft.client.renderer.texture.TextureUtil
+import net.minecraft.resources.IReloadableResourceManager
+import net.minecraft.resources.IResourceManager
+import net.minecraft.resources.IResourceManagerReloadListener
+import net.minecraft.util.math.vector.Matrix4f
+import net.minecraft.util.math.vector.Vector4f
import org.lwjgl.BufferUtils
import org.lwjgl.opengl._
@@ -31,7 +37,7 @@ class DynamicFontRenderer extends TextureFontRenderer with IResourceManagerReloa
initialize()
- Minecraft.getMinecraft.getResourceManager match {
+ Minecraft.getInstance.getResourceManager match {
case reloadable: IReloadableResourceManager => reloadable.registerReloadListener(this)
case _ =>
}
@@ -42,13 +48,13 @@ class DynamicFontRenderer extends TextureFontRenderer with IResourceManagerReloa
}
textures.clear()
charMap.clear()
+ glyphProvider.initialize()
textures += new DynamicFontRenderer.CharTexture(this)
activeTexture = textures.head
generateChars(basicChars.toCharArray)
}
def onResourceManagerReload(manager: IResourceManager) {
- glyphProvider.initialize()
initialize()
}
@@ -64,13 +70,25 @@ class DynamicFontRenderer extends TextureFontRenderer with IResourceManagerReloa
RenderState.checkError(getClass.getName + ".bindTexture")
}
+ override protected def selectType(index: Int): RenderType = {
+ activeTexture = textures(index)
+ activeTexture.getType
+ }
+
override protected def generateChar(char: Char) {
charMap.getOrElseUpdate(char, createCharIcon(char))
}
- override protected def drawChar(tx: Float, ty: Float, char: Char) {
+ override protected def drawChar(matrix: Matrix4f, tx: Float, ty: Float, char: Char) {
+ charMap.get(char) match {
+ case Some(icon) if icon.texture == activeTexture => icon.draw(matrix, tx, ty)
+ case _ =>
+ }
+ }
+
+ override protected def drawChar(builder: IVertexBuilder, matrix: Matrix4f, color: Int, tx: Float, ty: Float, char: Char) {
charMap.get(char) match {
- case Some(icon) if icon.texture == activeTexture => icon.draw(tx, ty)
+ case Some(icon) if icon.texture == activeTexture => icon.draw(builder, matrix, color, tx, ty)
case _ =>
}
}
@@ -94,17 +112,19 @@ object DynamicFontRenderer {
private val size = 256
class CharTexture(val owner: DynamicFontRenderer) {
- private val id = GlStateManager.generateTexture()
+ private val id = TextureUtil.generateTextureId()
RenderState.bindTexture(id)
if (Settings.get.textLinearFiltering) {
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR)
} else {
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST)
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST)
}
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST)
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, size, size, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, BufferUtils.createByteBuffer(size * size * 4))
RenderState.bindTexture(0)
+ private val rt = RenderTypes.createFontTex(id)
+
RenderState.checkError(getClass.getName + ".: create texture")
// Some padding to avoid bleeding.
@@ -112,21 +132,23 @@ object DynamicFontRenderer {
private val cellHeight = owner.charHeight + 2
private val cols = size / cellWidth
private val rows = size / cellHeight
- private val uStep = cellWidth / size.toDouble
- private val vStep = cellHeight / size.toDouble
- private val pad = 1.0 / size
+ private val uStep = cellWidth / size.toFloat
+ private val vStep = cellHeight / size.toFloat
+ private val pad = 1f / size
private val capacity = cols * rows
private var chars = 0
def delete() {
- GlStateManager.deleteTexture(id)
+ RenderSystem.deleteTexture(id)
}
def bind() {
RenderState.bindTexture(id)
}
+ def getType() = rt
+
def isFull(char: Char) = chars + FontUtils.wcwidth(char) > capacity
def add(char: Char) = {
@@ -149,16 +171,34 @@ object DynamicFontRenderer {
}
}
- class CharIcon(val texture: CharTexture, val w: Int, val h: Int, val u1: Double, val v1: Double, val u2: Double, val v2: Double) {
- def draw(tx: Float, ty: Float) {
- GL11.glTexCoord2d(u1, v2)
- GL11.glVertex2f(tx, ty + h)
- GL11.glTexCoord2d(u2, v2)
- GL11.glVertex2f(tx + w, ty + h)
- GL11.glTexCoord2d(u2, v1)
- GL11.glVertex2f(tx + w, ty)
- GL11.glTexCoord2d(u1, v1)
- GL11.glVertex2f(tx, ty)
+ class CharIcon(val texture: CharTexture, val w: Int, val h: Int, val u1: Float, val v1: Float, val u2: Float, val v2: Float) {
+ def draw(matrix: Matrix4f, tx: Float, ty: Float) {
+ GL11.glTexCoord2f(u1, v2)
+ val vec = new Vector4f(tx, ty + h, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ GL11.glTexCoord2f(u2, v2)
+ vec.set(tx + w, ty + h, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ GL11.glTexCoord2f(u2, v1)
+ vec.set(tx + w, ty, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ GL11.glTexCoord2f(u1, v1)
+ vec.set(tx, ty, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ }
+
+ def draw(builder: IVertexBuilder, matrix: Matrix4f, color: Int, tx: Float, ty: Float) {
+ val r = ((color >> 16) & 0xFF) / 255f
+ val g = ((color >> 8) & 0xFF) / 255f
+ val b = (color & 0xFF) / 255f
+ builder.vertex(matrix, tx, ty + h, 0).color(r, g, b, 1f).uv(u1, v2).endVertex()
+ builder.vertex(matrix, tx + w, ty + h, 0).color(r, g, b, 1f).uv(u2, v2).endVertex()
+ builder.vertex(matrix, tx + w, ty, 0).color(r, g, b, 1f).uv(u2, v1).endVertex()
+ builder.vertex(matrix, tx, ty, 0).color(r, g, b, 1f).uv(u1, v1).endVertex()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/font/FontParserHex.java b/src/main/scala/li/cil/oc/client/renderer/font/FontParserHex.java
index 78eee08440..3a24a6fb69 100644
--- a/src/main/scala/li/cil/oc/client/renderer/font/FontParserHex.java
+++ b/src/main/scala/li/cil/oc/client/renderer/font/FontParserHex.java
@@ -25,7 +25,7 @@ public void initialize() {
glyphs[i] = null;
}
try {
- final InputStream font = Minecraft.getMinecraft().getResourceManager().getResource(new ResourceLocation(Settings.resourceDomain(), "font.hex")).getInputStream();
+ final InputStream font = Minecraft.getInstance().getResourceManager().getResource(new ResourceLocation(Settings.resourceDomain(), "font.hex")).getInputStream();
try {
OpenComputers.log().info("Initializing unicode glyph provider.");
final BufferedReader input = new BufferedReader(new InputStreamReader(font));
diff --git a/src/main/scala/li/cil/oc/client/renderer/font/StaticFontRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/font/StaticFontRenderer.scala
index ff3a55f63d..ca0c53c3d6 100644
--- a/src/main/scala/li/cil/oc/client/renderer/font/StaticFontRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/font/StaticFontRenderer.scala
@@ -1,11 +1,16 @@
package li.cil.oc.client.renderer.font
import com.google.common.base.Charsets
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.RenderType
import net.minecraft.util.ResourceLocation
+import net.minecraft.util.math.vector.Matrix4f
+import net.minecraft.util.math.vector.Vector4f
import org.lwjgl.opengl.GL11
import scala.io.Source
@@ -16,7 +21,7 @@ import scala.io.Source
*/
class StaticFontRenderer extends TextureFontRenderer {
protected val (chars, charWidth, charHeight) = try {
- val lines = Source.fromInputStream(Minecraft.getMinecraft.getResourceManager.getResource(new ResourceLocation(Settings.resourceDomain, "textures/font/chars.txt")).getInputStream)(Charsets.UTF_8).getLines()
+ val lines = Source.fromInputStream(Minecraft.getInstance.getResourceManager.getResource(new ResourceLocation(Settings.resourceDomain, "textures/font/chars.txt")).getInputStream)(Charsets.UTF_8).getLines()
val chars = lines.next()
val (w, h) = if (lines.hasNext) {
val size = lines.next().split(" ", 2)
@@ -31,11 +36,11 @@ class StaticFontRenderer extends TextureFontRenderer {
}
private val cols = 256 / charWidth
- private val uStep = charWidth / 256.0
+ private val uStep = charWidth / 256f
private val uSize = uStep
- private val vStep = (charHeight + 1) / 256.0
- private val vSize = charHeight / 256.0
- private val s = Settings.get.fontCharScale
+ private val vStep = (charHeight + 1) / 256f
+ private val vSize = charHeight / 256f
+ private val s = Settings.get.fontCharScale.toFloat
private val dw = charWidth * s - charWidth
private val dh = charHeight * s - charHeight
@@ -48,9 +53,24 @@ class StaticFontRenderer extends TextureFontRenderer {
else {
Textures.bind(Textures.Font.Aliased)
}
+ if (Settings.get.textLinearFiltering) {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR)
+ }
+ else {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST)
+ }
+ }
+
+ override protected def selectType(index: Int): RenderType = {
+ if (Settings.get.textAntiAlias) {
+ RenderTypes.createFontTex("smoothed", Textures.Font.AntiAliased, Settings.get.textLinearFiltering)
+ }
+ else {
+ RenderTypes.createFontTex("aliased", Textures.Font.Aliased, Settings.get.textLinearFiltering)
+ }
}
- override protected def drawChar(tx: Float, ty: Float, char: Char) {
+ override protected def drawChar(matrix: Matrix4f, tx: Float, ty: Float, char: Char) {
val index = 1 + (chars.indexOf(char) match {
case -1 => chars.indexOf('?')
case i => i
@@ -60,13 +80,39 @@ class StaticFontRenderer extends TextureFontRenderer {
val u = x * uStep
val v = y * vStep
GL11.glTexCoord2d(u, v + vSize)
- GL11.glVertex3d(tx - dw, ty + charHeight * s, 0)
+ val vec = new Vector4f(tx - dw, ty + charHeight * s, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glTexCoord2d(u + uSize, v + vSize)
- GL11.glVertex3d(tx + charWidth * s, ty + charHeight * s, 0)
+ vec.set(tx + charWidth * s, ty + charHeight * s, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glTexCoord2d(u + uSize, v)
- GL11.glVertex3d(tx + charWidth * s, ty - dh, 0)
+ vec.set(tx + charWidth * s, ty - dh, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glTexCoord2d(u, v)
- GL11.glVertex3d(tx - dw, ty - dh, 0)
+ vec.set(tx - dw, ty - dh, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ }
+
+ protected def drawChar(builder: IVertexBuilder, matrix: Matrix4f, color: Int, tx: Float, ty: Float, char: Char) {
+ val index = 1 + (chars.indexOf(char) match {
+ case -1 => chars.indexOf('?')
+ case i => i
+ })
+ val x = (index - 1) % cols
+ val y = (index - 1) / cols
+ val u = x * uStep
+ val v = y * vStep
+ val r = ((color >> 16) & 0xFF) / 255f
+ val g = ((color >> 8) & 0xFF) / 255f
+ val b = (color & 0xFF) / 255f
+ builder.vertex(matrix, tx - dw, ty + charHeight * s, 0).color(r, g, b, 1f).uv(u, v + vSize).endVertex()
+ builder.vertex(matrix, tx + charWidth * s, ty + charHeight * s, 0).color(r, g, b, 1f).uv(u + uSize, v + vSize).endVertex()
+ builder.vertex(matrix, tx + charWidth * s, ty - dh, 0).color(r, g, b, 1f).uv(u + uSize, v).endVertex()
+ builder.vertex(matrix, tx - dw, ty - dh, 0).color(r, g, b, 1f).uv(u, v).endVertex()
}
override protected def generateChar(char: Char) {}
diff --git a/src/main/scala/li/cil/oc/client/renderer/font/TextureFontRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/font/TextureFontRenderer.scala
index d164830208..47ec494452 100644
--- a/src/main/scala/li/cil/oc/client/renderer/font/TextureFontRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/font/TextureFontRenderer.scala
@@ -1,10 +1,17 @@
package li.cil.oc.client.renderer.font
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.Settings
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.util.PackedColor
import li.cil.oc.util.RenderState
import li.cil.oc.util.TextBuffer
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.renderer.RenderType
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.util.math.vector.Matrix4f
+import net.minecraft.util.math.vector.Vector4f
import org.lwjgl.opengl.GL11
/**
@@ -26,29 +33,22 @@ abstract class TextureFontRenderer {
* be generated inside the draw call.
*/
def generateChars(chars: Array[Char]) {
- GlStateManager.enableTexture2D()
+ RenderSystem.enableTexture()
for (char <- chars) {
generateChar(char)
}
}
- def drawBuffer(buffer: TextBuffer, viewportWidth: Int, viewportHeight: Int) {
+ def drawBuffer(stack: MatrixStack, renderBuff: IRenderTypeBuffer, buffer: TextBuffer, viewportWidth: Int, viewportHeight: Int) {
val format = buffer.format
- GlStateManager.pushMatrix()
- RenderState.pushAttrib()
-
- GlStateManager.scale(0.5f, 0.5f, 1)
+ stack.pushPose()
- GL11.glDepthMask(false)
- RenderState.makeItBlend()
- GL11.glDisable(GL11.GL_TEXTURE_2D)
-
- RenderState.checkError(getClass.getName + ".drawBuffer: configure state")
+ stack.scale(0.5f, 0.5f, 1)
// Background first. We try to merge adjacent backgrounds of the same
// color to reduce the number of quads we have to draw.
- GL11.glBegin(GL11.GL_QUADS)
+ var quadBuilder: IVertexBuilder = null
for (y <- 0 until (viewportHeight min buffer.height)) {
val color = buffer.color(y)
var cbg = 0x000000
@@ -56,76 +56,48 @@ abstract class TextureFontRenderer {
var width = 0
for (col <- color.map(PackedColor.unpackBackground(_, format)) if x + width < viewportWidth) {
if (col != cbg) {
- drawQuad(cbg, x, y, width)
+ if (quadBuilder == null) quadBuilder = renderBuff.getBuffer(RenderTypes.FONT_QUAD)
+ drawQuad(quadBuilder, stack.last.pose, cbg, x, y, width)
cbg = col
x += width
width = 0
}
width = width + 1
}
- drawQuad(cbg, x, y, width)
- }
- GL11.glEnd()
-
- RenderState.checkError(getClass.getName + ".drawBuffer: background")
-
- GL11.glEnable(GL11.GL_TEXTURE_2D)
-
- if (Settings.get.textLinearFiltering) {
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR)
+ drawQuad(quadBuilder, stack.last.pose, cbg, x, y, width)
}
- // Foreground second. We only have to flush when the color changes, so
- // unless every char has a different color this should be quite efficient.
- for (y <- 0 until (viewportHeight min buffer.height)) {
- val line = buffer.buffer(y)
- val color = buffer.color(y)
- val ty = y * charHeight
- for (i <- 0 until textureCount) {
- bindTexture(i)
- GL11.glBegin(GL11.GL_QUADS)
- var cfg = -1
+ // Foreground second. We only have to flush when the texture changes.
+ for (i <- 0 until textureCount) {
+ // Initialized early because our RenderCache drops empty buffers.
+ val fontBuilder = renderBuff.getBuffer(selectType(i))
+ for (y <- 0 until (viewportHeight min buffer.height)) {
+ val line = buffer.buffer(y)
+ val color = buffer.color(y)
+ val ty = y * charHeight
var tx = 0f
for (n <- 0 until viewportWidth) {
val ch = line(n)
- val col = PackedColor.unpackForeground(color(n), format)
- // Check if color changed.
- if (col != cfg) {
- cfg = col
- GL11.glColor3f(
- ((cfg & 0xFF0000) >> 16) / 255f,
- ((cfg & 0x00FF00) >> 8) / 255f,
- ((cfg & 0x0000FF) >> 0) / 255f)
- }
// Don't render whitespace.
if (ch != ' ') {
- drawChar(tx, ty, ch)
+ val col = PackedColor.unpackForeground(color(n), format)
+ drawChar(fontBuilder, stack.last.pose, col, tx, ty, ch)
}
tx += charWidth
}
- GL11.glEnd()
}
}
- RenderState.checkError(getClass.getName + ".drawBuffer: foreground")
-
- GlStateManager.bindTexture(0)
- GL11.glDepthMask(true)
- GL11.glColor3f(1, 1, 1)
- RenderState.disableBlend()
- RenderState.popAttrib()
- GlStateManager.popMatrix()
-
- RenderState.checkError(getClass.getName + ".drawBuffer: leaving")
+ stack.popPose()
}
- def drawString(s: String, x: Int, y: Int): Unit = {
- GlStateManager.pushMatrix()
+ def drawString(stack: MatrixStack, s: String, x: Int, y: Int): Unit = {
+ stack.pushPose()
RenderState.pushAttrib()
- GlStateManager.translate(x, y, 0)
- GlStateManager.scale(0.5f, 0.5f, 1)
- GlStateManager.depthMask(false)
+ stack.translate(x, y, 0)
+ stack.scale(0.5f, 0.5f, 1)
+ RenderSystem.depthMask(false)
for (i <- 0 until textureCount) {
bindTexture(i)
@@ -135,7 +107,7 @@ abstract class TextureFontRenderer {
val ch = s.charAt(n)
// Don't render whitespace.
if (ch != ' ') {
- drawChar(tx, 0, ch)
+ drawChar(stack.last.pose, tx, 0, ch)
}
tx += charWidth
}
@@ -143,8 +115,8 @@ abstract class TextureFontRenderer {
}
RenderState.popAttrib()
- GlStateManager.popMatrix()
- GlStateManager.color(1, 1, 1)
+ stack.popPose()
+ RenderSystem.color3f(1, 1, 1)
}
protected def charWidth: Int
@@ -155,22 +127,25 @@ abstract class TextureFontRenderer {
protected def bindTexture(index: Int): Unit
+ protected def selectType(index: Int): RenderType
+
protected def generateChar(char: Char): Unit
- protected def drawChar(tx: Float, ty: Float, char: Char): Unit
+ protected def drawChar(matrix: Matrix4f, tx: Float, ty: Float, char: Char): Unit
+
+ protected def drawChar(builder: IVertexBuilder, matrix: Matrix4f, color: Int, tx: Float, ty: Float, char: Char): Unit
- private def drawQuad(color: Int, x: Int, y: Int, width: Int) = if (color != 0 && width > 0) {
+ private def drawQuad(builder: IVertexBuilder, matrix: Matrix4f, color: Int, x: Int, y: Int, width: Int) = if (color != 0 && width > 0) {
val x0 = x * charWidth
val x1 = (x + width) * charWidth
val y0 = y * charHeight
val y1 = (y + 1) * charHeight
- GlStateManager.color(
- ((color >> 16) & 0xFF) / 255f,
- ((color >> 8) & 0xFF) / 255f,
- (color & 0xFF) / 255f)
- GL11.glVertex3d(x0, y1, 0)
- GL11.glVertex3d(x1, y1, 0)
- GL11.glVertex3d(x1, y0, 0)
- GL11.glVertex3d(x0, y0, 0)
+ val r = ((color >> 16) & 0xFF) / 255f
+ val g = ((color >> 8) & 0xFF) / 255f
+ val b = (color & 0xFF) / 255f
+ builder.vertex(matrix, x0, y1, 0).color(r, g, b, 1f).endVertex()
+ builder.vertex(matrix, x1, y1, 0).color(r, g, b, 1f).endVertex()
+ builder.vertex(matrix, x1, y0, 0).color(r, g, b, 1f).endVertex()
+ builder.vertex(matrix, x0, y0, 0).color(r, g, b, 1f).endVertex()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/gui/BufferRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/gui/BufferRenderer.scala
index 54023d9383..12376b6f59 100644
--- a/src/main/scala/li/cil/oc/client/renderer/gui/BufferRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/gui/BufferRenderer.scala
@@ -1,11 +1,14 @@
package li.cil.oc.client.renderer.gui
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.api
import li.cil.oc.client.Textures
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GLAllocation
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.texture.TextureManager
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.Tessellator
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats
+import net.minecraft.util.math.vector.Matrix4f
import org.lwjgl.opengl.GL11
object BufferRenderer {
@@ -13,103 +16,68 @@ object BufferRenderer {
val innerMargin = 1
- private var textureManager: Option[TextureManager] = None
-
- private var displayLists = 0
-
- def init(tm: TextureManager) = this.synchronized(if (textureManager.isEmpty) {
- RenderState.checkError(getClass.getName + ".displayLists: entering (aka: wasntme)")
-
- textureManager = Some(tm)
- displayLists = GLAllocation.generateDisplayLists(2)
-
- RenderState.checkError(getClass.getName + ".displayLists: leaving")
- })
-
- def compileBackground(bufferWidth: Int, bufferHeight: Int, forRobot: Boolean = false) =
- if (textureManager.isDefined) {
- RenderState.checkError(getClass.getName + ".compileBackground: entering (aka: wasntme)")
-
- val innerWidth = innerMargin * 2 + bufferWidth
- val innerHeight = innerMargin * 2 + bufferHeight
-
- GL11.glNewList(displayLists, GL11.GL_COMPILE)
-
- Textures.bind(Textures.GUI.Borders)
-
- GL11.glBegin(GL11.GL_QUADS)
-
- val margin = if (forRobot) 2 else 7
- val (c0, c1, c2, c3) = if (forRobot) (5, 7, 9, 11) else (0, 7, 9, 16)
-
- // Top border (left corner, middle bar, right corner).
- drawBorder(
- 0, 0, margin, margin,
- c0, c0, c1, c1)
- drawBorder(
- margin, 0, innerWidth, margin,
- c1 + 0.25, c0, c2 - 0.25, c1)
- drawBorder(
- margin + innerWidth, 0, margin, margin,
- c2, c0, c3, c1)
-
- // Middle area (left bar, screen background, right bar).
- drawBorder(
- 0, margin, margin, innerHeight,
- c0, c1 + 0.25, c1, c2 - 0.25)
- drawBorder(
- margin, margin, innerWidth, innerHeight,
- c1 + 0.25, c1 + 0.25, c2 - 0.25, c2 - 0.25)
- drawBorder(
- margin + innerWidth, margin, margin, innerHeight,
- c2, c1 + 0.25, c3, c2 - 0.25)
-
- // Bottom border (left corner, middle bar, right corner).
- drawBorder(
- 0, margin + innerHeight, margin, margin,
- c0, c2, c1, c3)
- drawBorder(
- margin, margin + innerHeight, innerWidth, margin,
- c1 + 0.25, c2, c2 - 0.25, c3)
- drawBorder(
- margin + innerWidth, margin + innerHeight, margin, margin,
- c2, c2, c3, c3)
-
- GL11.glEnd()
-
- GL11.glEndList()
-
- RenderState.checkError(getClass.getName + ".compileBackground: leaving")
- }
-
- def drawBackground() =
- if (textureManager.isDefined) {
- GL11.glCallList(displayLists)
- }
-
- def drawText(screen: api.internal.TextBuffer) =
- if (textureManager.isDefined) {
- RenderState.pushAttrib()
- GlStateManager.depthMask(false)
- val changed = screen.renderText()
- GlStateManager.depthMask(true)
- RenderState.popAttrib()
- changed
- }
- else false
+ def drawBackground(stack: MatrixStack, bufferWidth: Int, bufferHeight: Int, forRobot: Boolean = false) = {
+ RenderState.checkError(getClass.getName + ".drawBackground: entering (aka: wasntme)")
+
+ val innerWidth = innerMargin * 2 + bufferWidth
+ val innerHeight = innerMargin * 2 + bufferHeight
+
+ val t = Tessellator.getInstance
+ val r = t.getBuilder
+ Textures.bind(Textures.GUI.Borders)
+ r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
+
+ val margin = if (forRobot) 2 else 7
+ val (c0, c1, c2, c3) = if (forRobot) (5, 7, 9, 11) else (0, 7, 9, 16)
+
+ // Top border (left corner, middle bar, right corner).
+ drawQuad(stack.last.pose, r,
+ 0, 0, margin, margin,
+ c0, c0, c1, c1)
+ drawQuad(stack.last.pose, r,
+ margin, 0, innerWidth, margin,
+ c1 + 0.25f, c0, c2 - 0.25f, c1)
+ drawQuad(stack.last.pose, r,
+ margin + innerWidth, 0, margin, margin,
+ c2, c0, c3, c1)
+
+ // Middle area (left bar, screen background, right bar).
+ drawQuad(stack.last.pose, r,
+ 0, margin, margin, innerHeight,
+ c0, c1 + 0.25f, c1, c2 - 0.25f)
+ drawQuad(stack.last.pose, r,
+ margin, margin, innerWidth, innerHeight,
+ c1 + 0.25f, c1 + 0.25f, c2 - 0.25f, c2 - 0.25f)
+ drawQuad(stack.last.pose, r,
+ margin + innerWidth, margin, margin, innerHeight,
+ c2, c1 + 0.25f, c3, c2 - 0.25f)
+
+ // Bottom border (left corner, middle bar, right corner).
+ drawQuad(stack.last.pose, r,
+ 0, margin + innerHeight, margin, margin,
+ c0, c2, c1, c3)
+ drawQuad(stack.last.pose, r,
+ margin, margin + innerHeight, innerWidth, margin,
+ c1 + 0.25f, c2, c2 - 0.25f, c3)
+ drawQuad(stack.last.pose, r,
+ margin + innerWidth, margin + innerHeight, margin, margin,
+ c2, c2, c3, c3)
+
+ t.end()
+
+ RenderState.checkError(getClass.getName + ".drawBackground: leaving")
+ }
- private def drawBorder(x: Double, y: Double, w: Double, h: Double, u1: Double, v1: Double, u2: Double, v2: Double) = {
- val u1d = u1 / 16.0
- val u2d = u2 / 16.0
- val v1d = v1 / 16.0
- val v2d = v2 / 16.0
- GL11.glTexCoord2d(u1d, v2d)
- GL11.glVertex3d(x, y + h, 0)
- GL11.glTexCoord2d(u2d, v2d)
- GL11.glVertex3d(x + w, y + h, 0)
- GL11.glTexCoord2d(u2d, v1d)
- GL11.glVertex3d(x + w, y, 0)
- GL11.glTexCoord2d(u1d, v1d)
- GL11.glVertex3d(x, y, 0)
+ private def drawQuad(matrix: Matrix4f, builder: IVertexBuilder, x: Float, y: Float, w: Float, h: Float, u1: Float, v1: Float, u2: Float, v2: Float) = {
+ val u1f = u1 / 16f
+ val u2f = u2 / 16f
+ val v1f = v1 / 16f
+ val v2f = v2 / 16f
+ builder.vertex(matrix, x, y + h, 0).uv(u1f, v2f).endVertex()
+ builder.vertex(matrix, x + w, y + h, 0).uv(u2f, v2f).endVertex()
+ builder.vertex(matrix, x+ w, y, 0).uv(u2f, v1f).endVertex()
+ builder.vertex(matrix, x, y, 0).uv(u1f, v1f).endVertex()
}
+
+ def drawText(stack: MatrixStack, screen: api.internal.TextBuffer) = screen.renderText(stack)
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala
index 2f5285d164..7ee1b117f6 100644
--- a/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala
@@ -1,36 +1,36 @@
package li.cil.oc.client.renderer.item
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.Settings
-import li.cil.oc.util.RenderState
-import net.minecraft.client.model.ModelBase
-import net.minecraft.client.model.ModelBiped
-import net.minecraft.client.model.ModelRenderer
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.RenderHelper
-import net.minecraft.entity.Entity
+import net.minecraft.client.renderer.LightTexture
+import net.minecraft.client.renderer.model.Model
+import net.minecraft.client.renderer.model.ModelRenderer
+import net.minecraft.client.renderer.entity.model.BipedModel
+import net.minecraft.client.renderer.texture.OverlayTexture
+import net.minecraft.entity.LivingEntity
import net.minecraft.util.ResourceLocation
-import org.lwjgl.opengl.GL11
-object HoverBootRenderer extends ModelBiped {
+object HoverBootRenderer extends BipedModel[LivingEntity](0.5f) {
val texture = new ResourceLocation(Settings.resourceDomain, "textures/model/drone.png")
- val bootLeft = new ModelRenderer(this, "bootLeft")
- val bootRight = new ModelRenderer(this, "bootRight")
- val body = new ModelRenderer(this, "body")
- val wing0 = new ModelRenderer(this, "wing0")
- val wing1 = new ModelRenderer(this, "wing1")
- val wing2 = new ModelRenderer(this, "wing2")
- val wing3 = new ModelRenderer(this, "wing3")
- val light0 = new LightModelRenderer(this, "light0")
- val light1 = new LightModelRenderer(this, "light1")
- val light2 = new LightModelRenderer(this, "light2")
- val light3 = new LightModelRenderer(this, "light3")
-
- bootLeft.addChild(body)
+ val bootLeft = new ModelRenderer(this)
+ val bootRight = new ModelRenderer(this)
+ val droneBody = new ModelRenderer(this)
+ val wing0 = new ModelRenderer(this)
+ val wing1 = new ModelRenderer(this)
+ val wing2 = new ModelRenderer(this)
+ val wing3 = new ModelRenderer(this)
+ val light0 = new LightModelRenderer(this)
+ val light1 = new LightModelRenderer(this)
+ val light2 = new LightModelRenderer(this)
+ val light3 = new LightModelRenderer(this)
+
+ bootLeft.addChild(droneBody)
bootLeft.addChild(wing0)
bootLeft.addChild(wing1)
- bootRight.addChild(body)
+ bootRight.addChild(droneBody)
bootRight.addChild(wing2)
bootRight.addChild(wing3)
@@ -39,89 +39,59 @@ object HoverBootRenderer extends ModelBiped {
wing2.addChild(light2)
wing3.addChild(light3)
- textureWidth = 64
- textureHeight = 32
-
- setTextureOffset("body.middle", 0, 23)
- setTextureOffset("body.top", 0, 1)
- setTextureOffset("body.bottom", 0, 17)
- setTextureOffset("wing0.flap0", 0, 9)
- setTextureOffset("wing0.pin0", 0, 27)
- setTextureOffset("wing1.flap1", 0, 9)
- setTextureOffset("wing1.pin1", 0, 27)
- setTextureOffset("wing2.flap2", 0, 9)
- setTextureOffset("wing2.pin2", 0, 27)
- setTextureOffset("wing3.flap3", 0, 9)
- setTextureOffset("wing3.pin3", 0, 27)
-
- setTextureOffset("light0.flap0", 24, 0)
- setTextureOffset("light1.flap1", 24, 0)
- setTextureOffset("light2.flap2", 24, 0)
- setTextureOffset("light3.flap3", 24, 0)
-
- bootRight.offsetY = 10.1f / 16
- bootLeft.offsetY = 10.11f / 16f
-
- body.addBox("top", -3, 1, -3, 6, 1, 6).rotateAngleY = math.toRadians(45).toFloat
- body.addBox("middle", -1, 0, -1, 2, 1, 2).rotateAngleY = math.toRadians(45).toFloat
- body.addBox("bottom", -2, -1, -2, 4, 1, 4).rotateAngleY = math.toRadians(45).toFloat
- wing0.addBox("flap0", -1, 0, -7, 6, 1, 6)
- wing0.addBox("pin0", 0, -1, -3, 1, 3, 1)
- wing1.addBox("flap1", -1, 0, 1, 6, 1, 6)
- wing1.addBox("pin1", 0, -1, 2, 1, 3, 1)
- wing2.addBox("flap2", -5, 0, 1, 6, 1, 6)
- wing2.addBox("pin2", -1, -1, 2, 1, 3, 1)
- wing3.addBox("flap3", -5, 0, -7, 6, 1, 6)
- wing3.addBox("pin3", -1, -1, -3, 1, 3, 1)
-
- light0.addBox("flap0", -1, 0, -7, 6, 1, 6)
- light1.addBox("flap1", -1, 0, 1, 6, 1, 6)
- light2.addBox("flap2", -5, 0, 1, 6, 1, 6)
- light3.addBox("flap3", -5, 0, -7, 6, 1, 6)
+ texWidth = 64
+ texHeight = 32
+
+ bootRight.y = 10.1f
+ bootLeft.y = 10.11f
+
+ droneBody.texOffs(0, 23).addBox(-3, 1, -3, 6, 1, 6).yRot = math.toRadians(45).toFloat // top
+ droneBody.texOffs(0, 1).addBox(-1, 0, -1, 2, 1, 2).yRot = math.toRadians(45).toFloat // middle
+ droneBody.texOffs(0, 17).addBox(-2, -1, -2, 4, 1, 4).yRot = math.toRadians(45).toFloat // bottom
+ wing0.texOffs(0, 9).addBox(-1, 0, -7, 6, 1, 6) // flap0
+ wing0.texOffs(0, 27).addBox(0, -1, -3, 1, 3, 1) // pin0
+ wing1.texOffs(0, 9).addBox(-1, 0, 1, 6, 1, 6) // flap1
+ wing1.texOffs(0, 27).addBox(0, -1, 2, 1, 3, 1) // pin1
+ wing2.texOffs(0, 9).addBox(-5, 0, 1, 6, 1, 6) // flap2
+ wing2.texOffs(0, 27).addBox(-1, -1, 2, 1, 3, 1) // pin2
+ wing3.texOffs(0, 9).addBox(-5, 0, -7, 6, 1, 6) // flap3
+ wing3.texOffs(0, 27).addBox(-1, -1, -3, 1, 3, 1) // pin3
+
+ light0.texOffs(24, 0).addBox(-1, 0, -7, 6, 1, 6) // flap0
+ light1.texOffs(24, 0).addBox(-1, 0, 1, 6, 1, 6) // flap1
+ light2.texOffs(24, 0).addBox(-5, 0, 1, 6, 1, 6) // flap2
+ light3.texOffs(24, 0).addBox(-5, 0, -7, 6, 1, 6) // flap3
// No drone textured legs, thank you very much.
- bipedLeftLeg.cubeList.clear()
- bipedRightLeg.cubeList.clear()
+ leftLeg = leftLeg.createShallowCopy()
+ rightLeg = rightLeg.createShallowCopy()
- bipedLeftLeg.addChild(bootLeft)
- bipedRightLeg.addChild(bootRight)
+ leftLeg.addChild(bootLeft)
+ rightLeg.addChild(bootRight)
- bipedHead.isHidden = true
- bipedHeadwear.isHidden = true
- bipedBody.isHidden = true
- bipedRightArm.isHidden = true
- bipedLeftArm.isHidden = true
+ head.visible = false
+ hat.visible = false
+ body.visible = false
+ rightArm.visible = false
+ leftArm.visible = false
var lightColor = 0x66DD55
- override def render(entity: Entity, f0: Float, f1: Float, f2: Float, f3: Float, f4: Float, f5: Float): Unit = {
+ override def setupAnim(entity: LivingEntity, f1: Float, f2: Float, f3: Float, f4: Float, f5: Float): Unit = {
+ super.setupAnim(entity, f1, f2, f3, f4, f5)
// Because Forge is being a dummy...
- isSneak = entity.isSneaking
+ crouching = entity.isCrouching
// Because Forge is being an even bigger dummy...
- isChild = false
- super.render(entity, f0, f1, f2, f3, f4, f5)
+ young = false
}
- class LightModelRenderer(modelBase: ModelBase, name: String) extends ModelRenderer(modelBase, name) {
- override def render(dt: Float): Unit = {
- RenderState.pushAttrib()
- GlStateManager.disableLighting()
- RenderState.disableEntityLighting()
- GlStateManager.depthFunc(GL11.GL_LEQUAL)
- RenderState.makeItBlend()
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
- val r = ((lightColor >>> 16) & 0xFF) / 255f
- val g = ((lightColor >>> 8) & 0xFF) / 255f
- val b = ((lightColor >>> 0) & 0xFF) / 255f
- GlStateManager.color(r, g, b)
-
- super.render(dt)
-
- RenderState.disableBlend()
- GlStateManager.enableLighting()
- RenderState.enableEntityLighting()
- GlStateManager.color(1, 1, 1)
- RenderState.popAttrib()
+ class LightModelRenderer(modelBase: Model) extends ModelRenderer(modelBase) {
+ override def render(stack: MatrixStack, builder: IVertexBuilder, light: Int, overlay: Int, r: Float, g: Float, b: Float, a: Float): Unit = {
+ val rm = ((lightColor >>> 16) & 0xFF) / 255f
+ val gm = ((lightColor >>> 8) & 0xFF) / 255f
+ val bm = ((lightColor >>> 0) & 0xFF) / 255f
+
+ super.render(stack, builder, LightTexture.pack(15, 15), OverlayTexture.NO_OVERLAY, r * rm, g * gm, b * bm, a)
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala
index e4dd1512b8..27efacf8e1 100644
--- a/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/item/UpgradeRenderer.scala
@@ -1,17 +1,21 @@
package li.cil.oc.client.renderer.item
+import com.google.common.collect.ImmutableList
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.api.driver.item.UpgradeRenderer.MountPointName
import li.cil.oc.api.event.RobotRenderEvent.MountPoint
-import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.integration.opencomputers.Item
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
+import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
+import net.minecraft.client.renderer.vertex.VertexFormat
import net.minecraft.item.ItemStack
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.util.math.vector.Vector3f
import org.lwjgl.opengl.GL11
object UpgradeRenderer {
@@ -36,71 +40,63 @@ object UpgradeRenderer {
descriptor == craftingUpgrade || descriptor == generatorUpgrade || descriptor == inventoryUpgrade
}
- def render(stack: ItemStack, mountPoint: MountPoint): Unit = {
+ def render(matrix: MatrixStack, buffer: IRenderTypeBuffer, stack: ItemStack, mountPoint: MountPoint): Unit = {
val descriptor = api.Items.get(stack)
if (descriptor == api.Items.get(Constants.ItemName.CraftingUpgrade)) {
- Textures.bind(Textures.Model.UpgradeCrafting)
- drawSimpleBlock(mountPoint)
+ drawSimpleBlock(matrix, buffer.getBuffer(RenderTypes.UPGRADE_CRAFTING), mountPoint)
RenderState.checkError(getClass.getName + ".renderItem: crafting upgrade")
}
else if (descriptor == api.Items.get(Constants.ItemName.GeneratorUpgrade)) {
- Textures.bind(Textures.Model.UpgradeGenerator)
- drawSimpleBlock(mountPoint, if (Item.dataTag(stack).getInteger("remainingTicks") > 0) 0.5f else 0)
+ drawSimpleBlock(matrix, buffer.getBuffer(RenderTypes.UPGRADE_GENERATOR), mountPoint, if (Item.dataTag(stack).getInt("remainingTicks") > 0) 0.5f else 0)
RenderState.checkError(getClass.getName + ".renderItem: generator upgrade")
}
else if (descriptor == api.Items.get(Constants.ItemName.InventoryUpgrade)) {
- Textures.bind(Textures.Model.UpgradeInventory)
- drawSimpleBlock(mountPoint)
+ drawSimpleBlock(matrix, buffer.getBuffer(RenderTypes.UPGRADE_INVENTORY), mountPoint)
RenderState.checkError(getClass.getName + ".renderItem: inventory upgrade")
}
}
- private val bounds = new AxisAlignedBB(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1)
+ private val (minX, minY, minZ) = (-0.1f, -0.1f, -0.1f)
+ private val (maxX, maxY, maxZ) = (0.1f, 0.1f, 0.1f)
- private def drawSimpleBlock(mountPoint: MountPoint, frontOffset: Float = 0) {
- GlStateManager.rotate(mountPoint.rotation.getW, mountPoint.rotation.getX, mountPoint.rotation.getY, mountPoint.rotation.getZ)
- GlStateManager.translate(mountPoint.offset.getX, mountPoint.offset.getY, mountPoint.offset.getZ)
-
- val t = Tessellator.getInstance()
- val r = t.getBuffer
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_NORMAL)
+ private def drawSimpleBlock(stack: MatrixStack, r: IVertexBuilder, mountPoint: MountPoint, frontOffset: Float = 0) {
+ stack.mulPose(new Vector3f(mountPoint.rotation.x, mountPoint.rotation.y, mountPoint.rotation.z).rotationDegrees(mountPoint.rotation.w))
+ stack.translate(mountPoint.offset.x, mountPoint.offset.y, mountPoint.offset.z)
// Front.
- r.pos(bounds.minX, bounds.minY, bounds.maxZ).tex(frontOffset, 0.5f).normal(0, 0, 1).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.maxZ).tex(frontOffset + 0.5f, 0.5f).normal(0, 0, 1).endVertex()
- r.pos(bounds.maxX, bounds.maxY, bounds.maxZ).tex(frontOffset + 0.5f, 0).normal(0, 0, 1).endVertex()
- r.pos(bounds.minX, bounds.maxY, bounds.maxZ).tex(frontOffset, 0).normal(0, 0, 1).endVertex()
+ r.vertex(stack.last.pose, minX, minY, maxZ).uv(frontOffset, 0.5f).normal(stack.last.normal, 0, 0, 1).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, maxZ).uv(frontOffset + 0.5f, 0.5f).normal(stack.last.normal, 0, 0, 1).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY, maxZ).uv(frontOffset + 0.5f, 0).normal(stack.last.normal, 0, 0, 1).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, maxZ).uv(frontOffset, 0).normal(stack.last.normal, 0, 0, 1).endVertex()
// Top.
- r.pos(bounds.maxX, bounds.maxY, bounds.maxZ).tex(1, 0.5f).normal(0, 1, 0).endVertex()
- r.pos(bounds.maxX, bounds.maxY, bounds.minZ).tex(1, 1).normal(0, 1, 0).endVertex()
- r.pos(bounds.minX, bounds.maxY, bounds.minZ).tex(0.5f, 1).normal(0, 1, 0).endVertex()
- r.pos(bounds.minX, bounds.maxY, bounds.maxZ).tex(0.5f, 0.5f).normal(0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY, maxZ).uv(1, 0.5f).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY, minZ).uv(1, 1).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, minZ).uv(0.5f, 1).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, maxZ).uv(0.5f, 0.5f).normal(stack.last.normal, 0, 1, 0).endVertex()
// Bottom.
- r.pos(bounds.minX, bounds.minY, bounds.maxZ).tex(0.5f, 0.5f).normal(0, -1, 0).endVertex()
- r.pos(bounds.minX, bounds.minY, bounds.minZ).tex(0.5f, 1).normal(0, -1, 0).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.minZ).tex(1, 1).normal(0, -1, 0).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.maxZ).tex(1, 0.5f).normal(0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, minX, minY, maxZ).uv(0.5f, 0.5f).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, minX, minY, minZ).uv(0.5f, 1).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, minZ).uv(1, 1).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, maxZ).uv(1, 0.5f).normal(stack.last.normal, 0, -1, 0).endVertex()
// Left.
- r.pos(bounds.maxX, bounds.maxY, bounds.maxZ).tex(0, 0.5f).normal(1, 0, 0).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.maxZ).tex(0, 1).normal(1, 0, 0).endVertex()
- r.pos(bounds.maxX, bounds.minY, bounds.minZ).tex(0.5f, 1).normal(1, 0, 0).endVertex()
- r.pos(bounds.maxX, bounds.maxY, bounds.minZ).tex(0.5f, 0.5f).normal(1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY, maxZ).uv(0, 0.5f).normal(stack.last.normal, 1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, maxZ).uv(0, 1).normal(stack.last.normal, 1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, minY, minZ).uv(0.5f, 1).normal(stack.last.normal, 1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, maxX, maxY, minZ).uv(0.5f, 0.5f).normal(stack.last.normal, 1, 0, 0).endVertex()
// Right.
- r.pos(bounds.minX, bounds.minY, bounds.maxZ).tex(0, 1).normal(-1, 0, 0).endVertex()
- r.pos(bounds.minX, bounds.maxY, bounds.maxZ).tex(0, 0.5f).normal(-1, 0, 0).endVertex()
- r.pos(bounds.minX, bounds.maxY, bounds.minZ).tex(0.5f, 0.5f).normal(-1, 0, 0).endVertex()
- r.pos(bounds.minX, bounds.minY, bounds.minZ).tex(0.5f, 1).normal(-1, 0, 0).endVertex()
-
- t.draw()
+ r.vertex(stack.last.pose, minX, minY, maxZ).uv(0, 1).normal(stack.last.normal, -1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, maxZ).uv(0, 0.5f).normal(stack.last.normal, -1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, minX, maxY, minZ).uv(0.5f, 0.5f).normal(stack.last.normal, -1, 0, 0).endVertex()
+ r.vertex(stack.last.pose, minX, minY, minZ).uv(0.5f, 1).normal(stack.last.normal, -1, 0, 0).endVertex()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/Document.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/Document.scala
index 82ca004ff6..9ecea144b0 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/Document.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/Document.scala
@@ -1,12 +1,14 @@
package li.cil.oc.client.renderer.markdown
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.api
import li.cil.oc.client.renderer.markdown.segment.InteractiveSegment
import li.cil.oc.client.renderer.markdown.segment.Segment
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.FontRenderer
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.util.math.vector.Vector4f
import org.lwjgl.opengl.GL11
import scala.collection.Iterable
@@ -61,45 +63,32 @@ object Document {
/**
* Line height for a normal line of text.
*/
- def lineHeight(renderer: FontRenderer): Int = renderer.FONT_HEIGHT + 1
+ def lineHeight(renderer: FontRenderer): Int = renderer.lineHeight + 1
/**
* Renders a list of segments and tooltips if a segment with a tooltip is hovered.
* Returns the hovered interactive segment, if any.
*/
- def render(document: Segment, x: Int, y: Int, maxWidth: Int, maxHeight: Int, yOffset: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
- val mc = Minecraft.getMinecraft
+ def render(stack: MatrixStack, document: Segment, x: Int, y: Int, maxWidth: Int, maxHeight: Int, yOffset: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
+ val window = Minecraft.getInstance.getWindow
RenderState.pushAttrib()
- // On some systems/drivers/graphics cards the next calls won't update the
- // depth buffer correctly if alpha test is enabled. Guess how we found out?
- // By noticing that on those systems it only worked while chat messages
- // were visible. Yeah. I know.
- GlStateManager.disableAlpha()
-
- // Clear depth mask, then create masks in foreground above and below scroll area.
- GlStateManager.color(1, 1, 1, 1)
- GlStateManager.clear(GL11.GL_DEPTH_BUFFER_BIT)
- GlStateManager.enableDepth()
- GlStateManager.depthFunc(GL11.GL_LEQUAL)
- GlStateManager.depthMask(true)
- GlStateManager.colorMask(false, false, false, false)
-
- GlStateManager.pushMatrix()
- GlStateManager.translate(0, 0, 500)
- GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex2f(0, y)
- GL11.glVertex2f(mc.displayWidth, y)
- GL11.glVertex2f(mc.displayWidth, 0)
- GL11.glVertex2f(0, 0)
- GL11.glVertex2f(0, mc.displayHeight)
- GL11.glVertex2f(mc.displayWidth, mc.displayHeight)
- GL11.glVertex2f(mc.displayWidth, y + maxHeight)
- GL11.glVertex2f(0, y + maxHeight)
- GL11.glEnd()
- GlStateManager.popMatrix()
- GlStateManager.colorMask(true, true, true, true)
+ RenderSystem.color4f(1, 1, 1, 1)
+ // Clip using the scissor test to not interfere with RenderType-maintained depth testing.
+ GL11.glEnable(GL11.GL_SCISSOR_TEST)
+ val (x0, y0, x1, y1) = {
+ val scale = window.getGuiScale
+ val bottomLeft = new Vector4f(x, y + maxHeight, 0, 1)
+ bottomLeft.transform(stack.last.pose)
+ val topRight = new Vector4f(x + maxWidth, y, 0, 1)
+ topRight.transform(stack.last.pose)
+ ((bottomLeft.x * scale).floor.asInstanceOf[Int],
+ (window.getHeight - bottomLeft.y * scale).floor.asInstanceOf[Int],
+ (topRight.x * scale).ceil.asInstanceOf[Int],
+ (window.getHeight - topRight.y * scale).ceil.asInstanceOf[Int])
+ }
+ GL11.glScissor(x0, y0, x1 - x0, y1 - y0);
// Actual rendering.
var hovered: Option[InteractiveSegment] = None
@@ -111,7 +100,7 @@ object Document {
while (segment != null) {
val segmentHeight = segment.nextY(indent, maxWidth, renderer)
if (currentY + segmentHeight >= minY && currentY <= maxY) {
- val result = segment.render(x, currentY, indent, maxWidth, renderer, mouseX, mouseY)
+ val result = segment.render(stack, x, currentY, indent, maxWidth, renderer, mouseX, mouseY)
hovered = hovered.orElse(result)
}
currentY += segmentHeight
@@ -121,8 +110,7 @@ object Document {
if (mouseX < x || mouseX > x + maxWidth || mouseY < y || mouseY > y + maxHeight) hovered = None
hovered.foreach(_.notifyHover())
- RenderState.popAttrib()
- GlStateManager.bindTexture(0)
+ GL11.glDisable(GL11.GL_SCISSOR_TEST)
hovered
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala
index 365577fe4a..c7a094e00d 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala
@@ -78,5 +78,5 @@ trait BasicTextSegment extends Segment {
pos
}
- protected def computeWrapIndent(renderer: FontRenderer) = if (lists.contains(rootPrefix)) renderer.getStringWidth(rootPrefix) else 0
+ protected def computeWrapIndent(renderer: FontRenderer) = if (lists.contains(rootPrefix)) renderer.width(rootPrefix) else 0
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala
index 692019483f..9b63146654 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala
@@ -1,12 +1,13 @@
package li.cil.oc.client.renderer.markdown.segment
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.renderer.TextBufferRenderCache
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer
-import net.minecraft.client.renderer.GlStateManager
private[markdown] class CodeSegment(val parent: Segment, val text: String) extends BasicTextSegment {
- override def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
+ override def render(stack: MatrixStack, x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
TextBufferRenderCache.renderer.generateChars(text.toCharArray)
var currentX = x + indent
@@ -16,8 +17,8 @@ private[markdown] class CodeSegment(val parent: Segment, val text: String) exten
var numChars = maxChars(chars, maxWidth - indent, maxWidth - wrapIndent, renderer)
while (chars.length > 0) {
val part = chars.take(numChars)
- GlStateManager.color(0.75f, 0.8f, 1, 1)
- TextBufferRenderCache.renderer.drawString(part, currentX, currentY)
+ RenderSystem.color4f(0.75f, 0.8f, 1, 1)
+ TextBufferRenderCache.renderer.drawString(stack, part, currentX, currentY)
currentX = x + wrapIndent
currentY += lineHeight(renderer)
chars = chars.drop(numChars).dropWhile(_.isWhitespace)
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala
index 84af300415..c105849cc3 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala
@@ -8,6 +8,7 @@ import li.cil.oc.api
import li.cil.oc.client.Manual
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.Minecraft
+import net.minecraft.util.Util
private[markdown] class LinkSegment(parent: Segment, text: String, val url: String) extends TextSegment(parent, text) with InteractiveSegment {
private final val normalColor = 0x66FF66
@@ -52,7 +53,7 @@ private[markdown] class LinkSegment(parent: Segment, text: String, val url: Stri
desktop.getMethod("browse", classOf[URI]).invoke(instance, new URI(url))
}
catch {
- case t: Throwable => Minecraft.getMinecraft.player.sendMessage(Localization.Chat.WarningLink(t.toString))
+ case t: Throwable => Minecraft.getInstance.player.sendMessage(Localization.Chat.WarningLink(t.toString), Util.NIL_UUID)
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala
index 4f484c3548..d8ace50bc5 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala
@@ -1,11 +1,14 @@
package li.cil.oc.client.renderer.markdown.segment
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.api.manual.ImageRenderer
import li.cil.oc.api.manual.InteractiveImageRenderer
import li.cil.oc.client.renderer.markdown.Document
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer
-import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.util.math.vector.Matrix4f
+import net.minecraft.util.math.vector.Vector4f
import org.lwjgl.opengl.GL11
private[markdown] class RenderSegment(val parent: Segment, val title: String, val imageRenderer: ImageRenderer) extends InteractiveSegment {
@@ -32,7 +35,7 @@ private[markdown] class RenderSegment(val parent: Segment, val title: String, va
override def nextX(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = 0
- override def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
+ override def render(stack: MatrixStack, x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
val width = imageWidth(maxWidth)
val height = imageHeight(maxWidth)
val xOffset = (maxWidth - width) / 2
@@ -44,34 +47,45 @@ private[markdown] class RenderSegment(val parent: Segment, val title: String, va
val hovered = checkHovered(mouseX, mouseY, x + xOffset, y + yOffset, width, height)
- GlStateManager.pushMatrix()
- GlStateManager.translate(x + xOffset, y + yOffset, 0)
- GlStateManager.scale(s, s, s)
+ stack.pushPose()
+ stack.translate(x + xOffset, y + yOffset, 0)
+ stack.scale(s, s, s)
- GlStateManager.enableBlend()
- GlStateManager.enableAlpha()
+ RenderSystem.enableBlend()
+ RenderSystem.enableAlphaTest()
+ // Disabled by text rendering above it (default state is disabled).
+ RenderSystem.enableDepthTest()
if (hovered.isDefined) {
- GlStateManager.color(1, 1, 1, 0.15f)
- GlStateManager.disableTexture2D()
+ RenderSystem.color4f(1, 1, 1, 0.15f)
+ RenderSystem.disableTexture()
GL11.glBegin(GL11.GL_QUADS)
- GL11.glVertex2f(0, 0)
- GL11.glVertex2f(0, imageRenderer.getHeight)
- GL11.glVertex2f(imageRenderer.getWidth, imageRenderer.getHeight)
- GL11.glVertex2f(imageRenderer.getWidth, 0)
+ val matrix = stack.last.pose
+ val vec = new Vector4f(0, 0, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ vec.set(0, imageRenderer.getHeight, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ vec.set(imageRenderer.getWidth, imageRenderer.getHeight, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
+ vec.set(imageRenderer.getWidth, 0, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glEnd()
- GlStateManager.enableTexture2D()
+ RenderSystem.enableTexture()
}
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
- imageRenderer.render(mouseX - x, mouseY - y)
+ imageRenderer.render(stack, mouseX - x, mouseY - y)
- GlStateManager.disableBlend()
- GlStateManager.disableAlpha()
- GlStateManager.disableLighting()
+ RenderSystem.disableBlend()
+ RenderSystem.disableAlphaTest()
+ RenderSystem.disableLighting()
- GlStateManager.popMatrix()
+ stack.popPose()
hovered
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala
index 645dd1a90a..13a4b59052 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala
@@ -1,5 +1,6 @@
package li.cil.oc.client.renderer.markdown.segment
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer
@@ -46,7 +47,7 @@ trait Segment {
* Render the segment at the specified coordinates with the specified
* properties.
*/
- def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = None
+ def render(stack: MatrixStack, x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = None
def renderAsText(format: MarkupFormat.Value): Iterable[String] = {
var segment = this
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala
index f89032ba5e..b47ad92679 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala
@@ -1,15 +1,16 @@
package li.cil.oc.client.renderer.markdown.segment
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.renderer.markdown.Document
import net.minecraft.client.gui.FontRenderer
-import net.minecraft.client.renderer.GlStateManager
import org.lwjgl.opengl.GL11
import scala.collection.mutable
import scala.util.matching.Regex
private[markdown] class TextSegment(val parent: Segment, val text: String) extends BasicTextSegment {
- override def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
+ override def render(stack: MatrixStack, x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
var currentX = x + indent
var currentY = y
var chars = text
@@ -20,12 +21,12 @@ private[markdown] class TextSegment(val parent: Segment, val text: String) exten
while (chars.length > 0) {
val part = chars.take(numChars)
hovered = hovered.orElse(resolvedInteractive.fold(None: Option[InteractiveSegment])(_.checkHovered(mouseX, mouseY, currentX, currentY, stringWidth(part, renderer), (Document.lineHeight(renderer) * resolvedScale).toInt)))
- GlStateManager.pushMatrix()
- GlStateManager.translate(currentX, currentY, 0)
- GlStateManager.scale(resolvedScale, resolvedScale, resolvedScale)
- GlStateManager.translate(-currentX, -currentY, 0)
- renderer.drawString(resolvedFormat + part, currentX, currentY, resolvedColor)
- GlStateManager.popMatrix()
+ stack.pushPose()
+ stack.translate(currentX, currentY, 0)
+ stack.scale(resolvedScale, resolvedScale, resolvedScale)
+ stack.translate(-currentX, -currentY, 0)
+ renderer.draw(stack, resolvedFormat + part, currentX, currentY, resolvedColor)
+ stack.popPose()
currentX = x + wrapIndent
currentY += lineHeight(renderer)
chars = chars.drop(numChars).dropWhile(_.isWhitespace)
@@ -65,7 +66,7 @@ private[markdown] class TextSegment(val parent: Segment, val text: String) exten
override protected def lineHeight(renderer: FontRenderer): Int = (super.lineHeight(renderer) * resolvedScale).toInt
- override protected def stringWidth(s: String, renderer: FontRenderer): Int = (renderer.getStringWidth(resolvedFormat + s) * resolvedScale).toInt
+ override protected def stringWidth(s: String, renderer: FontRenderer): Int = (renderer.width(resolvedFormat + s) * resolvedScale).toInt
// ----------------------------------------------------------------------- //
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/BlockImageProvider.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/BlockImageProvider.scala
index 8314464fc9..7329e253e0 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/BlockImageProvider.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/BlockImageProvider.scala
@@ -1,23 +1,18 @@
package li.cil.oc.client.renderer.markdown.segment.render
-import com.google.common.base.Strings
import li.cil.oc.api.manual.ImageProvider
import li.cil.oc.api.manual.ImageRenderer
import li.cil.oc.api.manual.InteractiveImageRenderer
-import li.cil.oc.client.Textures
import net.minecraft.block.Block
-import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
+import net.minecraftforge.registries.ForgeRegistries
object BlockImageProvider extends ImageProvider {
override def getImage(data: String): ImageRenderer = {
- val splitIndex = data.lastIndexOf('@')
- val (name, optMeta) = if (splitIndex > 0) data.splitAt(splitIndex) else (data, "")
- val meta = if (Strings.isNullOrEmpty(optMeta)) 0 else Integer.parseInt(optMeta.drop(1))
- Block.REGISTRY.getObject(new ResourceLocation(name)) match {
- case block: Block if Item.getItemFromBlock(block) != null => new ItemStackImageRenderer(Array(new ItemStack(block, 1, meta)))
- case _ => new TextureImageRenderer(Textures.GUI.ManualMissingItem) with InteractiveImageRenderer {
+ ForgeRegistries.BLOCKS.getValue(new ResourceLocation(data.toLowerCase)) match {
+ case block: Block if block.asItem() != null => new ItemStackImageRenderer(Array(new ItemStack(block)))
+ case _ => new TextureImageRenderer(TextureImageProvider.ManualMissingItem) with InteractiveImageRenderer {
override def getTooltip(tooltip: String): String = "oc:gui.Manual.Warning.BlockMissing"
override def onMouseClick(mouseX: Int, mouseY: Int): Boolean = false
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemImageProvider.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemImageProvider.scala
index f0ae718de0..9c3ebacec7 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemImageProvider.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemImageProvider.scala
@@ -1,22 +1,18 @@
package li.cil.oc.client.renderer.markdown.segment.render
-import com.google.common.base.Strings
import li.cil.oc.api.manual.ImageProvider
import li.cil.oc.api.manual.ImageRenderer
import li.cil.oc.api.manual.InteractiveImageRenderer
-import li.cil.oc.client.Textures
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
+import net.minecraftforge.registries.ForgeRegistries
object ItemImageProvider extends ImageProvider {
override def getImage(data: String): ImageRenderer = {
- val splitIndex = data.lastIndexOf('@')
- val (name, optMeta) = if (splitIndex > 0) data.splitAt(splitIndex) else (data, "")
- val meta = if (Strings.isNullOrEmpty(optMeta)) 0 else Integer.parseInt(optMeta.drop(1))
- Item.REGISTRY.getObject(new ResourceLocation(name)) match {
- case item: Item => new ItemStackImageRenderer(Array(new ItemStack(item, 1, meta)))
- case _ => new TextureImageRenderer(Textures.GUI.ManualMissingItem) with InteractiveImageRenderer {
+ ForgeRegistries.ITEMS.getValue(new ResourceLocation(data.toLowerCase)) match {
+ case item: Item => new ItemStackImageRenderer(Array(new ItemStack(item)))
+ case _ => new TextureImageRenderer(TextureImageProvider.ManualMissingItem) with InteractiveImageRenderer {
override def getTooltip(tooltip: String): String = "oc:gui.Manual.Warning.ItemMissing"
override def onMouseClick(mouseX: Int, mouseY: Int): Boolean = false
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemStackImageRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemStackImageRenderer.scala
index 277591b0ff..cb334056a5 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemStackImageRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/ItemStackImageRenderer.scala
@@ -1,13 +1,14 @@
package li.cil.oc.client.renderer.markdown.segment.render
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.api.manual.ImageRenderer
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.OpenGlHelper
import net.minecraft.client.renderer.RenderHelper
import net.minecraft.item.ItemStack
import org.lwjgl.opengl.GL11
import org.lwjgl.opengl.GL12
+import org.lwjgl.opengl.GL13
private[markdown] class ItemStackImageRenderer(val stacks: Array[ItemStack]) extends ImageRenderer {
// How long to show individual stacks, in milliseconds, before switching to the next.
@@ -17,16 +18,18 @@ private[markdown] class ItemStackImageRenderer(val stacks: Array[ItemStack]) ext
override def getHeight = 32
- override def render(mouseX: Int, mouseY: Int): Unit = {
- val mc = Minecraft.getMinecraft
+ override def render(matrix: MatrixStack, mouseX: Int, mouseY: Int): Unit = {
+ val mc = Minecraft.getInstance
val index = (System.currentTimeMillis() % (cycleSpeed * stacks.length)).toInt / cycleSpeed
val stack = stacks(index)
- GlStateManager.scale(getWidth / 16, getHeight / 16, getWidth / 16)
- GlStateManager.enableRescaleNormal()
- RenderHelper.enableGUIStandardItemLighting()
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240)
- mc.getRenderItem.renderItemAndEffectIntoGUI(stack, 0, 0)
- RenderHelper.disableStandardItemLighting()
+ matrix.scale(getWidth / 16, getHeight / 16, getWidth / 16)
+ // Translate manually because ItemRenderer generally can't take a MatrixStack.
+ RenderSystem.pushMatrix()
+ RenderSystem.multMatrix(matrix.last().pose())
+ RenderSystem.enableRescaleNormal()
+ RenderSystem.glMultiTexCoord2f(GL13.GL_TEXTURE1, 240, 240)
+ mc.getItemRenderer.renderAndDecorateItem(stack, 0, 0)
+ RenderSystem.popMatrix()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/OreDictImageProvider.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/OreDictImageProvider.scala
index 0bad3914f9..220ef8358c 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/OreDictImageProvider.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/OreDictImageProvider.scala
@@ -4,15 +4,31 @@ import li.cil.oc.api.manual.ImageProvider
import li.cil.oc.api.manual.ImageRenderer
import li.cil.oc.api.manual.InteractiveImageRenderer
import li.cil.oc.client.Textures
-import net.minecraftforge.oredict.OreDictionary
+import net.minecraft.block.Block
+import net.minecraft.item.Item
+import net.minecraft.item.ItemStack
+import net.minecraft.tags._
+import net.minecraft.util.ResourceLocation
-import scala.collection.convert.WrapAsScala._
+import scala.collection.mutable
+import scala.collection.convert.ImplicitConversionsToScala._
object OreDictImageProvider extends ImageProvider {
override def getImage(data: String): ImageRenderer = {
- val stacks = OreDictionary.getOres(data).filter(stack => !stack.isEmpty && stack.getItem != null)
- if (stacks != null && stacks.nonEmpty) new ItemStackImageRenderer(stacks.toArray)
- else new TextureImageRenderer(Textures.GUI.ManualMissingItem) with InteractiveImageRenderer {
+ val desired = new ResourceLocation(data.toLowerCase)
+ val stacks = mutable.ArrayBuffer.empty[ItemStack]
+ ItemTags.getAllTags.getTag(desired) match {
+ case tag: ITag[Item] => stacks ++= tag.getValues.map(new ItemStack(_))
+ case _ =>
+ }
+ if (stacks.isEmpty) {
+ BlockTags.getAllTags.getTag(desired) match {
+ case tag: ITag[Block] => stacks ++= tag.getValues.map(new ItemStack(_))
+ case _ =>
+ }
+ }
+ if (stacks.nonEmpty) new ItemStackImageRenderer(stacks.toArray)
+ else new TextureImageRenderer(TextureImageProvider.ManualMissingItem) with InteractiveImageRenderer {
override def getTooltip(tooltip: String): String = "oc:gui.Manual.Warning.OreDictMissing"
override def onMouseClick(mouseX: Int, mouseY: Int): Boolean = false
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageProvider.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageProvider.scala
index 588c81bd76..9491f9f3c2 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageProvider.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageProvider.scala
@@ -7,9 +7,14 @@ import li.cil.oc.client.Textures
import net.minecraft.util.ResourceLocation
object TextureImageProvider extends ImageProvider {
+ val ManualMissingItem = {
+ val tex = Textures.GUI.ManualMissingItem
+ new ResourceLocation(tex.getNamespace, s"textures/${tex.getPath}.png")
+ }
+
override def getImage(data: String): ImageRenderer = {
- try new TextureImageRenderer(new ResourceLocation(data)) catch {
- case t: Throwable => new TextureImageRenderer(Textures.GUI.ManualMissingItem) with InteractiveImageRenderer {
+ try new TextureImageRenderer(new ResourceLocation(data.toLowerCase)) catch {
+ case t: Throwable => new TextureImageRenderer(ManualMissingItem) with InteractiveImageRenderer {
override def getTooltip(tooltip: String): String = "oc:gui.Manual.Warning.ImageMissing"
override def onMouseClick(mouseX: Int, mouseY: Int): Boolean = false
diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageRenderer.scala
index 4af762c091..77b1e9a58d 100644
--- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/render/TextureImageRenderer.scala
@@ -3,27 +3,29 @@ package li.cil.oc.client.renderer.markdown.segment.render
import java.io.InputStream
import javax.imageio.ImageIO
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.api.manual.ImageRenderer
import li.cil.oc.client.Textures
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.texture.AbstractTexture
+import net.minecraft.client.renderer.texture.Texture
import net.minecraft.client.renderer.texture.TextureUtil
-import net.minecraft.client.resources.IResourceManager
+import net.minecraft.resources.IResourceManager
import net.minecraft.util.ResourceLocation
+import net.minecraft.util.math.vector.Matrix4f
+import net.minecraft.util.math.vector.Vector4f
import org.lwjgl.opengl.GL11
+import org.lwjgl.system.MemoryUtil
class TextureImageRenderer(val location: ResourceLocation) extends ImageRenderer {
private val texture = {
- val manager = Minecraft.getMinecraft.getTextureManager
+ val manager = Minecraft.getInstance.getTextureManager
manager.getTexture(location) match {
case image: ImageTexture => image
case other =>
- if (other != null && other.getGlTextureId != -1) {
- TextureUtil.deleteTexture(other.getGlTextureId)
- }
+ if (other != null) other.releaseId()
val image = new ImageTexture(location)
- manager.loadTexture(location, image)
+ manager.register(location, image)
image
}
}
@@ -32,34 +34,54 @@ class TextureImageRenderer(val location: ResourceLocation) extends ImageRenderer
override def getHeight: Int = texture.height
- override def render(mouseX: Int, mouseY: Int): Unit = {
+ override def render(stack: MatrixStack, mouseX: Int, mouseY: Int): Unit = {
Textures.bind(location)
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
GL11.glBegin(GL11.GL_QUADS)
GL11.glTexCoord2f(0, 0)
- GL11.glVertex2f(0, 0)
+ val matrix = stack.last.pose
+ val vec = new Vector4f(0, 0, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glTexCoord2f(0, 1)
- GL11.glVertex2f(0, texture.height)
+ vec.set(0, texture.height, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glTexCoord2f(1, 1)
- GL11.glVertex2f(texture.width, texture.height)
+ vec.set(texture.width, texture.height, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glTexCoord2f(1, 0)
- GL11.glVertex2f(texture.width, 0)
+ vec.set(texture.width, 0, 0, 1)
+ vec.transform(matrix)
+ GL11.glVertex3f(vec.x, vec.y, vec.z)
GL11.glEnd()
}
- private class ImageTexture(val location: ResourceLocation) extends AbstractTexture {
+ private class ImageTexture(val location: ResourceLocation) extends Texture {
var width = 0
var height = 0
- override def loadTexture(manager: IResourceManager): Unit = {
- deleteGlTexture()
+ override def load(manager: IResourceManager): Unit = {
+ releaseId()
var is: InputStream = null
try {
val resource = manager.getResource(location)
is = resource.getInputStream
val bi = ImageIO.read(is)
- TextureUtil.uploadTextureImageAllocate(getGlTextureId, bi, false, false)
+ val data = MemoryUtil.memAllocInt(bi.getWidth * bi.getHeight)
+ val tempArr = Array.ofDim[Int]((1024 * 1024) min data.capacity)
+ val dy = tempArr.length / bi.getWidth
+ for (y0 <- 0 until bi.getHeight by dy) {
+ val currH = dy min (bi.getHeight - y0 - 1)
+ bi.getRGB(0, y0, bi.getWidth, currH, tempArr, 0, bi.getWidth)
+ data.put(tempArr, 0, bi.getWidth * currH)
+ }
+
+ bind()
+ data.flip()
+ TextureUtil.initTexture(data, bi.getWidth, bi.getHeight)
width = bi.getWidth
height = bi.getHeight
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/AdapterRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/AdapterRenderer.scala
index 9b5417e132..b6a06d7501 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/AdapterRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/AdapterRenderer.scala
@@ -1,90 +1,84 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.texture.TextureMap
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import org.lwjgl.opengl.GL11
-
-object AdapterRenderer extends TileEntitySpecialRenderer[tileentity.Adapter] {
- override def render(adapter: tileentity.Adapter, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
-
- if (adapter.openSides.contains(true)) {
- RenderState.pushAttrib()
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.texture.AtlasTexture
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+
+object AdapterRenderer extends Function[TileEntityRendererDispatcher, AdapterRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new AdapterRenderer(dispatch)
+}
- GlStateManager.pushMatrix()
+class AdapterRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.Adapter](dispatch) {
+ override def render(adapter: tileentity.Adapter, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ RenderSystem.color4f(1, 1, 1, 1)
- bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE)
+ if (adapter.openSides.contains(true)) {
+ stack.pushPose()
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
val sideActivity = Textures.getSprite(Textures.Block.AdapterOn)
- if (adapter.isSideOpen(EnumFacing.DOWN)) {
- r.pos(0, 1, 0).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 1, 0).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
- r.pos(1, 1, 1).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
+ if (adapter.isSideOpen(Direction.DOWN)) {
+ r.vertex(stack.last.pose, 0, 1, 0).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
}
- if (adapter.isSideOpen(EnumFacing.UP)) {
- r.pos(0, 0, 0).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 1).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 0).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
+ if (adapter.isSideOpen(Direction.UP)) {
+ r.vertex(stack.last.pose, 0, 0, 0).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
}
- if (adapter.isSideOpen(EnumFacing.NORTH)) {
- r.pos(1, 1, 0).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(0, 1, 0).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(0, 0, 0).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 0).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (adapter.isSideOpen(Direction.NORTH)) {
+ r.vertex(stack.last.pose, 1, 1, 0).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- if (adapter.isSideOpen(EnumFacing.SOUTH)) {
- r.pos(0, 1, 1).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(1, 1, 1).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(0, 0, 1).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (adapter.isSideOpen(Direction.SOUTH)) {
+ r.vertex(stack.last.pose, 0, 1, 1).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- if (adapter.isSideOpen(EnumFacing.WEST)) {
- r.pos(0, 1, 0).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(0, 0, 0).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (adapter.isSideOpen(Direction.WEST)) {
+ r.vertex(stack.last.pose, 0, 1, 0).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- if (adapter.isSideOpen(EnumFacing.EAST)) {
- r.pos(1, 1, 1).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 1).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (adapter.isSideOpen(Direction.EAST)) {
+ r.vertex(stack.last.pose, 1, 1, 1).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/AssemblerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/AssemblerRenderer.scala
index c8dd054827..129f5b025e 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/AssemblerRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/AssemblerRenderer.scala
@@ -1,75 +1,65 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Assembler
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.opengl.GL11
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.math.vector.Vector3f
-object AssemblerRenderer extends TileEntitySpecialRenderer[Assembler] {
+object AssemblerRenderer extends Function[TileEntityRendererDispatcher, AssemblerRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new AssemblerRenderer(dispatch)
+}
- override def render(assembler: Assembler, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+class AssemblerRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Assembler](dispatch) {
+ override def render(assembler: Assembler, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- RenderState.pushAttrib()
+ RenderSystem.color4f(1, 1, 1, 1)
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(1)
+ stack.pushPose()
- GlStateManager.pushMatrix()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
- val t = Tessellator.getInstance
- val r = t.getBuffer
-
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
{
val icon = Textures.getSprite(Textures.Block.AssemblerTopOn)
- r.pos(-0.5, 0.55, 0.5).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0.5, 0.55, 0.5).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0.5, 0.55, -0.5).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(-0.5, 0.55, -0.5).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, -0.5f, 0.55f, 0.5f).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0.5f, 0.55f, 0.5f).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0.5f, 0.55f, -0.5f).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, -0.5f, 0.55f, -0.5f).uv(icon.getU0, icon.getV0).endVertex()
}
- t.draw()
-
// TODO Unroll loop to draw all at once?
- val indent = 6 / 16f + 0.005
+ val indent = 6 / 16f + 0.005f
for (i <- 0 until 4) {
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
-
if (assembler.isAssembling) {
val icon = Textures.getSprite(Textures.Block.AssemblerSideAssembling)
- r.pos(indent, 0.5, -indent).tex(icon.getInterpolatedU((0.5 - indent) * 16), icon.getMaxV).endVertex()
- r.pos(indent, 0.5, indent).tex(icon.getInterpolatedU((0.5 + indent) * 16), icon.getMaxV).endVertex()
- r.pos(indent, -0.5, indent).tex(icon.getInterpolatedU((0.5 + indent) * 16), icon.getMinV).endVertex()
- r.pos(indent, -0.5, -indent).tex(icon.getInterpolatedU((0.5 - indent) * 16), icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, indent, 0.5f, -indent).uv(icon.getU((0.5f - indent) * 16), icon.getV1).endVertex()
+ r.vertex(stack.last.pose, indent, 0.5f, indent).uv(icon.getU((0.5f + indent) * 16), icon.getV1).endVertex()
+ r.vertex(stack.last.pose, indent, -0.5f, indent).uv(icon.getU((0.5f + indent) * 16), icon.getV0).endVertex()
+ r.vertex(stack.last.pose, indent, -0.5f, -indent).uv(icon.getU((0.5f - indent) * 16), icon.getV0).endVertex()
}
{
val icon = Textures.getSprite(Textures.Block.AssemblerSideOn)
- r.pos(0.5005, 0.5, -0.5).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0.5005, 0.5, 0.5).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0.5005, -0.5, 0.5).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0.5005, -0.5, -0.5).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 0.5005f, 0.5f, -0.5f).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0.5005f, 0.5f, 0.5f).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0.5005f, -0.5f, 0.5f).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0.5005f, -0.5f, -0.5f).uv(icon.getU0, icon.getV0).endVertex()
}
- t.draw()
-
- GlStateManager.rotate(90, 0, 1, 0)
+ stack.mulPose(Vector3f.YP.rotationDegrees(90))
}
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/CaseRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/CaseRenderer.scala
index 24af1347ae..99895e1d3d 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/CaseRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/CaseRenderer.scala
@@ -1,73 +1,62 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Case
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.RenderHelper
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
-import org.lwjgl.opengl.GL11
-
-object CaseRenderer extends TileEntitySpecialRenderer[Case] {
- override def render(computer: Case, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.util.math.vector.Vector3f
- RenderState.pushAttrib()
+object CaseRenderer extends Function[TileEntityRendererDispatcher, CaseRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new CaseRenderer(dispatch)
+}
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(1)
+class CaseRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Case](dispatch) {
+ override def render(computer: Case, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
+ stack.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
computer.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
- GlStateManager.translate(-0.5, 0.5, 0.505)
- GlStateManager.scale(1, -1, 1)
+ stack.translate(-0.5, 0.5, 0.505)
+ stack.scale(1, -1, 1)
if (computer.isRunning) {
- renderFrontOverlay(Textures.Block.CaseFrontOn)
- if (System.currentTimeMillis() - computer.lastFileSystemAccess < 400 && computer.world.rand.nextDouble() > 0.1) {
- renderFrontOverlay(Textures.Block.CaseFrontActivity)
+ renderFrontOverlay(stack, Textures.Block.CaseFrontOn, buffer.getBuffer(RenderTypes.BLOCK_OVERLAY))
+ if (System.currentTimeMillis() - computer.lastFileSystemAccess < 400 && computer.world.random.nextDouble() > 0.1) {
+ renderFrontOverlay(stack, Textures.Block.CaseFrontActivity, buffer.getBuffer(RenderTypes.BLOCK_OVERLAY))
}
}
else if (computer.hasErrored && RenderUtil.shouldShowErrorLight(computer.hashCode)) {
- renderFrontOverlay(Textures.Block.CaseFrontError)
+ renderFrontOverlay(stack, Textures.Block.CaseFrontError, buffer.getBuffer(RenderTypes.BLOCK_OVERLAY))
}
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
- private def renderFrontOverlay(texture: ResourceLocation): Unit = {
- val t = Tessellator.getInstance
- val r = t.getBuffer
-
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
-
+ private def renderFrontOverlay(stack: MatrixStack, texture: ResourceLocation, r: IVertexBuilder): Unit = {
val icon = Textures.getSprite(texture)
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- t.draw()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/ChargerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/ChargerRenderer.scala
index acd81901a8..429b7a4de8 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/ChargerRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/ChargerRenderer.scala
@@ -1,82 +1,75 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Charger
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import org.lwjgl.opengl.GL11
-
-object ChargerRenderer extends TileEntitySpecialRenderer[Charger] {
- override def render(charger: Charger, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3f
+
+object ChargerRenderer extends Function[TileEntityRendererDispatcher, ChargerRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new ChargerRenderer(dispatch)
+}
- if (charger.chargeSpeed > 0) {
- RenderState.pushAttrib()
+class ChargerRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Charger](dispatch) {
+ override def render(charger: Charger, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(1)
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
+ if (charger.chargeSpeed > 0) {
+ stack.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
charger.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
- GlStateManager.translate(-0.5f, 0.5f, 0.5f)
- GlStateManager.scale(1, -1, 1)
-
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ stack.translate(-0.5f, 0.5f, 0.5f)
+ stack.scale(1, -1, 1)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
{
- val inverse = 1 - charger.chargeSpeed
+ val inverse = 1 - charger.chargeSpeed.toFloat
val icon = Textures.getSprite(Textures.Block.ChargerFrontOn)
- r.pos(0, 1, 0.005).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0.005).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, inverse, 0.005).tex(icon.getMaxU, icon.getInterpolatedV(inverse * 16)).endVertex()
- r.pos(0, inverse, 0.005).tex(icon.getMinU, icon.getInterpolatedV(inverse * 16)).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0.005f).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0.005f).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, inverse, 0.005f).uv(icon.getU1, icon.getV(inverse * 16)).endVertex()
+ r.vertex(stack.last.pose, 0, inverse, 0.005f).uv(icon.getU0, icon.getV(inverse * 16)).endVertex()
}
if (charger.hasPower) {
val icon = Textures.getSprite(Textures.Block.ChargerSideOn)
- r.pos(-0.005, 1, -1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(-0.005, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(-0.005, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(-0.005, 0, -1).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, -0.005f, 1, -1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, -0.005f, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, -0.005f, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, -0.005f, 0, -1).uv(icon.getU0, icon.getV0).endVertex()
- r.pos(1, 1, -1.005).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, -1.005).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, -1.005).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, -1.005).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 1, 1, -1.005f).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, -1.005f).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, -1.005f).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, -1.005f).uv(icon.getU0, icon.getV0).endVertex()
- r.pos(1.005, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1.005, 1, -1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1.005, 0, -1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1.005, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 1.005f, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1.005f, 1, -1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1.005f, 0, -1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1.005f, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/DisassemblerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/DisassemblerRenderer.scala
index b57b468cdb..b129606b6c 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/DisassemblerRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/DisassemblerRenderer.scala
@@ -1,74 +1,68 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.opengl.GL11
-
-object DisassemblerRenderer extends TileEntitySpecialRenderer[tileentity.Disassembler] {
- override def render(disassembler: tileentity.Disassembler, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
- if (disassembler.isActive) {
- RenderState.pushAttrib()
+object DisassemblerRenderer extends Function[TileEntityRendererDispatcher, DisassemblerRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new DisassemblerRenderer(dispatch)
+}
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- GlStateManager.color(1, 1, 1, 1)
+class DisassemblerRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.Disassembler](dispatch) {
+ override def render(disassembler: tileentity.Disassembler, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ if (disassembler.isActive) {
+ stack.pushPose()
+
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- val t = Tessellator.getInstance
- val r = t.getBuffer
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
{
val icon = Textures.getSprite(Textures.Block.DisassemblerTopOn)
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
{
val icon = Textures.getSprite(Textures.Block.DisassemblerSideOn)
- r.pos(1, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(1, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 1, 1, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/DiskDriveRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/DiskDriveRenderer.scala
index a559eb1366..6068fe056e 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/DiskDriveRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/DiskDriveRenderer.scala
@@ -1,84 +1,68 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.DiskDrive
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.OpenGlHelper
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.block.model.ItemCameraTransforms
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.item.EntityItem
-import net.minecraft.util.EnumFacing
-import org.lwjgl.opengl.GL11
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.model.ItemCameraTransforms
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3f
+
+object DiskDriveRenderer extends Function[TileEntityRendererDispatcher, DiskDriveRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new DiskDriveRenderer(dispatch)
+}
-object DiskDriveRenderer extends TileEntitySpecialRenderer[DiskDrive] {
- override def render(drive: DiskDrive, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+class DiskDriveRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[DiskDrive](dispatch) {
+ override def render(drive: DiskDrive, dt: Float, matrix: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- RenderState.pushAttrib()
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
+ matrix.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ matrix.translate(0.5, 0.5, 0.5)
drive.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => matrix.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => matrix.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => matrix.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
drive.items(0) match {
case stack if !stack.isEmpty =>
- GlStateManager.pushMatrix()
- GlStateManager.translate(0, 3.5f / 16, 6 / 16f)
- GlStateManager.rotate(90, -1, 0, 0)
- GlStateManager.scale(0.5f, 0.5f, 0.5f)
+ matrix.pushPose()
+ matrix.translate(0, 3.5f / 16, 6 / 16f)
+ matrix.mulPose(Vector3f.XN.rotationDegrees(90))
+ matrix.scale(0.5f, 0.5f, 0.5f)
- val brightness = drive.world.getCombinedLight(drive.getPos.offset(drive.facing), 0)
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536)
-
- // This is very 'meh', but item frames do it like this, too!
- val entity = new EntityItem(drive.world, 0, 0, 0, stack)
- entity.hoverStart = 0
- Textures.Block.bind()
- Minecraft.getMinecraft.getRenderItem.renderItem(entity.getItem, ItemCameraTransforms.TransformType.FIXED)
- GlStateManager.popMatrix()
+ Minecraft.getInstance.getItemRenderer.renderStatic(stack, ItemCameraTransforms.TransformType.FIXED, light, overlay, matrix, buffer)
+ matrix.popPose()
case _ =>
}
- if (System.currentTimeMillis() - drive.lastAccess < 400 && drive.world.rand.nextDouble() > 0.1) {
- GlStateManager.translate(-0.5, 0.5, 0.505)
- GlStateManager.scale(1, -1, 1)
-
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(1)
+ if (System.currentTimeMillis() - drive.lastAccess < 400 && drive.world.random.nextDouble() > 0.1) {
+ matrix.translate(-0.5, 0.5, 0.505)
+ matrix.scale(1, -1, 1)
- val t = Tessellator.getInstance
- val r = t.getBuffer
-
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
val icon = Textures.getSprite(Textures.Block.DiskDriveFrontActivity)
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
+ r.vertex(matrix.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(matrix.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(matrix.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(matrix.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ matrix.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/GeolyzerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/GeolyzerRenderer.scala
index 16eeabdbf9..2d609c12ec 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/GeolyzerRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/GeolyzerRenderer.scala
@@ -1,50 +1,42 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Geolyzer
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.opengl.GL11
-
-object GeolyzerRenderer extends TileEntitySpecialRenderer[Geolyzer] {
- override def render(geolyzer: Geolyzer, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
- RenderState.pushAttrib()
+object GeolyzerRenderer extends Function[TileEntityRendererDispatcher, GeolyzerRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new GeolyzerRenderer(dispatch)
+}
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(1)
- GlStateManager.color(1, 1, 1, 1)
+class GeolyzerRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Geolyzer](dispatch) {
+ override def render(geolyzer: Geolyzer, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ stack.pushPose()
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
val icon = Textures.getSprite(Textures.Block.GeolyzerTopOn)
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala
index 39515d101b..9834f42212 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala
@@ -1,30 +1,41 @@
package li.cil.oc.client.renderer.tileentity
import java.nio.IntBuffer
+import java.util.ArrayDeque
+import java.util.function.Function
import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import com.google.common.cache.CacheBuilder
import com.google.common.cache.RemovalListener
import com.google.common.cache.RemovalNotification
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Settings
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity.Hologram
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.GlStateManager.CullFace
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3f
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.event.TickEvent.ClientTickEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.BufferUtils
import org.lwjgl.opengl.GL11
import org.lwjgl.opengl.GL15
import scala.util.Random
-object HologramRenderer extends TileEntitySpecialRenderer[Hologram] with Callable[Int] with RemovalListener[TileEntity, Int] {
+object HologramRenderer extends Function[TileEntityRendererDispatcher, HologramRenderer]
+ with Callable[Int] with RemovalListener[TileEntity, Int] {
+
+ override def apply(dispatch: TileEntityRendererDispatcher) = new HologramRenderer(dispatch)
+
private val random = new Random()
/** We cache the VBOs for the projectors we render for performance. */
@@ -65,76 +76,86 @@ object HologramRenderer extends TileEntitySpecialRenderer[Hologram] with Callabl
*/
private var failed = false
- override def render(hologram: Hologram, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- if (failed) {
- HologramRendererFallback.render(hologram, x, y, z, f, damage, alpha)
- return
- }
+ private val renderQueue = new ArrayDeque[Hologram]
- this.hologram = hologram
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+ // Defer actual rendering until now so transparent things render correctly.
+ @SubscribeEvent
+ def onRenderWorldLast(e: RenderWorldLastEvent): Unit = {
+ RenderState.checkError(getClass.getName + ".onRenderWorldLastEvent: entering (aka: wasntme)")
+
+ val stack = e.getMatrixStack
+ val camPos = Minecraft.getInstance.gameRenderer.getMainCamera.getPosition
+ val buffer = Minecraft.getInstance.renderBuffers.bufferSource
+
+ while (!renderQueue.isEmpty) {
+ val holo = renderQueue.removeFirst()
+ val pos = holo.getBlockPos
+ stack.pushPose()
+ stack.translate(pos.getX + 0.5 - camPos.x, pos.getY + 0.5 - camPos.y, pos.getZ + 0.5 - camPos.z)
+ doRender(holo, e.getPartialTicks, stack)
+ stack.popPose()
+ }
- if (!hologram.hasPower) return
+ RenderState.checkError(getClass.getName + ".onRenderWorldLastEvent: leaving")
+ }
- GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS)
- RenderState.pushAttrib()
+ private def doRender(hologram: Hologram, f: Float, stack: MatrixStack) {
+ HologramRenderer.hologram = hologram
+ GL11.glPushClientAttrib(GL11.GL_CLIENT_ALL_ATTRIB_BITS)
RenderState.makeItBlend()
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
+ RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
- val playerDistSq = x * x + y * y + z * z
- val maxDistSq = hologram.getMaxRenderDistanceSquared
+ val pos = hologram.getBlockPos
+ val relPos = Minecraft.getInstance.player.getEyePosition(f).
+ subtract(pos.getX + 0.5, pos.getY + 0.5, pos.getZ + 0.5)
+ val playerDistSq = relPos.dot(relPos)
+ val maxDistSq = hologram.getViewDistance * hologram.getViewDistance
val fadeDistSq = hologram.getFadeStartDistanceSquared
RenderState.setBlendAlpha(0.75f * (if (playerDistSq > fadeDistSq) math.max(0, 1 - ((playerDistSq - fadeDistSq) / (maxDistSq - fadeDistSq)).toFloat) else 1))
- GlStateManager.pushMatrix()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
-
hologram.yaw match {
- case EnumFacing.WEST => GL11.glRotatef(-90, 0, 1, 0)
- case EnumFacing.NORTH => GL11.glRotatef(180, 0, 1, 0)
- case EnumFacing.EAST => GL11.glRotatef(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
hologram.pitch match {
- case EnumFacing.DOWN => GL11.glRotatef(90, 1, 0, 0)
- case EnumFacing.UP => GL11.glRotatef(-90, 1, 0, 0)
+ case Direction.DOWN => stack.mulPose(Vector3f.XP.rotationDegrees(90))
+ case Direction.UP => stack.mulPose(Vector3f.XP.rotationDegrees(-90))
case _ => // No pitch.
}
- GlStateManager.rotate(hologram.rotationAngle, hologram.rotationX, hologram.rotationY, hologram.rotationZ)
- GlStateManager.rotate(hologram.rotationSpeed * (hologram.getWorld.getTotalWorldTime % (360 * 20 - 1) + f) / 20f, hologram.rotationSpeedX, hologram.rotationSpeedY, hologram.rotationSpeedZ)
+ stack.mulPose(new Vector3f(hologram.rotationX, hologram.rotationY, hologram.rotationZ).rotationDegrees(hologram.rotationAngle))
+ stack.mulPose(new Vector3f(hologram.rotationSpeedX, hologram.rotationSpeedY, hologram.rotationSpeedZ)
+ .rotationDegrees(hologram.rotationSpeed * (hologram.getLevel.getGameTime % (360 * 20 - 1) + f) / 20f))
- GlStateManager.scale(1.001, 1.001, 1.001) // Avoid z-fighting with other blocks.
- GlStateManager.translate(
+ stack.scale(1.001f, 1.001f, 1.001f) // Avoid z-fighting with other blocks.
+ stack.translate(
(hologram.translation.x * hologram.width / 16 - 1.5) * hologram.scale,
hologram.translation.y * hologram.height / 16 * hologram.scale,
(hologram.translation.z * hologram.width / 16 - 1.5) * hologram.scale)
// Do a bit of flickering, because that's what holograms do!
if (Settings.get.hologramFlickerFrequency > 0 && random.nextDouble() < Settings.get.hologramFlickerFrequency) {
- GlStateManager.scale(1 + random.nextGaussian() * 0.01, 1 + random.nextGaussian() * 0.001, 1 + random.nextGaussian() * 0.01)
- GlStateManager.translate(random.nextGaussian() * 0.01, random.nextGaussian() * 0.01, random.nextGaussian() * 0.01)
+ stack.scale(1 + random.nextGaussian().toFloat * 0.01f, 1 + random.nextGaussian().toFloat * 0.001f, 1 + random.nextGaussian().toFloat * 0.01f)
+ stack.translate(random.nextGaussian() * 0.01, random.nextGaussian() * 0.01, random.nextGaussian() * 0.01)
}
// After the below scaling, hologram is drawn inside a [0..48]x[0..32]x[0..48] box
- GlStateManager.scale(hologram.scale / 16f, hologram.scale / 16f, hologram.scale / 16f)
-
- bindTexture(Textures.Model.HologramEffect)
+ stack.scale(hologram.scale.toFloat / 16f, hologram.scale.toFloat / 16f, hologram.scale.toFloat / 16f)
- // Normalize normals (yes, glScale scales them too).
- GL11.glEnable(GL11.GL_NORMALIZE)
+ Textures.bind(Textures.Model.HologramEffect)
- val sx = (x + 0.5) * hologram.scale
- val sy = -(y + 0.5) * hologram.scale
- val sz = (z + 0.5) * hologram.scale
+ val sx = relPos.x * hologram.scale
+ val sy = relPos.y * hologram.scale
+ val sz = relPos.z * hologram.scale
if (sx >= -1.5 && sx <= 1.5 && sz >= -1.5 && sz <= 1.5 && sy >= 0 && sy <= 2) {
// Camera is inside the hologram.
- GlStateManager.disableCull()
+ RenderSystem.disableCull()
}
else {
// Camera is outside the hologram.
- GlStateManager.enableCull()
- GlStateManager.cullFace(CullFace.BACK)
+ RenderSystem.enableCull()
}
// We do two passes here to avoid weird transparency effects: in the first
@@ -142,22 +163,21 @@ object HologramRenderer extends TileEntitySpecialRenderer[Hologram] with Callabl
// When we don't do this the hologram will look different from different
// angles (because some faces will shine through sometimes and sometimes
// they won't), so a more... consistent look is desirable.
+ RenderSystem.pushMatrix()
+ RenderSystem.multMatrix(stack.last.pose)
val glBuffer = cache.get(hologram, this)
- GlStateManager.colorMask(false, false, false, false)
- GlStateManager.depthMask(true)
+ GL11.glEnable(GL11.GL_DEPTH_TEST)
+ RenderSystem.colorMask(false, false, false, false)
+ RenderSystem.depthMask(true)
draw(glBuffer)
- GlStateManager.colorMask(true, true, true, true)
- GlStateManager.depthFunc(GL11.GL_EQUAL)
+ RenderSystem.colorMask(true, true, true, true)
+ RenderSystem.depthFunc(GL11.GL_EQUAL)
draw(glBuffer)
- GlStateManager.depthFunc(GL11.GL_LEQUAL)
-
- GlStateManager.popMatrix()
+ RenderSystem.depthFunc(GL11.GL_LEQUAL)
+ RenderSystem.popMatrix()
RenderState.disableBlend()
- RenderState.popAttrib()
GL11.glPopClientAttrib()
-
- RenderState.checkError(getClass.getName + ".render: leaving")
}
def draw(glBuffer: Int) {
@@ -382,3 +402,14 @@ object HologramRenderer extends TileEntitySpecialRenderer[Hologram] with Callabl
@SubscribeEvent
def onTick(e: ClientTickEvent) = cache.cleanUp()
}
+
+class HologramRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Hologram](dispatch) {
+ override def render(hologram: Hologram, f: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ if (HologramRenderer.failed) {
+ HologramRendererFallback.render(hologram, f, stack, buffer, light, overlay)
+ return
+ }
+
+ if (hologram.hasPower) HologramRenderer.renderQueue.addLast(hologram)
+ }
+}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRendererFallback.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRendererFallback.scala
index 850fbaeaf3..ae63453f3b 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRendererFallback.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRendererFallback.scala
@@ -1,27 +1,34 @@
package li.cil.oc.client.renderer.tileentity
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.common.tileentity.Hologram
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.util.math.vector.Vector3f
-object HologramRendererFallback extends TileEntitySpecialRenderer[Hologram] {
+object HologramRendererFallback {
var text = "Requires OpenGL 1.5"
- override def render(hologram: Hologram, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+ def render(hologram: Hologram, f: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- val fontRenderer = Minecraft.getMinecraft.fontRenderer
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
- GlStateManager.translate(x + 0.5, y + 0.75, z + 0.5)
+ val fontRenderer = Minecraft.getInstance.font
- GlStateManager.scale(1 / 128f, -1 / 128f, 1 / 128f)
- GlStateManager.disableCull()
- fontRenderer.drawString(text, -fontRenderer.getStringWidth(text) / 2, 0, 0xFFFFFFFF)
+ stack.pushPose()
+ stack.translate(0.5, 0.75, 0.5)
+ stack.scale(1 / 128f, -1 / 128f, 1 / 128f)
- GlStateManager.popMatrix()
+ fontRenderer.drawInBatch(text, -fontRenderer.width(text) / 2, 0, 0xFFFFFFFF,
+ false, stack.last.pose, buffer, false, 0, light)
+ stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ fontRenderer.drawInBatch(text, -fontRenderer.width(text) / 2, 0, 0xFFFFFFFF,
+ false, stack.last.pose, buffer, false, 0, light)
+
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/MicrocontrollerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/MicrocontrollerRenderer.scala
index 26a0d4d82e..aec54a5b29 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/MicrocontrollerRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/MicrocontrollerRenderer.scala
@@ -1,73 +1,66 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Microcontroller
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.BufferBuilder
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
-import org.lwjgl.opengl.GL11
+import net.minecraft.util.math.vector.Vector3f
-object MicrocontrollerRenderer extends TileEntitySpecialRenderer[Microcontroller] {
- override def render(mcu: Microcontroller, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+object MicrocontrollerRenderer extends Function[TileEntityRendererDispatcher, MicrocontrollerRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new MicrocontrollerRenderer(dispatch)
+}
- RenderState.pushAttrib()
+class MicrocontrollerRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Microcontroller](dispatch) {
+ override def render(mcu: Microcontroller, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(1)
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
+ stack.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
mcu.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
- GlStateManager.translate(-0.5, 0.5, 0.505)
- GlStateManager.scale(1, -1, 1)
+ stack.translate(-0.5, 0.5, 0.505)
+ stack.scale(1, -1, 1)
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
-
- renderFrontOverlay(Textures.Block.MicrocontrollerFrontLight, r)
+ renderFrontOverlay(stack, Textures.Block.MicrocontrollerFrontLight, r)
if (mcu.isRunning) {
- renderFrontOverlay(Textures.Block.MicrocontrollerFrontOn, r)
+ renderFrontOverlay(stack, Textures.Block.MicrocontrollerFrontOn, r)
}
else if (mcu.hasErrored && RenderUtil.shouldShowErrorLight(mcu.hashCode)) {
- renderFrontOverlay(Textures.Block.MicrocontrollerFrontError, r)
+ renderFrontOverlay(stack, Textures.Block.MicrocontrollerFrontError, r)
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
- private def renderFrontOverlay(texture: ResourceLocation, r: BufferBuilder): Unit = {
+ private def renderFrontOverlay(stack: MatrixStack, texture: ResourceLocation, r: IVertexBuilder): Unit = {
val icon = Textures.getSprite(texture)
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/NetSplitterRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/NetSplitterRenderer.scala
index 847c653140..17627fa3b3 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/NetSplitterRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/NetSplitterRenderer.scala
@@ -1,90 +1,86 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.texture.TextureMap
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import org.lwjgl.opengl.GL11
-
-object NetSplitterRenderer extends TileEntitySpecialRenderer[tileentity.NetSplitter] {
- override def render(splitter: tileentity.NetSplitter, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.texture.AtlasTexture
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+
+object NetSplitterRenderer extends Function[TileEntityRendererDispatcher, NetSplitterRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new NetSplitterRenderer(dispatch)
+}
- if (splitter.openSides.contains(!splitter.isInverted)) {
- RenderState.pushAttrib()
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
+class NetSplitterRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.NetSplitter](dispatch) {
+ override def render(splitter: tileentity.NetSplitter, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ if (splitter.openSides.contains(!splitter.isInverted)) {
+ stack.pushPose()
- bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE)
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ Minecraft.getInstance().getModelManager().getAtlas(AtlasTexture.LOCATION_BLOCKS).bind()
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
val sideActivity = Textures.getSprite(Textures.Block.NetSplitterOn)
- if (splitter.isSideOpen(EnumFacing.DOWN)) {
- r.pos(0, 1, 0).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 1, 0).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
- r.pos(1, 1, 1).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
+ if (splitter.isSideOpen(Direction.DOWN)) {
+ r.vertex(stack.last.pose, 0, 1, 0).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
}
- if (splitter.isSideOpen(EnumFacing.UP)) {
- r.pos(0, 0, 0).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 1).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 0).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
+ if (splitter.isSideOpen(Direction.UP)) {
+ r.vertex(stack.last.pose, 0, 0, 0).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
}
- if (splitter.isSideOpen(EnumFacing.NORTH)) {
- r.pos(1, 1, 0).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(0, 1, 0).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(0, 0, 0).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 0).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (splitter.isSideOpen(Direction.NORTH)) {
+ r.vertex(stack.last.pose, 1, 1, 0).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- if (splitter.isSideOpen(EnumFacing.SOUTH)) {
- r.pos(0, 1, 1).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(1, 1, 1).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(0, 0, 1).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (splitter.isSideOpen(Direction.SOUTH)) {
+ r.vertex(stack.last.pose, 0, 1, 1).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- if (splitter.isSideOpen(EnumFacing.WEST)) {
- r.pos(0, 1, 0).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(0, 0, 0).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (splitter.isSideOpen(Direction.WEST)) {
+ r.vertex(stack.last.pose, 0, 1, 0).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- if (splitter.isSideOpen(EnumFacing.EAST)) {
- r.pos(1, 1, 1).tex(sideActivity.getMinU, sideActivity.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(sideActivity.getMaxU, sideActivity.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(sideActivity.getMaxU, sideActivity.getMinV).endVertex()
- r.pos(1, 0, 1).tex(sideActivity.getMinU, sideActivity.getMinV).endVertex()
+ if (splitter.isSideOpen(Direction.EAST)) {
+ r.vertex(stack.last.pose, 1, 1, 1).uv(sideActivity.getU0, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(sideActivity.getU1, sideActivity.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(sideActivity.getU1, sideActivity.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(sideActivity.getU0, sideActivity.getV0).endVertex()
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/PowerDistributorRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/PowerDistributorRenderer.scala
index bd41d973b0..cf70b78788 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/PowerDistributorRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/PowerDistributorRenderer.scala
@@ -1,75 +1,68 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.opengl.GL11
-
-object PowerDistributorRenderer extends TileEntitySpecialRenderer[tileentity.PowerDistributor] {
- override def render(distributor: tileentity.PowerDistributor, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
- if (distributor.globalBuffer > 0) {
- RenderState.pushAttrib()
+object PowerDistributorRenderer extends Function[TileEntityRendererDispatcher, PowerDistributorRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new PowerDistributorRenderer(dispatch)
+}
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha((distributor.globalBuffer / distributor.globalBufferSize).toFloat)
+class PowerDistributorRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.PowerDistributor](dispatch) {
+ override def render(distributor: tileentity.PowerDistributor, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ if (distributor.globalBuffer > 0) {
+ stack.pushPose()
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
{
val icon = Textures.getSprite(Textures.Block.PowerDistributorTopOn)
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
{
val icon = Textures.getSprite(Textures.Block.PowerDistributorSideOn)
- r.pos(1, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(1, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 1, 1, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala
index fd562d3063..761349b031 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala
@@ -1,38 +1,42 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity.Printer
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.OpenGlHelper
+import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.renderer.RenderHelper
-import net.minecraft.client.renderer.block.model.ItemCameraTransforms
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
+import net.minecraft.client.renderer.model.ItemCameraTransforms
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.math.vector.Vector3f
+import org.lwjgl.opengl.GL13
+
+object PrinterRenderer extends Function[TileEntityRendererDispatcher, PrinterRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new PrinterRenderer(dispatch)
+}
-object PrinterRenderer extends TileEntitySpecialRenderer[Printer] {
- override def render(printer: Printer, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+class PrinterRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Printer](dispatch) {
+ override def render(printer: Printer, dt: Float, matrix: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
if (printer.data.stateOff.nonEmpty) {
val stack = printer.data.createItemStack()
- RenderState.pushAttrib()
- GlStateManager.pushMatrix()
-
- GlStateManager.translate(x + 0.5, y + 0.5 + 0.3, z + 0.5)
-
- GlStateManager.rotate((System.currentTimeMillis() % 20000) / 20000f * 360, 0, 1, 0)
- GlStateManager.scale(0.75, 0.75, 0.75)
+ matrix.pushPose()
+ matrix.translate(0.5, 0.5 + 0.3, 0.5)
- val brightness = printer.world.getCombinedLight(printer.getPos, 0)
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536)
+ matrix.mulPose(Vector3f.YP.rotationDegrees((System.currentTimeMillis() % 20000) / 20000f * 360))
+ matrix.scale(0.75f, 0.75f, 0.75f)
Textures.Block.bind()
- Minecraft.getMinecraft.getRenderItem.renderItem(stack, ItemCameraTransforms.TransformType.FIXED)
+ Minecraft.getInstance.getItemRenderer.renderStatic(stack, ItemCameraTransforms.TransformType.FIXED, light, overlay, matrix, buffer)
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ matrix.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/RackRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/RackRenderer.scala
index e916ae1a2a..ebdf3c26ca 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/RackRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/RackRenderer.scala
@@ -1,55 +1,58 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.api.event.RackMountableRenderEvent
import li.cil.oc.common.tileentity.Rack
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.util.EnumFacing
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3f
import net.minecraftforge.common.MinecraftForge
import org.lwjgl.opengl.GL11
-object RackRenderer extends TileEntitySpecialRenderer[Rack] {
+object RackRenderer extends Function[TileEntityRendererDispatcher, RackRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new RackRenderer(dispatch)
+}
+
+class RackRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Rack](dispatch) {
private final val vOffset = 2 / 16f
private final val vSize = 3 / 16f
- override def render(rack: Rack, x: Double, y: Double, z: Double, partialTicks: Float, destroyStage: Int, alpha: Float): Unit = {
+ override def render(rack: Rack, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- RenderState.pushAttrib()
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
+ stack.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
rack.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
- GlStateManager.translate(-0.5, 0.5, 0.505 - 0.5f / 16f)
- GlStateManager.scale(1, -1, 1)
+ stack.translate(-0.5, 0.5, 0.505 - 0.5f / 16f)
+ stack.scale(1, -1, 1)
// Note: we manually sync the rack inventory for this to work.
- for (i <- 0 until rack.getSizeInventory) {
- if (!rack.getStackInSlot(i).isEmpty) {
- GlStateManager.pushMatrix()
- RenderState.pushAttrib()
-
+ for (i <- 0 until rack.getContainerSize) {
+ if (!rack.getItem(i).isEmpty) {
val v0 = vOffset + i * vSize
val v1 = vOffset + (i + 1) * vSize
- val event = new RackMountableRenderEvent.TileEntity(rack, i, rack.lastData(i), v0, v1)
+ val event = new RackMountableRenderEvent.TileEntity(rack, i, rack.lastData(i), stack, buffer, light, overlay, v0, v1)
MinecraftForge.EVENT_BUS.post(event)
-
- RenderState.popAttrib()
- GlStateManager.popMatrix()
}
}
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/RaidRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/RaidRenderer.scala
index 83b3bbb33e..b4bb92dd4c 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/RaidRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/RaidRenderer.scala
@@ -1,72 +1,67 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Raid
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.BufferBuilder
+import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.renderer.texture.TextureAtlasSprite
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import org.lwjgl.opengl.GL11
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3f
-object RaidRenderer extends TileEntitySpecialRenderer[Raid] {
- override def render(raid: Raid, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+object RaidRenderer extends Function[TileEntityRendererDispatcher, RaidRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new RaidRenderer(dispatch)
+}
- RenderState.pushAttrib()
+class RaidRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Raid](dispatch) {
+ override def render(raid: Raid, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
+ stack.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
raid.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
- GlStateManager.translate(-0.5, 0.5, 0.505)
- GlStateManager.scale(1, -1, 1)
+ stack.translate(-0.5, 0.5, 0.505)
+ stack.scale(1, -1, 1)
- val t = Tessellator.getInstance
- val r = t.getBuffer
-
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
{
val icon = Textures.getSprite(Textures.Block.RaidFrontError)
- for (slot <- 0 until raid.getSizeInventory) {
+ for (slot <- 0 until raid.getContainerSize) {
if (!raid.presence(slot)) {
- renderSlot(r, slot, icon)
+ renderSlot(stack, r, slot, icon)
}
}
}
{
val icon = Textures.getSprite(Textures.Block.RaidFrontActivity)
- for (slot <- 0 until raid.getSizeInventory) {
- if (System.currentTimeMillis() - raid.lastAccess < 400 && raid.world.rand.nextDouble() > 0.1 && slot == raid.lastAccess % raid.getSizeInventory) {
- renderSlot(r, slot, icon)
+ for (slot <- 0 until raid.getContainerSize) {
+ if (System.currentTimeMillis() - raid.lastAccess < 400 && raid.world.random.nextDouble() > 0.1 && slot == raid.lastAccess % raid.getContainerSize) {
+ renderSlot(stack, r, slot, icon)
}
}
}
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
@@ -74,12 +69,12 @@ object RaidRenderer extends TileEntitySpecialRenderer[Raid] {
private val u1 = 2 / 16f
private val fs = 4 / 16f
- private def renderSlot(r: BufferBuilder, slot: Int, icon: TextureAtlasSprite) {
+ private def renderSlot(stack: MatrixStack, r: IVertexBuilder, slot: Int, icon: TextureAtlasSprite) {
val l = u1 + slot * fs
val h = u1 + (slot + 1) * fs
- r.pos(l, 1, 0).tex(icon.getInterpolatedU(l * 16), icon.getMaxV).endVertex()
- r.pos(h, 1, 0).tex(icon.getInterpolatedU(h * 16), icon.getMaxV).endVertex()
- r.pos(h, 0, 0).tex(icon.getInterpolatedU(h * 16), icon.getMinV).endVertex()
- r.pos(l, 0, 0).tex(icon.getInterpolatedU(l * 16), icon.getMinV).endVertex()
+ r.vertex(stack.last.pose, l, 1, 0).uv(icon.getU(l * 16), icon.getV1).endVertex()
+ r.vertex(stack.last.pose, h, 1, 0).uv(icon.getU(h * 16), icon.getV1).endVertex()
+ r.vertex(stack.last.pose, h, 0, 0).uv(icon.getU(h * 16), icon.getV0).endVertex()
+ r.vertex(stack.last.pose, l, 0, 0).uv(icon.getU(l * 16), icon.getV0).endVertex()
}
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/RelayRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/RelayRenderer.scala
index ca447b2afb..efab260d61 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/RelayRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/RelayRenderer.scala
@@ -1,66 +1,59 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.opengl.GL11
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+
+object RelayRenderer extends Function[TileEntityRendererDispatcher, RelayRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new RelayRenderer(dispatch)
+}
-object RelayRenderer extends TileEntitySpecialRenderer[tileentity.Relay] {
- override def render(switch: tileentity.Relay, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+class RelayRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.Relay](dispatch) {
+ override def render(switch: tileentity.Relay, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+ RenderSystem.color4f(1, 1, 1, 1)
+
val activity = math.max(0, 1 - (System.currentTimeMillis() - switch.lastMessage) / 1000.0)
if (activity > 0) {
- RenderState.pushAttrib()
-
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(activity.toFloat)
-
- GlStateManager.pushMatrix()
-
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ stack.pushPose()
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
val icon = Textures.getSprite(Textures.Block.SwitchSideOn)
- r.pos(1, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(1, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 1, 1, 1).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
+
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala
index 3af604a955..b52d6ce108 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala
@@ -1,12 +1,16 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
import com.google.common.base.Strings
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.driver.item.UpgradeRenderer
import li.cil.oc.api.driver.item.UpgradeRenderer.MountPointName
import li.cil.oc.api.event.RobotRenderEvent
-import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.EventHandler
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
@@ -14,29 +18,35 @@ import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer._
-import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType
-import net.minecraft.client.renderer.entity.RenderLivingBase
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
+import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.client.renderer.vertex.VertexFormat
-import net.minecraft.client.renderer.vertex.VertexFormatElement
-import net.minecraft.init.Items
-import net.minecraft.item.ItemBlock
+import net.minecraft.item.Items
+import net.minecraft.item.BlockItem
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.Vec3d
+import net.minecraft.util.Direction
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.util.math.vector.Vector3f
+import net.minecraft.util.math.vector.Matrix3f
import net.minecraft.util.text.TextFormatting
-import net.minecraftforge.client.MinecraftForgeClient
+import net.minecraftforge.client.ForgeHooksClient
import net.minecraftforge.common.MinecraftForge
-import org.lwjgl.opengl.GL11
-import scala.collection.convert.WrapAsJava._
import scala.collection.mutable
+import scala.jdk.CollectionConverters._
import scala.language.implicitConversions
-object RobotRenderer extends TileEntitySpecialRenderer[tileentity.RobotProxy] {
- private val displayList = GLAllocation.generateDisplayLists(2)
+object RobotRenderer extends Function[TileEntityRendererDispatcher, RobotRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new RobotRenderer(dispatch)
+
+ private val instance = new RobotRenderer(null)
+ def renderChassis(stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, offset: Double = 0, isRunningOverride: Boolean = false) =
+ instance.renderChassis(stack, buffer, light, null, offset, isRunningOverride)
+}
+
+class RobotRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.RobotProxy](dispatch) {
private val mountPoints = new Array[RobotRenderEvent.MountPoint](7)
private val slotNameMapping = Map(
@@ -60,88 +70,71 @@ object RobotRenderer extends TileEntitySpecialRenderer[tileentity.RobotProxy] {
private val gt = 0.5f + gap
private val gb = 0.5f - gap
- // https://github.com/MinecraftForge/MinecraftForge/issues/2321
- val POSITION_TEX_NORMALF = new VertexFormat()
- val NORMAL_3F = new VertexFormatElement(0, VertexFormatElement.EnumType.FLOAT, VertexFormatElement.EnumUsage.NORMAL, 3)
- POSITION_TEX_NORMALF.addElement(DefaultVertexFormats.POSITION_3F)
- POSITION_TEX_NORMALF.addElement(DefaultVertexFormats.TEX_2F)
- POSITION_TEX_NORMALF.addElement(NORMAL_3F)
-
- private implicit def extendWorldRenderer(self: BufferBuilder): ExtendedWorldRenderer = new ExtendedWorldRenderer(self)
+ private implicit def extendWorldRenderer(self: IVertexBuilder): ExtendedWorldRenderer = new ExtendedWorldRenderer(self)
- private class ExtendedWorldRenderer(val buffer: BufferBuilder) {
- def normal(normal: Vec3d): BufferBuilder = {
+ private class ExtendedWorldRenderer(val buffer: IVertexBuilder) {
+ def normal(matrix: Matrix3f, normal: Vector3d): IVertexBuilder = {
val normalized = normal.normalize()
- buffer.normal(normalized.x.toFloat, normalized.y.toFloat, normalized.z.toFloat)
+ buffer.normal(matrix, normalized.x.toFloat, normalized.y.toFloat, normalized.z.toFloat)
}
}
- private def drawTop(): Unit = {
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ private def drawTop(stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, red: Int, green: Int, blue: Int): Unit = {
+ val r = buffer.getBuffer(RenderTypes.ROBOT_CHASSIS)
- r.begin(GL11.GL_TRIANGLE_FAN, POSITION_TEX_NORMALF)
+ r.vertex(stack.last.pose, 0.5f, 1, 0.5f).color(red, green, blue, 0xFF).uv(0.25f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, l, gt, h).color(red, green, blue, 0xFF).uv(0, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gt, h).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
- r.pos(0.5f, 1, 0.5f).tex(0.25f, 0.25f).normal(new Vec3d(0, 0.2, 1)).endVertex()
- r.pos(l, gt, h).tex(0, 0.5f).normal(new Vec3d(0, 0.2, 1)).endVertex()
- r.pos(h, gt, h).tex(0.5f, 0.5f).normal(new Vec3d(0, 0.2, 1)).endVertex()
- r.pos(h, gt, l).tex(0.5f, 0).normal(new Vec3d(1, 0.2, 0)).endVertex()
- r.pos(l, gt, l).tex(0, 0).normal(new Vec3d(0, 0.2, -1)).endVertex()
- r.pos(l, gt, h).tex(0, 0.5f).normal(new Vec3d(-1, 0.2, 0)).endVertex()
+ r.vertex(stack.last.pose, 0.5f, 1, 0.5f).color(red, green, blue, 0xFF).uv(0.25f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gt, h).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gt, l).color(red, green, blue, 0xFF).uv(0.5f, 0).uv2(light).normal(stack.last.normal, new Vector3d(1, 0.2, 0)).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, 0.5f, 1, 0.5f).color(red, green, blue, 0xFF).uv(0.25f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gt, l).color(red, green, blue, 0xFF).uv(0.5f, 0).uv2(light).normal(stack.last.normal, new Vector3d(1, 0.2, 0)).endVertex()
+ r.vertex(stack.last.pose, l, gt, l).color(red, green, blue, 0xFF).uv(0, 0).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, -1)).endVertex()
- r.begin(GL11.GL_QUADS, POSITION_TEX_NORMALF)
+ r.vertex(stack.last.pose, 0.5f, 1, 0.5f).color(red, green, blue, 0xFF).uv(0.25f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, l, gt, l).color(red, green, blue, 0xFF).uv(0, 0).uv2(light).normal(stack.last.normal, new Vector3d(0, 0.2, -1)).endVertex()
+ r.vertex(stack.last.pose, l, gt, h).color(red, green, blue, 0xFF).uv(0, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(-1, 0.2, 0)).endVertex()
- r.pos(l, gt, h).tex(0, 1).normal(0, -1, 0).endVertex()
- r.pos(l, gt, l).tex(0, 0.5).normal(0, -1, 0).endVertex()
- r.pos(h, gt, l).tex(0.5, 0.5).normal(0, -1, 0).endVertex()
- r.pos(h, gt, h).tex(0.5, 1).normal(0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, l, gt, h).color(red, green, blue, 0xFF).uv(0, 1).uv2(light).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, l, gt, l).color(red, green, blue, 0xFF).uv(0, 0.5f).uv2(light).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, h, gt, l).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, 0, -1, 0).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, l, gt, h).color(red, green, blue, 0xFF).uv(0, 1).uv2(light).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, h, gt, l).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, 0, -1, 0).endVertex()
+ r.vertex(stack.last.pose, h, gt, h).color(red, green, blue, 0xFF).uv(0.5f, 1).uv2(light).normal(stack.last.normal, 0, -1, 0).endVertex()
}
- private def drawBottom(): Unit = {
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ private def drawBottom(stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, red: Int, green: Int, blue: Int): Unit = {
+ val r = buffer.getBuffer(RenderTypes.ROBOT_CHASSIS)
- r.begin(GL11.GL_TRIANGLE_FAN, POSITION_TEX_NORMALF)
+ r.vertex(stack.last.pose, 0.5f, 0.03f, 0.5f).color(red, green, blue, 0xFF).uv(0.75f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, l, gb, l).color(red, green, blue, 0xFF).uv(0.5f, 0).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gb, l).color(red, green, blue, 0xFF).uv(1, 0).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
- r.pos(0.5f, 0.03f, 0.5f).tex(0.75f, 0.25f).normal(new Vec3d(0, -0.2, 1)).endVertex()
- r.pos(l, gb, l).tex(0.5f, 0).normal(new Vec3d(0, -0.2, 1)).endVertex()
- r.pos(h, gb, l).tex(1, 0).normal(new Vec3d(0, -0.2, 1)).endVertex()
- r.pos(h, gb, h).tex(1, 0.5f).normal(new Vec3d(1, -0.2, 0)).endVertex()
- r.pos(l, gb, h).tex(0.5f, 0.5f).normal(new Vec3d(0, -0.2, -1)).endVertex()
- r.pos(l, gb, l).tex(0.5f, 0).normal(new Vec3d(-1, -0.2, 0)).endVertex()
+ r.vertex(stack.last.pose, 0.5f, 0.03f, 0.5f).color(red, green, blue, 0xFF).uv(0.75f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gb, l).color(red, green, blue, 0xFF).uv(1, 0).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gb, h).color(red, green, blue, 0xFF).uv(1, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(1, -0.2, 0)).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, 0.5f, 0.03f, 0.5f).color(red, green, blue, 0xFF).uv(0.75f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, h, gb, h).color(red, green, blue, 0xFF).uv(1, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(1, -0.2, 0)).endVertex()
+ r.vertex(stack.last.pose, l, gb, h).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, -1)).endVertex()
- r.begin(GL11.GL_QUADS, POSITION_TEX_NORMALF)
+ r.vertex(stack.last.pose, 0.5f, 0.03f, 0.5f).color(red, green, blue, 0xFF).uv(0.75f, 0.25f).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, 1)).endVertex()
+ r.vertex(stack.last.pose, l, gb, h).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, new Vector3d(0, -0.2, -1)).endVertex()
+ r.vertex(stack.last.pose, l, gb, l).color(red, green, blue, 0xFF).uv(0.5f, 0).uv2(light).normal(stack.last.normal, new Vector3d(-1, -0.2, 0)).endVertex()
- r.pos(l, gb, l).tex(0, 0.5).normal(0, 1, 0).endVertex()
- r.pos(l, gb, h).tex(0, 1).normal(0, 1, 0).endVertex()
- r.pos(h, gb, h).tex(0.5, 1).normal(0, 1, 0).endVertex()
- r.pos(h, gb, l).tex(0.5, 0.5).normal(0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, l, gb, l).color(red, green, blue, 0xFF).uv(0, 0.5f).uv2(light).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, l, gb, h).color(red, green, blue, 0xFF).uv(0, 1).uv2(light).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, h, gb, h).color(red, green, blue, 0xFF).uv(0.5f, 1).uv2(light).normal(stack.last.normal, 0, 1, 0).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, l, gb, l).color(red, green, blue, 0xFF).uv(0, 0.5f).uv2(light).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, h, gb, h).color(red, green, blue, 0xFF).uv(0.5f, 1).uv2(light).normal(stack.last.normal, 0, 1, 0).endVertex()
+ r.vertex(stack.last.pose, h, gb, l).color(red, green, blue, 0xFF).uv(0.5f, 0.5f).uv2(light).normal(stack.last.normal, 0, 1, 0).endVertex()
}
- def compileList() {
- GL11.glNewList(displayList, GL11.GL_COMPILE)
-
- drawTop()
-
- GL11.glEndList()
-
- GL11.glNewList(displayList + 1, GL11.GL_COMPILE)
-
- drawBottom()
-
- GL11.glEndList()
- }
-
- compileList()
-
def resetMountPoints(running: Boolean) {
val offset = if (running) 0 else -0.06f
@@ -209,7 +202,7 @@ object RobotRenderer extends TileEntitySpecialRenderer[tileentity.RobotProxy] {
mountPoints(6).rotation.setW(0)
}
- def renderChassis(robot: tileentity.Robot = null, offset: Double = 0, isRunningOverride: Boolean = false) {
+ def renderChassis(stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, robot: tileentity.Robot = null, offset: Double = 0, isRunningOverride: Boolean = false) {
val isRunning = if (robot == null) isRunningOverride else robot.isRunning
val size = 0.3f
@@ -229,277 +222,209 @@ object RobotRenderer extends TileEntitySpecialRenderer[tileentity.RobotProxy] {
val event = new RobotRenderEvent(robot, mountPoints)
MinecraftForge.EVENT_BUS.post(event)
if (!event.isCanceled) {
- bindTexture(Textures.Model.Robot)
+ val color = event.getColorMultiplier
+ val (cr, cg, cb) = ((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
if (!isRunning) {
- GlStateManager.translate(0, -2 * gap, 0)
+ stack.translate(0, -2 * gap, 0)
}
- //GlStateManager.callList(displayList + 1)
- drawBottom()
+ drawBottom(stack, buffer, light, cr, cg, cb)
if (!isRunning) {
- GlStateManager.translate(0, -2 * gap, 0)
+ stack.translate(0, -2 * gap, 0)
}
-
- if (MinecraftForgeClient.getRenderPass > 0) return
-
- //GlStateManager.callList(displayList)
- drawTop()
- GlStateManager.color(1, 1, 1)
+ drawTop(stack, buffer, light, cr, cg, cb)
if (isRunning) {
- RenderState.disableEntityLighting()
-
- {
- // Additive blending for the light.
- RenderState.makeItBlend()
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE)
- // Light color.
- val lightColor = if (robot != null && robot.info != null) robot.info.lightColor else 0xF23030
- val r = (lightColor >>> 16) & 0xFF
- val g = (lightColor >>> 8) & 0xFF
- val b = (lightColor >>> 0) & 0xFF
- GlStateManager.color(r / 255f, g / 255f, b / 255f)
- }
-
- val t = Tessellator.getInstance
- val r = t.getBuffer
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(l, gt, l).tex(u0, v0).endVertex()
- r.pos(l, gb, l).tex(u0, v1).endVertex()
- r.pos(l, gb, h).tex(u1, v1).endVertex()
- r.pos(l, gt, h).tex(u1, v0).endVertex()
-
- r.pos(l, gt, h).tex(u0, v0).endVertex()
- r.pos(l, gb, h).tex(u0, v1).endVertex()
- r.pos(h, gb, h).tex(u1, v1).endVertex()
- r.pos(h, gt, h).tex(u1, v0).endVertex()
-
- r.pos(h, gt, h).tex(u0, v0).endVertex()
- r.pos(h, gb, h).tex(u0, v1).endVertex()
- r.pos(h, gb, l).tex(u1, v1).endVertex()
- r.pos(h, gt, l).tex(u1, v0).endVertex()
-
- r.pos(h, gt, l).tex(u0, v0).endVertex()
- r.pos(h, gb, l).tex(u0, v1).endVertex()
- r.pos(l, gb, l).tex(u1, v1).endVertex()
- r.pos(l, gt, l).tex(u1, v0).endVertex()
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
+ // Light color.
+ val lightColor = if (event.lightColor < 0) {
+ if (robot != null && robot.info != null) robot.info.lightColor else 0xF23030
+ } else event.lightColor & 0xFFFFFF
+ val red = (lightColor >>> 16) & 0xFF
+ val green = (lightColor >>> 8) & 0xFF
+ val blue = (lightColor >>> 0) & 0xFF
+
+ val r = buffer.getBuffer(RenderTypes.ROBOT_LIGHT)
+ r.vertex(stack.last.pose, l, gt, l).color(red, green, blue, 0xFF).uv(u0, v0).endVertex()
+ r.vertex(stack.last.pose, l, gb, l).color(red, green, blue, 0xFF).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, l, gb, h).color(red, green, blue, 0xFF).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, l, gt, h).color(red, green, blue, 0xFF).uv(u1, v0).endVertex()
+
+ r.vertex(stack.last.pose, l, gt, h).color(red, green, blue, 0xFF).uv(u0, v0).endVertex()
+ r.vertex(stack.last.pose, l, gb, h).color(red, green, blue, 0xFF).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, h, gb, h).color(red, green, blue, 0xFF).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, h, gt, h).color(red, green, blue, 0xFF).uv(u1, v0).endVertex()
+
+ r.vertex(stack.last.pose, h, gt, h).color(red, green, blue, 0xFF).uv(u0, v0).endVertex()
+ r.vertex(stack.last.pose, h, gb, h).color(red, green, blue, 0xFF).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, h, gb, l).color(red, green, blue, 0xFF).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, h, gt, l).color(red, green, blue, 0xFF).uv(u1, v0).endVertex()
+
+ r.vertex(stack.last.pose, h, gt, l).color(red, green, blue, 0xFF).uv(u0, v0).endVertex()
+ r.vertex(stack.last.pose, h, gb, l).color(red, green, blue, 0xFF).uv(u0, v1).endVertex()
+ r.vertex(stack.last.pose, l, gb, l).color(red, green, blue, 0xFF).uv(u1, v1).endVertex()
+ r.vertex(stack.last.pose, l, gt, l).color(red, green, blue, 0xFF).uv(u1, v0).endVertex()
}
- GlStateManager.color(1, 1, 1, 1)
}
}
- override def render(proxy: tileentity.RobotProxy, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+ override def render(proxy: tileentity.RobotProxy, f: Float, matrix: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
val robot = proxy.robot
- val worldTime = robot.getWorld.getTotalWorldTime + f
+ val worldTime = proxy.getLevel.getGameTime + f
- GlStateManager.pushMatrix()
- RenderState.pushAttrib()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ matrix.pushPose()
+
+ matrix.translate(0.5, 0.5, 0.5)
// If the move started while we were rendering and we have a reference to
// the *old* proxy the robot would be rendered at the wrong position, so we
// correct for the offset.
if (robot.proxy != proxy) {
- GlStateManager.translate(robot.proxy.x - proxy.x, robot.proxy.y - proxy.y, robot.proxy.z - proxy.z)
+ matrix.translate(robot.proxy.x - proxy.x, robot.proxy.y - proxy.y, robot.proxy.z - proxy.z)
}
if (robot.isAnimatingMove) {
val remaining = (robot.animationTicksLeft - f) / robot.animationTicksTotal.toDouble
- val delta = robot.moveFrom.get.subtract(robot.getPos)
- GlStateManager.translate(delta.getX * remaining, delta.getY * remaining, delta.getZ * remaining)
+ val delta = robot.moveFrom.get.subtract(robot.getBlockPos)
+ matrix.translate(delta.getX * remaining, delta.getY * remaining, delta.getZ * remaining)
}
val timeJitter = robot.hashCode ^ 0xFF
val hover =
if (robot.isRunning) (Math.sin(timeJitter + worldTime / 20.0) * 0.03).toFloat
else -0.03f
- GlStateManager.translate(0, hover, 0)
-
- GlStateManager.pushMatrix()
+ matrix.translate(0, hover, 0)
- GlStateManager.depthMask(true)
- RenderState.enableEntityLighting()
- GlStateManager.disableBlend()
+ matrix.pushPose()
if (robot.isAnimatingTurn) {
val remaining = (robot.animationTicksLeft - f) / robot.animationTicksTotal.toFloat
- GlStateManager.rotate(90 * remaining, 0, robot.turnAxis, 0)
+ val axis = if (robot.turnAxis < 0) Vector3f.YN else Vector3f.YP
+ matrix.mulPose(axis.rotationDegrees(90 * remaining))
}
robot.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => matrix.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => matrix.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => matrix.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ matrix.translate(-0.5f, -0.5f, -0.5f)
val offset = timeJitter + worldTime / 20.0
- renderChassis(robot, offset)
+ renderChassis(matrix, buffer, light, robot, offset)
- if (MinecraftForgeClient.getRenderPass == 0 && !robot.renderingErrored && x * x + y * y + z * z < 24 * 24) {
- val itemRenderer = Minecraft.getMinecraft.getItemRenderer
- StackOption(robot.getStackInSlot(0)) match {
+ val pos = proxy.getBlockPos
+ val dist = Minecraft.getInstance.player.position.distanceToSqr(pos.getX + 0.5, pos.getY + 0.5, pos.getZ + 0.5)
+ if (!robot.renderingErrored && dist < 24 * 24) {
+ val itemRenderer = Minecraft.getInstance.getItemRenderer
+ StackOption(robot.getItem(0)) match {
case SomeStack(stack) =>
- RenderState.pushAttrib()
- GlStateManager.pushMatrix()
+ matrix.pushPose()
try {
// Copy-paste from player render code, with minor adjustments for
// robot scale.
- GlStateManager.disableCull()
- GlStateManager.enableRescaleNormal()
-
- GlStateManager.scale(1, -1, -1)
- GlStateManager.translate(0, -8 * 0.0625F - 0.0078125F, -0.5F)
+ matrix.scale(1, -1, -1)
+ matrix.translate(0, -8 * 0.0625F - 0.0078125F, -0.5F)
if (robot.isAnimatingSwing) {
val wantedTicksPerCycle = 10
val cycles = math.max(robot.animationTicksTotal / wantedTicksPerCycle, 1)
val ticksPerCycle = robot.animationTicksTotal / cycles
val remaining = (robot.animationTicksLeft - f) / ticksPerCycle.toDouble
- GlStateManager.rotate((Math.sin((remaining - remaining.toInt) * Math.PI) * 45).toFloat, 1, 0, 0)
+ matrix.mulPose(Vector3f.XP.rotationDegrees((Math.sin((remaining - remaining.toInt) * Math.PI) * 45).toFloat))
}
val item = stack.getItem
- if (item.isInstanceOf[ItemBlock]) {
- GlStateManager.rotate(-90.0F, 1.0F, 0.0F, 0.0F)
- GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F)
+ if (item.isInstanceOf[BlockItem]) {
+ matrix.mulPose(Vector3f.XP.rotationDegrees(180.0F))
+ matrix.mulPose(Vector3f.YP.rotationDegrees(90.0F))
val scale = 0.625F
- GlStateManager.scale(scale, scale, scale)
+ matrix.scale(scale, scale, scale)
}
else if (item == Items.BOW) {
- GlStateManager.translate(1.5f/16f, -0.125F, -0.125F)
- GlStateManager.rotate(10.0F, 0.0F, 0.0F, 1.0F)
- val scale = 0.625F
- GlStateManager.scale(scale, -scale, scale)
- }
- else if (item.isFull3D) {
- if (item.shouldRotateAroundWhenRendering) {
- GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F)
- GlStateManager.translate(0.0F, -0.0625F, 0.0F)
- }
-
- GlStateManager.translate(0.0F, 0.1875F, 0.0F)
- GlStateManager.translate(0.0625F, -0.125F, -2/16F)
+ matrix.translate(0, -3f/16f, -0.125F)
+ matrix.mulPose(Vector3f.ZP.rotationDegrees(170.0F))
val scale = 0.625F
- GlStateManager.scale(scale, -scale, scale)
- GlStateManager.rotate(0.0F, 1.0F, 0.0F, 0.0F)
- GlStateManager.rotate(0.0F, 0.0F, 1.0F, 0.0F)
+ matrix.scale(scale, scale, scale)
}
else {
- GlStateManager.translate(0, 2f/16f, 0)
- val scale = 0.875F
- GlStateManager.scale(scale, scale, scale)
- GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F)
- GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F)
+ matrix.translate(1f/16f, 1f/16f, -2f/16f)
+ val scale = 0.625F
+ matrix.scale(scale, scale, scale)
+ matrix.mulPose(Vector3f.ZP.rotationDegrees(180.0F))
}
- itemRenderer.renderItem(Minecraft.getMinecraft.player, stack, TransformType.THIRD_PERSON_RIGHT_HAND)
+ itemRenderer.renderStatic(Minecraft.getInstance.player, stack, TransformType.THIRD_PERSON_RIGHT_HAND, false, matrix, buffer, proxy.getLevel, light, overlay)
}
catch {
case e: Throwable =>
OpenComputers.log.warn("Failed rendering equipped item.", e)
robot.renderingErrored = true
}
- GlStateManager.enableCull()
- GlStateManager.disableRescaleNormal()
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ matrix.popPose()
case _ =>
}
- if (MinecraftForgeClient.getRenderPass == 0) {
- lazy val availableSlots = slotNameMapping.keys.to[mutable.Set]
- lazy val wildcardRenderers = mutable.Buffer.empty[(ItemStack, UpgradeRenderer)]
- lazy val slotMapping = Array.fill(mountPoints.length)(null: (ItemStack, UpgradeRenderer))
+ lazy val availableSlots = slotNameMapping.keys.to(mutable.Set).asJava
+ lazy val wildcardRenderers = mutable.Buffer.empty[(ItemStack, UpgradeRenderer)]
+ lazy val slotMapping = Array.fill(mountPoints.length)(null: (ItemStack, UpgradeRenderer))
- val renderers = (robot.componentSlots ++ robot.containerSlots).map(robot.getStackInSlot).
- collect { case stack if !stack.isEmpty && stack.getItem.isInstanceOf[UpgradeRenderer] => (stack, stack.getItem.asInstanceOf[UpgradeRenderer]) }
+ val renderers = (robot.componentSlots ++ robot.containerSlots).map(robot.getItem).
+ collect { case stack if !stack.isEmpty && stack.getItem.isInstanceOf[UpgradeRenderer] => (stack, stack.getItem.asInstanceOf[UpgradeRenderer]) }
- for ((stack, renderer) <- renderers) {
- val preferredSlot = renderer.computePreferredMountPoint(stack, robot, availableSlots)
- if (availableSlots.remove(preferredSlot)) {
- slotMapping(slotNameMapping(preferredSlot)) = (stack, renderer)
- }
- else if (preferredSlot == MountPointName.Any) {
- wildcardRenderers += ((stack, renderer))
- }
+ for ((stack, renderer) <- renderers) {
+ val preferredSlot = renderer.computePreferredMountPoint(stack, robot, availableSlots)
+ if (availableSlots.remove(preferredSlot)) {
+ slotMapping(slotNameMapping(preferredSlot)) = (stack, renderer)
}
-
- var firstEmpty = slotMapping.indexOf(null)
- for (entry <- wildcardRenderers if firstEmpty >= 0) {
- slotMapping(firstEmpty) = entry
- firstEmpty = slotMapping.indexOf(null)
+ else if (preferredSlot == MountPointName.Any) {
+ wildcardRenderers += ((stack, renderer))
}
+ }
- for ((info, mountPoint) <- (slotMapping, mountPoints).zipped if info != null) try {
- val (stack, renderer) = info
- GlStateManager.pushMatrix()
- GlStateManager.translate(0.5f, 0.5f, 0.5f)
- renderer.render(stack, mountPoint, robot, f)
- GlStateManager.popMatrix()
- }
- catch {
- case e: Throwable =>
- OpenComputers.log.warn("Failed rendering equipped upgrade.", e)
- robot.renderingErrored = true
- }
+ var firstEmpty = slotMapping.indexOf(null)
+ for (entry <- wildcardRenderers if firstEmpty >= 0) {
+ slotMapping(firstEmpty) = entry
+ firstEmpty = slotMapping.indexOf(null)
+ }
+
+ for ((info, mountPoint) <- (slotMapping, mountPoints).zipped if info != null) try {
+ val (stack, renderer) = info
+ matrix.pushPose()
+ matrix.translate(0.5f, 0.5f, 0.5f)
+ renderer.render(matrix, buffer, stack, mountPoint, robot, f)
+ matrix.popPose()
+ }
+ catch {
+ case e: Throwable =>
+ OpenComputers.log.warn("Failed rendering equipped upgrade.", e)
+ robot.renderingErrored = true
}
}
- GlStateManager.popMatrix()
+ matrix.popPose()
val name = robot.name
- if (Settings.get.robotLabels && MinecraftForgeClient.getRenderPass == 1 && !Strings.isNullOrEmpty(name) && x * x + y * y + z * z < RenderLivingBase.NAME_TAG_RANGE) {
- GlStateManager.pushMatrix()
-
+ if (Settings.get.robotLabels && !Strings.isNullOrEmpty(name) && ForgeHooksClient.isNameplateInRenderDistance(null, dist)) {
// This is pretty much copy-pasta from the entity's label renderer.
- val t = Tessellator.getInstance
- val r = t.getBuffer
- val f = getFontRenderer
+ val f = Minecraft.getInstance.font
val scale = 1.6f / 60f
- val width = f.getStringWidth(name)
+ val width = f.width(name)
val halfWidth = width / 2
+ val bgColor = (255f * Minecraft.getInstance.options.getBackgroundOpacity(0.25F)).asInstanceOf[Int] << 24
- GlStateManager.translate(0, 0.8, 0)
- GL11.glNormal3f(0, 1, 0)
- GlStateManager.color(1, 1, 1)
-
- GlStateManager.rotate(-rendererDispatcher.entityYaw, 0, 1, 0)
- GlStateManager.rotate(rendererDispatcher.entityPitch, 1, 0, 0)
- GlStateManager.scale(-scale, -scale, scale)
-
- RenderState.makeItBlend()
- GlStateManager.depthMask(false)
- GlStateManager.disableLighting()
- GlStateManager.disableTexture2D()
-
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR)
- r.pos(-halfWidth - 1, -1, 0).color(0, 0, 0, 0.5f).endVertex()
- r.pos(-halfWidth - 1, 8, 0).color(0, 0, 0, 0.5f).endVertex()
- r.pos(halfWidth + 1, 8, 0).color(0, 0, 0, 0.5f).endVertex()
- r.pos(halfWidth + 1, -1, 0).color(0, 0, 0, 0.5f).endVertex()
- t.draw()
-
- GlStateManager.enableTexture2D() // For the font.
- f.drawString((if (EventHandler.isItTime) TextFormatting.OBFUSCATED.toString else "") + name, -halfWidth, 0, 0xFFFFFFFF)
-
- GlStateManager.depthMask(true)
- GlStateManager.enableLighting()
- RenderState.disableBlend()
+ matrix.translate(0, 0.8, 0)
+ matrix.mulPose(Minecraft.getInstance.getEntityRenderDispatcher.cameraOrientation)
+ matrix.scale(-scale, -scale, scale)
- GlStateManager.popMatrix()
+ f.drawInBatch((if (EventHandler.isItTime) TextFormatting.OBFUSCATED.toString else "") + name,
+ -halfWidth, 0, -1, false, matrix.last.pose, buffer, false, bgColor, light)
}
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ matrix.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/ScreenRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/ScreenRenderer.scala
index 0beb9af08b..0faec2772e 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/ScreenRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/ScreenRenderer.scala
@@ -1,24 +1,31 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity.Screen
import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.OpenGlHelper
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.util.EnumFacing
-import org.lwjgl.opengl.GL11
-import org.lwjgl.opengl.GL14
-import org.lwjgl.opengl.GLContext
-
-object ScreenRenderer extends TileEntitySpecialRenderer[Screen] {
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
+import net.minecraft.util.math.vector.Vector3f
+
+object ScreenRenderer extends Function[TileEntityRendererDispatcher, ScreenRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new ScreenRenderer(dispatch)
+}
+
+class ScreenRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[Screen](dispatch) {
private val maxRenderDistanceSq = Settings.get.maxScreenTextRenderDistance * Settings.get.maxScreenTextRenderDistance
private val fadeDistanceSq = Settings.get.screenTextFadeStartDistance * Settings.get.screenTextFadeStartDistance
@@ -32,13 +39,11 @@ object ScreenRenderer extends TileEntitySpecialRenderer[Screen] {
api.Items.get(Constants.BlockName.ScreenTier2),
api.Items.get(Constants.BlockName.ScreenTier3))
- private val canUseBlendColor = GLContext.getCapabilities.OpenGL14
-
// ----------------------------------------------------------------------- //
// Rendering
// ----------------------------------------------------------------------- //
- override def render(screen: Screen, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
+ override def render(screen: Screen, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
this.screen = screen
@@ -51,111 +56,85 @@ object ScreenRenderer extends TileEntitySpecialRenderer[Screen] {
return
}
- // y = block.bottom - player.feet
- // eye is higher, so the y delta should be more negative
- val eye_delta: Double = y - Minecraft.getMinecraft.player.getEyeHeight
+ val eye_pos = Minecraft.getInstance.player.getEyePosition(dt)
+ val eye_delta: Double = screen.getBlockPos.getY - eye_pos.y
// Crude check whether screen text can be seen by the local player based
// on the player's position -> angle relative to screen.
val screenFacing = screen.facing.getOpposite
- if (screenFacing.getFrontOffsetX * (x + 0.5) + screenFacing.getFrontOffsetY * (eye_delta + 0.5) + screenFacing.getFrontOffsetZ * (z + 0.5) < 0) {
+ val x = screen.getBlockPos.getX - eye_pos.x
+ val z = screen.getBlockPos.getZ - eye_pos.z
+ if (screenFacing.getStepX * (x + 0.5) + screenFacing.getStepY * (eye_delta + 0.5) + screenFacing.getStepZ * (z + 0.5) < 0) {
return
}
- RenderState.checkError(getClass.getName + ".render: checks")
-
- RenderState.pushAttrib()
-
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 0xFF, 0xFF)
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- GlStateManager.color(1, 1, 1, 1)
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.pushMatrix()
+ stack.pushPose()
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
+ stack.translate(0.5, 0.5, 0.5)
RenderState.checkError(getClass.getName + ".render: setup")
- drawOverlay()
+ drawOverlay(stack, buffer.getBuffer(RenderTypes.BLOCK_OVERLAY))
RenderState.checkError(getClass.getName + ".render: overlay")
- if (distance > fadeDistanceSq) {
- val alpha = math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat)
- if (canUseBlendColor) {
- GL14.glBlendColor(0, 0, 0, alpha)
- GlStateManager.blendFunc(GL11.GL_CONSTANT_ALPHA, GL11.GL_ONE)
- }
- }
+ val alpha = if (distance > fadeDistanceSq) math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat) else 1f
RenderState.checkError(getClass.getName + ".render: fade")
if (screen.buffer.isRenderingEnabled) {
- draw()
+ draw(stack, alpha, buffer)
}
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ stack.popPose()
RenderState.checkError(getClass.getName + ".render: leaving")
}
- private def transform() {
+ private def transform(stack: MatrixStack) {
screen.yaw match {
- case EnumFacing.WEST => GlStateManager.rotate(-90, 0, 1, 0)
- case EnumFacing.NORTH => GlStateManager.rotate(180, 0, 1, 0)
- case EnumFacing.EAST => GlStateManager.rotate(90, 0, 1, 0)
+ case Direction.WEST => stack.mulPose(Vector3f.YP.rotationDegrees(-90))
+ case Direction.NORTH => stack.mulPose(Vector3f.YP.rotationDegrees(180))
+ case Direction.EAST => stack.mulPose(Vector3f.YP.rotationDegrees(90))
case _ => // No yaw.
}
screen.pitch match {
- case EnumFacing.DOWN => GlStateManager.rotate(90, 1, 0, 0)
- case EnumFacing.UP => GlStateManager.rotate(-90, 1, 0, 0)
+ case Direction.DOWN => stack.mulPose(Vector3f.XP.rotationDegrees(90))
+ case Direction.UP => stack.mulPose(Vector3f.XP.rotationDegrees(-90))
case _ => // No pitch.
}
// Fit area to screen (bottom left = bottom left).
- GlStateManager.translate(-0.5f, -0.5f, 0.5f)
- GlStateManager.translate(0, screen.height, 0)
+ stack.translate(-0.5f, -0.5f, 0.5f)
+ stack.translate(0, screen.height, 0)
// Flip text upside down.
- GlStateManager.scale(1, -1, 1)
+ stack.scale(1, -1, 1)
}
- private def drawOverlay() = if (screen.facing == EnumFacing.UP || screen.facing == EnumFacing.DOWN) {
+ private def drawOverlay(matrix: MatrixStack, r: IVertexBuilder) = if (screen.facing == Direction.UP || screen.facing == Direction.DOWN) {
// Show up vector overlay when holding same screen block.
- val stack = Minecraft.getMinecraft.player.getHeldItemMainhand
+ val stack = Minecraft.getInstance.player.getItemInHand(Hand.MAIN_HAND)
if (!stack.isEmpty) {
- if (Wrench.holdsApplicableWrench(Minecraft.getMinecraft.player, screen.getPos) || screens.contains(api.Items.get(stack))) {
- GlStateManager.pushMatrix()
- transform()
- GlStateManager.depthMask(false)
- GlStateManager.translate(screen.width / 2f - 0.5f, screen.height / 2f - 0.5f, 0.05f)
-
- val t = Tessellator.getInstance
- val r = t.getBuffer
-
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ if (Wrench.holdsApplicableWrench(Minecraft.getInstance.player, screen.getBlockPos) || screens.contains(api.Items.get(stack))) {
+ matrix.pushPose()
+ transform(matrix)
+ matrix.translate(screen.width / 2f - 0.5f, screen.height / 2f - 0.5f, 0.05f)
val icon = Textures.getSprite(Textures.Block.ScreenUpIndicator)
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- t.draw()
+ r.vertex(matrix.last.pose, 0, 1, 0).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(matrix.last.pose, 1, 1, 0).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(matrix.last.pose, 1, 0, 0).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(matrix.last.pose, 0, 0, 0).uv(icon.getU0, icon.getV0).endVertex()
- GlStateManager.depthMask(true)
- GlStateManager.popMatrix()
+ matrix.popPose()
}
}
}
- private def draw() {
+ private def draw(stack: MatrixStack, alpha: Float, buffer: IRenderTypeBuffer) {
RenderState.checkError(getClass.getName + ".draw: entering (aka: wasntme)")
val sx = screen.width
@@ -163,10 +142,10 @@ object ScreenRenderer extends TileEntitySpecialRenderer[Screen] {
val tw = sx * 16f
val th = sy * 16f
- transform()
+ transform(stack)
// Offset from border.
- GlStateManager.translate(sx * 2.25f / tw, sy * 2.25f / th, 0)
+ stack.translate(sx * 2.25f / tw, sy * 2.25f / th, 0)
// Inner size (minus borders).
val isx = sx - (4.5f / 16)
@@ -179,37 +158,37 @@ object ScreenRenderer extends TileEntitySpecialRenderer[Screen] {
val scaleY = isy / sizeY
if (true) {
if (scaleX > scaleY) {
- GlStateManager.translate(sizeX * 0.5f * (scaleX - scaleY), 0, 0)
- GlStateManager.scale(scaleY, scaleY, 1)
+ stack.translate(sizeX * 0.5f * (scaleX - scaleY), 0, 0)
+ stack.scale(scaleY, scaleY, 1)
}
else {
- GlStateManager.translate(0, sizeY * 0.5f * (scaleY - scaleX), 0)
- GlStateManager.scale(scaleX, scaleX, 1)
+ stack.translate(0, sizeY * 0.5f * (scaleY - scaleX), 0)
+ stack.scale(scaleX, scaleX, 1)
}
}
else {
// Stretch to fit.
- GlStateManager.scale(scaleX, scaleY, 1)
+ stack.scale(scaleX, scaleY, 1)
}
// Slightly offset the text so it doesn't clip into the screen.
- GlStateManager.translate(0, 0, 0.01)
+ stack.translate(0, 0, 0.01)
RenderState.checkError(getClass.getName + ".draw: setup")
// Render the actual text.
- screen.buffer.renderText()
+ screen.buffer.renderText(stack)
RenderState.checkError(getClass.getName + ".draw: text")
}
private def playerDistanceSq() = {
- val player = Minecraft.getMinecraft.player
+ val player = Minecraft.getInstance.player
val bounds = screen.getRenderBoundingBox
- val px = player.posX
- val py = player.posY
- val pz = player.posZ
+ val px = player.getX
+ val py = player.getY
+ val pz = player.getZ
val ex = bounds.maxX - bounds.minX
val ey = bounds.maxY - bounds.minY
diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/TransposerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/TransposerRenderer.scala
index 095d0d678c..ad749314cf 100644
--- a/src/main/scala/li/cil/oc/client/renderer/tileentity/TransposerRenderer.scala
+++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/TransposerRenderer.scala
@@ -1,76 +1,69 @@
package li.cil.oc.client.renderer.tileentity
+import java.util.function.Function
+
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.Tessellator
-import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import org.lwjgl.opengl.GL11
-
-object TransposerRenderer extends TileEntitySpecialRenderer[tileentity.Transposer] {
- override def render(transposer: tileentity.Transposer, x: Double, y: Double, z: Double, f: Float, damage: Int, alpha: Float) {
- RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
+import net.minecraft.client.renderer.IRenderTypeBuffer
+import net.minecraft.client.renderer.tileentity.TileEntityRenderer
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
- val activity = math.max(0, 1 - (System.currentTimeMillis() - transposer.lastOperation) / 1000.0)
- if (activity > 0) {
- RenderState.pushAttrib()
+object TransposerRenderer extends Function[TileEntityRendererDispatcher, TransposerRenderer] {
+ override def apply(dispatch: TileEntityRendererDispatcher) = new TransposerRenderer(dispatch)
+}
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
- RenderState.setBlendAlpha(activity.toFloat)
+class TransposerRenderer(dispatch: TileEntityRendererDispatcher) extends TileEntityRenderer[tileentity.Transposer](dispatch) {
+ override def render(transposer: tileentity.Transposer, dt: Float, stack: MatrixStack, buffer: IRenderTypeBuffer, light: Int, overlay: Int) {
+ RenderState.checkError(getClass.getName + ".render: entering (aka: wasntme)")
- GlStateManager.pushMatrix()
+ RenderSystem.color4f(1, 1, 1, 1)
- GlStateManager.translate(x + 0.5, y + 0.5, z + 0.5)
- GlStateManager.scale(1.0025, -1.0025, 1.0025)
- GlStateManager.translate(-0.5f, -0.5f, -0.5f)
+ val activity = math.max(0, 1 - (System.currentTimeMillis() - transposer.lastOperation) / 1000.0f)
+ if (activity > 0) {
+ stack.pushPose()
- val t = Tessellator.getInstance
- val r = t.getBuffer
+ stack.translate(0.5, 0.5, 0.5)
+ stack.scale(1.0025f, -1.0025f, 1.0025f)
+ stack.translate(-0.5f, -0.5f, -0.5f)
- Textures.Block.bind()
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
+ val r = buffer.getBuffer(RenderTypes.BLOCK_OVERLAY_COLOR)
val icon = Textures.getSprite(Textures.Block.TransposerOn)
- r.pos(0, 1, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMinU, icon.getMinV).endVertex()
- r.pos(1, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
-
- r.pos(0, 0, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
-
- r.pos(1, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(0, 1, 0).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(0, 1, 1).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(0, 0, 1).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(0, 0, 0).tex(icon.getMinU, icon.getMinV).endVertex()
-
- r.pos(1, 1, 1).tex(icon.getMinU, icon.getMaxV).endVertex()
- r.pos(1, 1, 0).tex(icon.getMaxU, icon.getMaxV).endVertex()
- r.pos(1, 0, 0).tex(icon.getMaxU, icon.getMinV).endVertex()
- r.pos(1, 0, 1).tex(icon.getMinU, icon.getMinV).endVertex()
-
- t.draw()
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
-
- GlStateManager.popMatrix()
- RenderState.popAttrib()
+ r.vertex(stack.last.pose, 0, 1, 0).color(1, 1, 1, activity).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).color(1, 1, 1, activity).uv(icon.getU0, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).color(1, 1, 1, activity).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).color(1, 1, 1, activity).uv(icon.getU1, icon.getV1).endVertex()
+
+ r.vertex(stack.last.pose, 0, 0, 0).color(1, 1, 1, activity).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).color(1, 1, 1, activity).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).color(1, 1, 1, activity).uv(icon.getU0, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).color(1, 1, 1, activity).uv(icon.getU0, icon.getV1).endVertex()
+
+ r.vertex(stack.last.pose, 1, 1, 0).color(1, 1, 1, activity).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 0).color(1, 1, 1, activity).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).color(1, 1, 1, activity).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).color(1, 1, 1, activity).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 1).color(1, 1, 1, activity).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 1).color(1, 1, 1, activity).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).color(1, 1, 1, activity).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).color(1, 1, 1, activity).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 0, 1, 0).color(1, 1, 1, activity).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 1, 1).color(1, 1, 1, activity).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 1).color(1, 1, 1, activity).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 0, 0, 0).color(1, 1, 1, activity).uv(icon.getU0, icon.getV0).endVertex()
+
+ r.vertex(stack.last.pose, 1, 1, 1).color(1, 1, 1, activity).uv(icon.getU0, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 1, 0).color(1, 1, 1, activity).uv(icon.getU1, icon.getV1).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 0).color(1, 1, 1, activity).uv(icon.getU1, icon.getV0).endVertex()
+ r.vertex(stack.last.pose, 1, 0, 1).color(1, 1, 1, activity).uv(icon.getU0, icon.getV0).endVertex()
+
+ stack.popPose()
}
RenderState.checkError(getClass.getName + ".render: leaving")
diff --git a/src/main/scala/li/cil/oc/common/Achievement.scala b/src/main/scala/li/cil/oc/common/Achievement.scala
index a7fed0a4ee..ae08527c3e 100644
--- a/src/main/scala/li/cil/oc/common/Achievement.scala
+++ b/src/main/scala/li/cil/oc/common/Achievement.scala
@@ -1,6 +1,6 @@
package li.cil.oc.common
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
//placeholder
@@ -9,11 +9,11 @@ object Achievement {
def init() {
}
- def onAssemble(stack: ItemStack, player: EntityPlayer): Unit = {
+ def onAssemble(stack: ItemStack, player: PlayerEntity): Unit = {
}
- def onCraft(stack: ItemStack, player: EntityPlayer): Unit = {
+ def onCraft(stack: ItemStack, player: PlayerEntity): Unit = {
}
}
@@ -25,7 +25,7 @@ import li.cil.oc.OpenComputers
import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.common.init.Items
import li.cil.oc.util.StackOption
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.stats.StatBase
import net.minecraft.stats.{Achievement => MCAchievement}
@@ -249,13 +249,13 @@ object Achievement {
AchievementPage.registerAchievementPage(new AchievementPage(OpenComputers.Name, All: _*))
}
- def onAssemble(stack: ItemStack, player: EntityPlayer): Unit = {
+ def onAssemble(stack: ItemStack, player: PlayerEntity): Unit = {
AssemblingMap.get(Items.get(stack)).foreach(player.addStat(_, 1))
}
- def onCraft(stack: ItemStack, player: EntityPlayer): Unit = {
+ def onCraft(stack: ItemStack, player: PlayerEntity): Unit = {
CraftingMap.get(Items.get(stack)).foreach(player.addStat(_, 1))
- CustomCraftingMap.find(entry => ItemStack.areItemStacksEqual(stack, entry._1)).foreach(entry => player.addStat(entry._2, 1))
+ CustomCraftingMap.find(entry => ItemStack.matches(stack, entry._1)).foreach(entry => player.addStat(entry._2, 1))
}
private def newAchievement(name: String) = new AchievementBuilder(name)
diff --git a/src/main/scala/li/cil/oc/common/ComponentTracker.scala b/src/main/scala/li/cil/oc/common/ComponentTracker.scala
index 84e01e2860..3caabb9979 100644
--- a/src/main/scala/li/cil/oc/common/ComponentTracker.scala
+++ b/src/main/scala/li/cil/oc/common/ComponentTracker.scala
@@ -3,12 +3,14 @@ package li.cil.oc.common
import com.google.common.cache.Cache
import com.google.common.cache.CacheBuilder
import li.cil.oc.api.network.ManagedEnvironment
+import net.minecraft.util.RegistryKey
import net.minecraft.world.World
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
/**
@@ -17,10 +19,10 @@ import scala.collection.mutable
* containers. For now this is only used for screens / text buffer components.
*/
abstract class ComponentTracker {
- private val worlds = mutable.Map.empty[Int, Cache[String, ManagedEnvironment]]
+ private val worlds = mutable.Map.empty[RegistryKey[World], Cache[String, ManagedEnvironment]]
private def components(world: World) = {
- worlds.getOrElseUpdate(world.provider.getDimension,
+ worlds.getOrElseUpdate(world.dimension,
com.google.common.cache.CacheBuilder.newBuilder().
weakValues().
asInstanceOf[CacheBuilder[String, ManagedEnvironment]].
@@ -46,7 +48,10 @@ abstract class ComponentTracker {
}
@SubscribeEvent
- def onWorldUnload(e: WorldEvent.Unload): Unit = clear(e.getWorld)
+ def onWorldUnload(e: WorldEvent.Unload): Unit = e.getWorld match {
+ case world: World => clear(world)
+ case _ =>
+ }
protected def clear(world: World): Unit = this.synchronized {
components(world).invalidateAll()
diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala
index 6a4faddeb3..59ffc590e7 100644
--- a/src/main/scala/li/cil/oc/common/EventHandler.scala
+++ b/src/main/scala/li/cil/oc/common/EventHandler.scala
@@ -15,7 +15,6 @@ import li.cil.oc.api.network.Environment
import li.cil.oc.api.network.SidedComponent
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.client.renderer.PetRenderer
-import li.cil.oc.common.asm.ClassTransformer
import li.cil.oc.common.capabilities.CapabilityColored
import li.cil.oc.common.capabilities.CapabilityEnvironment
import li.cil.oc.common.capabilities.CapabilitySidedComponent
@@ -25,7 +24,6 @@ import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.item.data.TabletData
import li.cil.oc.common.item.traits
-import li.cil.oc.common.recipe.Recipes
import li.cil.oc.common.tileentity.Robot
import li.cil.oc.common.tileentity.traits.power
import li.cil.oc.integration.Mods
@@ -38,29 +36,36 @@ import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.StackOption._
import li.cil.oc.util._
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
-import net.minecraft.init.SoundEvents
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.util.SoundEvents
import net.minecraft.item.ItemStack
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.SoundCategory
+import net.minecraft.util.Util
+import net.minecraft.world.chunk.Chunk
+import net.minecraft.world.server.ChunkHolder
+import net.minecraft.world.server.ChunkManager
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.client.event.ClientPlayerNetworkEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.AttachCapabilitiesEvent
+import net.minecraftforge.event.TickEvent
+import net.minecraftforge.event.TickEvent.ClientTickEvent
+import net.minecraftforge.event.TickEvent.ServerTickEvent
import net.minecraftforge.event.entity.EntityJoinWorldEvent
+import net.minecraftforge.event.entity.player.PlayerEvent._
import net.minecraftforge.event.world.BlockEvent
import net.minecraftforge.event.world.ChunkEvent
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.FMLCommonHandler
-import net.minecraftforge.fml.common.Optional
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.PlayerEvent._
-import net.minecraftforge.fml.common.gameevent.TickEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent
-import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent
-
-import scala.collection.convert.WrapAsScala._
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.fml.common.ObfuscationReflectionHelper
+import net.minecraftforge.fml.server.ServerLifecycleHooks
+
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
@@ -113,29 +118,16 @@ object EventHandler {
}
}
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- def scheduleIC2Add(tileEntity: power.IndustrialCraft2Experimental) {
- if (SideTracker.isServer) pendingServer.synchronized {
- tileEntity match {
- case tile: ic2.api.energy.tile.IEnergyTile =>
- pendingServer += (() => if (!tileEntity.addedToIC2PowerGrid && !tileEntity.isInvalid) {
- MinecraftForge.EVENT_BUS.post(new ic2.api.energy.event.EnergyTileLoadEvent(tile))
- tileEntity.addedToIC2PowerGrid = true
- })
- case _ =>
- }
- }
- }
-
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
- def scheduleAE2Add(tileEntity: power.AppliedEnergistics2): Unit = {
- if (SideTracker.isServer) pendingServer.synchronized {
- tileEntity match {
- case tile: IGridBlock =>
- pendingServer += (() => if (!tileEntity.isInvalid) {
- tileEntity.getGridNode(AEPartLocation.INTERNAL).updateState()
- })
- case _ =>
+ object AE2 {
+ def scheduleAE2Add(tileEntity: power.AppliedEnergistics2): Unit = {
+ if (SideTracker.isServer) pendingServer.synchronized {
+ tileEntity match {
+ case tile: IGridBlock =>
+ pendingServer += (() => if (!tileEntity.isRemoved) {
+ tileEntity.getGridNode(AEPartLocation.INTERNAL).updateState()
+ })
+ case _ =>
+ }
}
}
}
@@ -154,12 +146,13 @@ object EventHandler {
if (!event.getCapabilities.containsKey(traits.Chargeable.KEY)) {
event.getObject match {
case stack: ItemStack => stack.getItem match {
- case chargeable: traits.Chargeable => event.addCapability(traits.Chargeable.KEY, new traits.Chargeable.Provider(stack, chargeable))
- case _: li.cil.oc.api.driver.item.Chargeable =>
- li.cil.oc.common.item.Delegator.subItem(stack) match {
- case Some(subItem: traits.Chargeable) => event.addCapability(traits.Chargeable.KEY, new traits.Chargeable.Provider(stack, subItem))
- case _ =>
- }
+ case chargeable: traits.Chargeable => {
+ val provider = new traits.Chargeable.Provider(stack, chargeable)
+ event.addCapability(traits.Chargeable.KEY, provider)
+ event.addListener(new Runnable {
+ override def run = provider.invalidate
+ })
+ }
case _ =>
}
case _ =>
@@ -170,22 +163,42 @@ object EventHandler {
@SubscribeEvent
def onAttachCapabilities(event: AttachCapabilitiesEvent[TileEntity]): Unit = {
event.getObject match {
- case tileEntity: TileEntity with Environment =>
- event.addCapability(CapabilityEnvironment.ProviderEnvironment, new CapabilityEnvironment.Provider(tileEntity))
+ case tileEntity: TileEntity with Environment => {
+ val provider = new CapabilityEnvironment.Provider(tileEntity)
+ event.addCapability(CapabilityEnvironment.ProviderEnvironment, provider)
+ event.addListener(new Runnable {
+ override def run = provider.invalidate
+ })
+ }
case _ =>
}
event.getObject match {
- case tileEntity: TileEntity with Environment with SidedComponent =>
- event.addCapability(CapabilitySidedComponent.SidedComponent, new CapabilitySidedComponent.Provider(tileEntity))
- case tileEntity: TileEntity with SidedEnvironment =>
- event.addCapability(CapabilitySidedEnvironment.ProviderSidedEnvironment, new CapabilitySidedEnvironment.Provider(tileEntity))
+ case tileEntity: TileEntity with Environment with SidedComponent => {
+ val provider = new CapabilitySidedComponent.Provider(tileEntity)
+ event.addCapability(CapabilitySidedComponent.SidedComponent, provider)
+ event.addListener(new Runnable {
+ override def run = provider.invalidate
+ })
+ }
+ case tileEntity: TileEntity with SidedEnvironment => {
+ val provider = new CapabilitySidedEnvironment.Provider(tileEntity)
+ event.addCapability(CapabilitySidedEnvironment.ProviderSidedEnvironment, provider)
+ event.addListener(new Runnable {
+ override def run = provider.invalidate
+ })
+ }
case _ =>
}
event.getObject match {
- case tileEntity: TileEntity with Colored =>
- event.addCapability(CapabilityColored.ProviderColored, new CapabilityColored.Provider(tileEntity))
+ case tileEntity: TileEntity with Colored => {
+ val provider = new CapabilityColored.Provider(tileEntity)
+ event.addCapability(CapabilityColored.ProviderColored, provider)
+ event.addListener(new Runnable {
+ override def run = provider.invalidate
+ })
+ }
case _ =>
}
}
@@ -212,7 +225,7 @@ object EventHandler {
val invalid = mutable.ArrayBuffer.empty[Robot]
runningRobots.foreach(robot => {
- if (robot.isInvalid) invalid += robot
+ if (robot.isRemoved) invalid += robot
else if (robot.world != null) robot.machine.update()
})
runningRobots --= invalid
@@ -244,20 +257,11 @@ object EventHandler {
@SubscribeEvent
def playerLoggedIn(e: PlayerLoggedInEvent) {
- if (SideTracker.isServer) e.player match {
+ if (SideTracker.isServer) e.getPlayer match {
case _: FakePlayer => // Nope
- case player: EntityPlayerMP =>
+ case player: ServerPlayerEntity =>
if (!LuaStateFactory.isAvailable && !LuaStateFactory.luajRequested) {
- player.sendMessage(Localization.Chat.WarningLuaFallback)
- }
- if (Recipes.hadErrors) {
- player.sendMessage(Localization.Chat.WarningRecipes)
- }
- if (ClassTransformer.hadErrors) {
- player.sendMessage(Localization.Chat.WarningClassTransformer)
- }
- if (ClassTransformer.hadSimpleComponentErrors) {
- player.sendMessage(Localization.Chat.WarningSimpleComponent)
+ player.sendMessage(Localization.Chat.WarningLuaFallback, Util.NIL_UUID)
}
// Gaaah, MC 1.8 y u do this to me? Sending the packets here directly can lead to them
// arriving on the client before it has a world and player instance, which causes all
@@ -267,11 +271,12 @@ object EventHandler {
ServerPacketSender.sendLootDisks(player)
})
// Do update check in local games and for OPs.
- val server = FMLCommonHandler.instance.getMinecraftServerInstance
- if (!server.isDedicatedServer || server.getPlayerList.canSendCommands(player.getGameProfile)) {
+ val server = ServerLifecycleHooks.getCurrentServer
+ if (server.getPlayerList.isOp(player.getGameProfile)) {
Future {
- UpdateCheck.info onSuccess {
- case Some(release) => player.sendMessage(Localization.Chat.InfoNewVersion(release.tag_name))
+ UpdateCheck.info foreach {
+ case Some(release) => player.sendMessage(Localization.Chat.InfoNewVersion(release.tag_name), Util.NIL_UUID)
+ case _ =>
}
}
}
@@ -280,7 +285,8 @@ object EventHandler {
}
@SubscribeEvent
- def clientLoggedIn(e: ClientConnectedToServerEvent) {
+ @OnlyIn(Dist.CLIENT)
+ def clientLoggedIn(e: ClientPlayerNetworkEvent.LoggedInEvent) {
PetRenderer.isInitialized = false
PetRenderer.hidden.clear()
Loot.disksForClient.clear()
@@ -292,14 +298,14 @@ object EventHandler {
@SubscribeEvent
def onBlockBreak(e: BlockEvent.BreakEvent): Unit = {
- e.getWorld.getTileEntity(e.getPos) match {
+ e.getWorld.getBlockEntity(e.getPos) match {
case c: tileentity.Case =>
- if (c.isCreative && (!e.getPlayer.capabilities.isCreativeMode || !c.canInteract(e.getPlayer.getName))) {
+ if (c.isCreative && (!e.getPlayer.isCreative || !c.canInteract(e.getPlayer.getName.getString))) {
e.setCanceled(true)
}
case r: tileentity.RobotProxy =>
val robot = r.robot
- if (robot.isCreative && (!e.getPlayer.capabilities.isCreativeMode || !robot.canInteract(e.getPlayer.getName))) {
+ if (robot.isCreative && (!e.getPlayer.isCreative || !robot.canInteract(e.getPlayer.getName.getString))) {
e.setCanceled(true)
}
case _ =>
@@ -308,27 +314,27 @@ object EventHandler {
@SubscribeEvent
def onPlayerRespawn(e: PlayerRespawnEvent) {
- keyboards.foreach(_.releasePressedKeys(e.player))
+ keyboards.foreach(_.releasePressedKeys(e.getPlayer))
}
@SubscribeEvent
def onPlayerChangedDimension(e: PlayerChangedDimensionEvent) {
- keyboards.foreach(_.releasePressedKeys(e.player))
+ keyboards.foreach(_.releasePressedKeys(e.getPlayer))
}
@SubscribeEvent
def onPlayerLogout(e: PlayerLoggedOutEvent) {
- keyboards.foreach(_.releasePressedKeys(e.player))
+ keyboards.foreach(_.releasePressedKeys(e.getPlayer))
}
@SubscribeEvent
def onEntityJoinWorld(e: EntityJoinWorldEvent): Unit = {
- if (Settings.get.giveManualToNewPlayers && !e.getWorld.isRemote) e.getEntity match {
- case player: EntityPlayer if !player.isInstanceOf[FakePlayer] =>
+ if (Settings.get.giveManualToNewPlayers && !e.getWorld.isClientSide) e.getEntity match {
+ case player: PlayerEntity if !player.isInstanceOf[FakePlayer] =>
val persistedData = PlayerUtils.persistedData(player)
if (!persistedData.getBoolean(Settings.namespace + "receivedManual")) {
- persistedData.setBoolean(Settings.namespace + "receivedManual", true)
- player.inventory.addItemStackToInventory(api.Items.get(Constants.ItemName.Manual).createItemStack(1))
+ persistedData.putBoolean(Settings.namespace + "receivedManual", true)
+ player.inventory.add(api.Items.get(Constants.ItemName.Manual).createItemStack(1))
}
case _ =>
}
@@ -347,8 +353,8 @@ object EventHandler {
didRecraft = recraft(e, navigationUpgrade, stack => {
// Restore the map currently used in the upgrade.
- Option(api.Driver.driverFor(e.crafting)) match {
- case Some(driver) => StackOption(new ItemStack(driver.dataTag(stack).getCompoundTag(Settings.namespace + "map")))
+ Option(api.Driver.driverFor(e.getCrafting)) match {
+ case Some(driver) => StackOption(ItemStack.of(driver.dataTag(stack).getCompound(Settings.namespace + "map")))
case _ => EmptyStack
}
}) || didRecraft
@@ -374,21 +380,21 @@ object EventHandler {
}) || didRecraft
// Presents?
- e.player match {
+ e.getPlayer match {
case _: FakePlayer => // No presents for you, automaton. Such discrimination. Much bad conscience.
- case player: EntityPlayerMP if player.getEntityWorld != null && !player.getEntityWorld.isRemote =>
+ case player: ServerPlayerEntity if player.level != null && !player.level.isClientSide =>
// Presents!? If we didn't recraft, it's an OC item, and the time is right...
- if (Settings.get.presentChance > 0 && !didRecraft && api.Items.get(e.crafting) != null &&
- e.player.getRNG.nextFloat() < Settings.get.presentChance && timeForPresents) {
+ if (Settings.get.presentChance > 0 && !didRecraft && api.Items.get(e.getCrafting) != null &&
+ e.getPlayer.getRandom.nextFloat() < Settings.get.presentChance && timeForPresents) {
// Presents!
val present = api.Items.get(Constants.ItemName.Present).createItemStack(1)
- e.player.world.playSound(e.player, e.player.posX, e.player.posY, e.player.posZ, SoundEvents.BLOCK_NOTE_PLING, SoundCategory.MASTER, 0.2f, 1f)
- InventoryUtils.addToPlayerInventory(present, e.player)
+ e.getPlayer.level.playSound(e.getPlayer, e.getPlayer.getX, e.getPlayer.getY, e.getPlayer.getZ, SoundEvents.NOTE_BLOCK_PLING, SoundCategory.MASTER, 0.2f, 1f)
+ InventoryUtils.addToPlayerInventory(present, e.getPlayer)
}
case _ => // Nope.
}
- Achievement.onCraft(e.crafting, e.player)
+ Achievement.onCraft(e.getCrafting, e.getPlayer)
}
@SubscribeEvent
@@ -396,8 +402,8 @@ object EventHandler {
val entity = e.getOriginalEntity
Option(entity).flatMap(e => Option(e.getItem)) match {
case Some(stack) =>
- Achievement.onAssemble(stack, e.player)
- Achievement.onCraft(stack, e.player)
+ Achievement.onAssemble(stack, e.getPlayer)
+ Achievement.onCraft(stack, e.getPlayer)
case _ => // Huh.
}
}
@@ -423,12 +429,12 @@ object EventHandler {
}
private def recraft(e: ItemCraftedEvent, item: ItemInfo, callback: ItemStack => StackOption): Boolean = {
- if (api.Items.get(e.crafting) == item) {
- for (slot <- 0 until e.craftMatrix.getSizeInventory) {
- val stack = e.craftMatrix.getStackInSlot(slot)
+ if (api.Items.get(e.getCrafting) == item) {
+ for (slot <- 0 until e.getInventory.getContainerSize) {
+ val stack = e.getInventory.getItem(slot)
if (api.Items.get(stack) == item) {
callback(stack).foreach(extra =>
- InventoryUtils.addToPlayerInventory(extra, e.player))
+ InventoryUtils.addToPlayerInventory(extra, e.getPlayer))
}
}
true
@@ -436,19 +442,36 @@ object EventHandler {
else false
}
+ private val getChunks = ObfuscationReflectionHelper.findMethod(classOf[ChunkManager], "func_223491_f")
+
+ private def getChunks(world: ServerWorld): Iterable[ChunkHolder] = try {
+ getChunks.invoke(world.getChunkSource.chunkMap).asInstanceOf[java.lang.Iterable[ChunkHolder]]
+ }
+ catch {
+ case e: Throwable =>
+ throw new Error("Could not access server chunk list", e)
+ }
+
// This is called from the ServerThread *and* the ClientShutdownThread, which
// can potentially happen at the same time... for whatever reason. So let's
// synchronize what we're doing here to avoid race conditions (e.g. when
// disposing networks, where this actually triggered an assert).
@SubscribeEvent
def onWorldUnload(e: WorldEvent.Unload): Unit = this.synchronized {
- if (!e.getWorld.isRemote) {
- e.getWorld.loadedTileEntityList.collect {
+ if (!e.getWorld.isClientSide) {
+ val world = e.getWorld.asInstanceOf[ServerWorld]
+ world.blockEntityList.collect {
case te: tileentity.traits.TileEntity => te.dispose()
}
- e.getWorld.loadedEntityList.collect {
- case host: MachineHost => host.machine.stop()
- }
+
+ getChunks(world).foreach(holder => {
+ val chunk = holder.getTickingChunk
+ if (chunk != null) chunk.getEntitySections.foreach {
+ _.iterator.collect {
+ case host: MachineHost => host.machine.stop()
+ }
+ }
+ })
Callbacks.clear()
}
@@ -458,18 +481,21 @@ object EventHandler {
}
@SubscribeEvent
- def onChunkUnload(e: ChunkEvent.Unload): Unit = {
- if (!e.getWorld.isRemote) {
- e.getChunk.getEntityLists.foreach(_.collect {
- case host: MachineHost => host.machine match {
- case machine: Machine => scheduleClose(machine)
- case _ => // Dafuq?
- }
- case rack: Rack =>
- (0 until rack.getSizeInventory).
- map(rack.getMountable).
- collect { case server: Server if server.machine != null => server.machine.stop() }
- })
+ def onChunkUnloaded(e: ChunkEvent.Unload): Unit = {
+ if (!e.getWorld.isClientSide) e.getChunk match {
+ case chunk: Chunk => {
+ chunk.getEntitySections.foreach(_.collect {
+ case host: MachineHost => host.machine match {
+ case machine: Machine => scheduleClose(machine)
+ case _ => // Dafuq?
+ }
+ case rack: Rack =>
+ (0 until rack.getContainerSize).
+ map(rack.getMountable).
+ collect { case server: Server if server.machine != null => server.machine.stop() }
+ })
+ }
+ case _ =>
}
}
}
diff --git a/src/main/scala/li/cil/oc/common/GuiHandler.scala b/src/main/scala/li/cil/oc/common/GuiHandler.scala
deleted file mode 100644
index 59e6f8b758..0000000000
--- a/src/main/scala/li/cil/oc/common/GuiHandler.scala
+++ /dev/null
@@ -1,103 +0,0 @@
-package li.cil.oc.common
-
-import li.cil.oc.common.inventory.{DatabaseInventory, DiskDriveMountableInventory, ServerInventory}
-import li.cil.oc.common.item.Delegator
-import li.cil.oc.util.BlockPosition
-import li.cil.oc.util.ExtendedWorld._
-import li.cil.oc.server.component.{DiskDriveMountable, Server}
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.ItemStack
-import net.minecraft.world.World
-import net.minecraftforge.fml.common.network.IGuiHandler
-
-abstract class GuiHandler extends IGuiHandler {
- override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef = {
- GuiType.Categories.get(id) match {
- case Some(GuiType.Category.Block) =>
- world.getTileEntity(BlockPosition(x, GuiType.extractY(y), z)) match {
- case t: tileentity.Adapter if id == GuiType.Adapter.id =>
- new container.Adapter(player.inventory, t)
- case t: tileentity.Assembler if id == GuiType.Assembler.id =>
- new container.Assembler(player.inventory, t)
- case t: tileentity.Charger if id == GuiType.Charger.id =>
- new container.Charger(player.inventory, t)
- case t: tileentity.Case if id == GuiType.Case.id =>
- new container.Case(player.inventory, t)
- case t: tileentity.Disassembler if id == GuiType.Disassembler.id =>
- new container.Disassembler(player.inventory, t)
- case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
- new container.DiskDrive(player.inventory, t)
- case t: tileentity.Printer if id == GuiType.Printer.id =>
- new container.Printer(player.inventory, t)
- case t: tileentity.Raid if id == GuiType.Raid.id =>
- new container.Raid(player.inventory, t)
- case t: tileentity.Relay if id == GuiType.Relay.id =>
- new container.Relay(player.inventory, t)
- case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
- new container.Robot(player.inventory, t.robot)
- case t: tileentity.Rack if id == GuiType.Rack.id =>
- new container.Rack(player.inventory, t)
- case t: tileentity.Rack if id == GuiType.ServerInRack.id =>
- val slot = GuiType.extractSlot(y)
- val server = t.getMountable(slot).asInstanceOf[Server]
- new container.Server(player.inventory, server, Option(server))
- case t: tileentity.Rack if id == GuiType.DiskDriveMountableInRack.id =>
- val slot = GuiType.extractSlot(y)
- val drive = t.getMountable(slot).asInstanceOf[DiskDriveMountable]
- new container.DiskDrive(player.inventory, drive)
- case _ => null
- }
- case Some(GuiType.Category.Entity) =>
- world.getEntityByID(x) match {
- case drone: entity.Drone if id == GuiType.Drone.id =>
- new container.Drone(player.inventory, drone)
- case _ => null
- }
- case Some(GuiType.Category.Item) => {
- val itemStackInUse = getItemStackInUse(id, player)
- Delegator.subItem(itemStackInUse) match {
- case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
- new container.Database(player.inventory, new DatabaseInventory {
- override def container = itemStackInUse
-
- override def isUsableByPlayer(player: EntityPlayer) = player == player
- })
- case Some(server: item.Server) if id == GuiType.Server.id =>
- new container.Server(player.inventory, new ServerInventory {
- override def container = itemStackInUse
-
- override def isUsableByPlayer(player: EntityPlayer) = player == player
- })
- case Some(tablet: item.Tablet) if id == GuiType.TabletInner.id =>
- val stack = itemStackInUse
- if (stack.hasTagCompound)
- new container.Tablet(player.inventory, item.Tablet.get(stack, player))
- else
- null
- case Some(drive: item.DiskDriveMountable) if id == GuiType.DiskDriveMountable.id =>
- new container.DiskDrive(player.inventory, new DiskDriveMountableInventory {
- override def container: ItemStack = itemStackInUse
-
- override def isUsableByPlayer(player: EntityPlayer) = player == player
- })
- case _ => null
- }
- }
- case _ => null
- }
- }
-
- def getItemStackInUse(id: Int, player: EntityPlayer): ItemStack = {
- val mainItem: ItemStack = player.getHeldItemMainhand
- Delegator.subItem(mainItem) match {
- case Some(drive: item.traits.FileSystemLike) if id == GuiType.Drive.id => mainItem
- case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id => mainItem
- case Some(server: item.Server) if id == GuiType.Server.id => mainItem
- case Some(tablet: item.Tablet) if id == GuiType.Tablet.id => mainItem
- case Some(tablet: item.Tablet) if id == GuiType.TabletInner.id => mainItem
- case Some(terminal: item.Terminal) if id == GuiType.Terminal.id => mainItem
- case Some(drive: item.DiskDriveMountable) if id == GuiType.DiskDriveMountable.id => mainItem
- case _ => player.inventory.offHandInventory.get(0)
- }
- }
-}
diff --git a/src/main/scala/li/cil/oc/common/GuiType.scala b/src/main/scala/li/cil/oc/common/GuiType.scala
deleted file mode 100644
index ee001fc5b6..0000000000
--- a/src/main/scala/li/cil/oc/common/GuiType.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package li.cil.oc.common
-
-import li.cil.oc.util.ScalaEnum
-
-import scala.collection.mutable
-
-object GuiType extends ScalaEnum {
- val Categories = mutable.Map.empty[Int, Category.Value]
-
- sealed trait EnumVal extends Value {
- def id = ordinal
- def subType: GuiType.Category.Value
- Categories += ordinal -> subType
- }
-
- val Adapter = new EnumVal { def name = "Adapter"; def subType = GuiType.Category.Block }
- val Assembler = new EnumVal { def name = "Assembler"; def subType = GuiType.Category.Block }
- val Case = new EnumVal { def name = "Case"; def subType = GuiType.Category.Block }
- val Charger = new EnumVal { def name = "Charger"; def subType = GuiType.Category.Block }
- val Database = new EnumVal { def name = "Database"; def subType = GuiType.Category.Item }
- val Disassembler = new EnumVal { def name = "Disassembler"; def subType = GuiType.Category.Block }
- val DiskDrive = new EnumVal { def name = "DiskDrive"; def subType = GuiType.Category.Block }
- val DiskDriveMountable = new EnumVal { def name = "DiskDriveMountable"; def subType = GuiType.Category.Item }
- val DiskDriveMountableInRack = new EnumVal { def name = "DiskDriveMountableInRack"; def subType = GuiType.Category.Block }
- val Drive = new EnumVal { def name = "Drive"; def subType = GuiType.Category.Item }
- val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity }
- val Manual = new EnumVal { def name = "Manual"; def subType = GuiType.Category.None }
- val Printer = new EnumVal { def name = "Printer"; def subType = GuiType.Category.Block }
- val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block }
- val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block }
- val Relay = new EnumVal { def name = "Relay"; def subType = GuiType.Category.Block }
- val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
- val Screen = new EnumVal { def name = "Screen"; def subType = GuiType.Category.Block }
- val Server = new EnumVal { def name = "Server"; def subType = GuiType.Category.Item }
- val ServerInRack = new EnumVal { def name = "ServerInRack"; def subType = GuiType.Category.Block }
- val Switch = new EnumVal { def name = "Switch"; def subType = GuiType.Category.Block }
- val Tablet = new EnumVal { def name = "Tablet"; def subType = GuiType.Category.Item }
- val TabletInner = new EnumVal { def name = "TabletInner"; def subType = GuiType.Category.Item }
- val Terminal = new EnumVal { def name = "Terminal"; def subType = GuiType.Category.Item }
- val Waypoint = new EnumVal { def name = "Waypoint"; def subType = GuiType.Category.Block }
-
- object Category extends ScalaEnum {
- sealed trait EnumVal extends Value
-
- val None = new EnumVal { def name = "None" }
- val Block = new EnumVal { def name = "Block" }
- val Entity = new EnumVal { def name = "Entity" }
- val Item = new EnumVal { def name = "Item" }
- }
-
- def embedSlot(y: Int, slot: Int) = (y & 0x00FFFFFF) | (slot << 24)
-
- def extractY(value: Int) = value & 0x00FFFFFF
-
- def extractSlot(value: Int) = (value >>> 24) & 0xFF
-}
diff --git a/src/main/scala/li/cil/oc/common/IMC.scala b/src/main/scala/li/cil/oc/common/IMC.scala
index 3401977ba1..7e86efac31 100644
--- a/src/main/scala/li/cil/oc/common/IMC.scala
+++ b/src/main/scala/li/cil/oc/common/IMC.scala
@@ -14,94 +14,93 @@ import li.cil.oc.integration.util.Wrench
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.machine.ProgramLocations
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagString
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.StringNBT
import net.minecraft.util.math.BlockPos
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.common.event.FMLInterModComms.IMCEvent
+import net.minecraftforge.fml.InterModComms.IMCMessage
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object IMC {
- def handleEvent(e: IMCEvent): Unit = {
- for (message <- e.getMessages) {
- if (message.key == api.IMC.REGISTER_ASSEMBLER_TEMPLATE && message.isNBTMessage) {
- if (message.getNBTValue.hasKey("name", NBT.TAG_STRING))
- OpenComputers.log.debug(s"Registering new assembler template '${message.getNBTValue.getString("name")}' from mod ${message.getSender}.")
+ def handleMessage(message: IMCMessage): Unit = {
+ message.getMessageSupplier.get.asInstanceOf[AnyRef] match {
+ case template: CompoundNBT if message.getMethod == api.IMC.REGISTER_ASSEMBLER_TEMPLATE => {
+ if (template.contains("name", NBT.TAG_STRING))
+ OpenComputers.log.debug(s"Registering new assembler template '${template.getString("name")}' from mod ${message.getSenderModId}.")
else
- OpenComputers.log.debug(s"Registering new, unnamed assembler template from mod ${message.getSender}.")
- try AssemblerTemplates.add(message.getNBTValue) catch {
+ OpenComputers.log.debug(s"Registering new, unnamed assembler template from mod ${message.getSenderModId}.")
+ try AssemblerTemplates.add(template) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering assembler template.", t)
}
}
- else if (message.key == api.IMC.REGISTER_DISASSEMBLER_TEMPLATE && message.isNBTMessage) {
- if (message.getNBTValue.hasKey("name", NBT.TAG_STRING))
- OpenComputers.log.debug(s"Registering new disassembler template '${message.getNBTValue.getString("name")}' from mod ${message.getSender}.")
+ case template: CompoundNBT if message.getMethod == api.IMC.REGISTER_DISASSEMBLER_TEMPLATE => {
+ if (template.contains("name", NBT.TAG_STRING))
+ OpenComputers.log.debug(s"Registering new disassembler template '${template.getString("name")}' from mod ${message.getSenderModId}.")
else
- OpenComputers.log.debug(s"Registering new, unnamed disassembler template from mod ${message.getSender}.")
- try DisassemblerTemplates.add(message.getNBTValue) catch {
+ OpenComputers.log.debug(s"Registering new, unnamed disassembler template from mod ${message.getSenderModId}.")
+ try DisassemblerTemplates.add(template) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering disassembler template.", t)
}
}
- else if (message.key == api.IMC.REGISTER_TOOL_DURABILITY_PROVIDER && message.isStringMessage) {
- OpenComputers.log.debug(s"Registering new tool durability provider '${message.getStringValue}' from mod ${message.getSender}.")
- try ToolDurabilityProviders.add(getStaticMethod(message.getStringValue, classOf[ItemStack])) catch {
+ case name: String if message.getMethod == api.IMC.REGISTER_TOOL_DURABILITY_PROVIDER => {
+ OpenComputers.log.debug(s"Registering new tool durability provider '${name}' from mod ${message.getSenderModId}.")
+ try ToolDurabilityProviders.add(getStaticMethod(name, classOf[ItemStack])) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering tool durability provider.", t)
}
}
- else if (message.key == api.IMC.REGISTER_WRENCH_TOOL && message.isStringMessage) {
- OpenComputers.log.debug(s"Registering new wrench usage '${message.getStringValue}' from mod ${message.getSender}.")
- try Wrench.addUsage(getStaticMethod(message.getStringValue, classOf[EntityPlayer], classOf[BlockPos], classOf[Boolean])) catch {
+ case name: String if message.getMethod == api.IMC.REGISTER_WRENCH_TOOL => {
+ OpenComputers.log.debug(s"Registering new wrench usage '${name}' from mod ${message.getSenderModId}.")
+ try Wrench.addUsage(getStaticMethod(name, classOf[PlayerEntity], classOf[BlockPos], classOf[Boolean])) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering wrench usage.", t)
}
}
- else if (message.key == api.IMC.REGISTER_WRENCH_TOOL_CHECK && message.isStringMessage) {
- OpenComputers.log.debug(s"Registering new wrench tool check '${message.getStringValue}' from mod ${message.getSender}.")
- try Wrench.addCheck(getStaticMethod(message.getStringValue, classOf[ItemStack])) catch {
+ case name: String if message.getMethod == api.IMC.REGISTER_WRENCH_TOOL_CHECK => {
+ OpenComputers.log.debug(s"Registering new wrench tool check '${name}' from mod ${message.getSenderModId}.")
+ try Wrench.addCheck(getStaticMethod(name, classOf[ItemStack])) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering wrench check.", t)
}
}
- else if (message.key == api.IMC.REGISTER_ITEM_CHARGE && message.isNBTMessage) {
- OpenComputers.log.debug(s"Registering new item charge implementation '${message.getNBTValue.getString("name")}' from mod ${message.getSender}.")
+ case implInfo: CompoundNBT if message.getMethod == api.IMC.REGISTER_ITEM_CHARGE => {
+ OpenComputers.log.debug(s"Registering new item charge implementation '${implInfo.getString("name")}' from mod ${message.getSenderModId}.")
try ItemCharge.add(
- getStaticMethod(message.getNBTValue.getString("canCharge"), classOf[ItemStack]),
- getStaticMethod(message.getNBTValue.getString("charge"), classOf[ItemStack], classOf[Double], classOf[Boolean])
+ getStaticMethod(implInfo.getString("canCharge"), classOf[ItemStack]),
+ getStaticMethod(implInfo.getString("charge"), classOf[ItemStack], classOf[Double], classOf[Boolean])
) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering item charge implementation.", t)
}
}
- else if (message.key == api.IMC.BLACKLIST_PERIPHERAL && message.isStringMessage) {
- OpenComputers.log.debug(s"Blacklisting CC peripheral '${message.getStringValue}' as requested by mod ${message.getSender}.")
- if (!Settings.get.peripheralBlacklist.contains(message.getStringValue)) {
- Settings.get.peripheralBlacklist.add(message.getStringValue)
+ case name: String if message.getMethod == api.IMC.BLACKLIST_PERIPHERAL => {
+ OpenComputers.log.debug(s"Blacklisting CC peripheral '${name}' as requested by mod ${message.getSenderModId}.")
+ if (!Settings.get.peripheralBlacklist.contains(name)) {
+ Settings.get.peripheralBlacklist.add(name)
}
}
- else if (message.key == api.IMC.BLACKLIST_HOST && message.isNBTMessage) {
- OpenComputers.log.debug(s"Blacklisting component '${message.getNBTValue.getString("name")}' for host '${message.getNBTValue.getString("host")}' as requested by mod ${message.getSender}.")
- try Registry.blacklistHost(new ItemStack(message.getNBTValue.getCompoundTag("item")), Class.forName(message.getNBTValue.getString("host"))) catch {
+ case compInfo: CompoundNBT if message.getMethod == api.IMC.BLACKLIST_HOST => {
+ OpenComputers.log.debug(s"Blacklisting component '${compInfo.getString("name")}' for host '${compInfo.getString("host")}' as requested by mod ${message.getSenderModId}.")
+ try Registry.blacklistHost(ItemStack.of(compInfo.getCompound("item")), Class.forName(compInfo.getString("host"))) catch {
case t: Throwable => OpenComputers.log.warn("Failed blacklisting component.", t)
}
}
- else if (message.key == api.IMC.REGISTER_ASSEMBLER_FILTER && message.isStringMessage) {
- OpenComputers.log.debug(s"Registering new assembler template filter '${message.getStringValue}' from mod ${message.getSender}.")
- try AssemblerTemplates.addFilter(message.getStringValue) catch {
+ case name: String if message.getMethod == api.IMC.REGISTER_ASSEMBLER_FILTER => {
+ OpenComputers.log.debug(s"Registering new assembler template filter '${name}' from mod ${message.getSenderModId}.")
+ try AssemblerTemplates.addFilter(name) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering assembler template filter.", t)
}
}
- else if (message.key == api.IMC.REGISTER_INK_PROVIDER && message.isStringMessage) {
- OpenComputers.log.debug(s"Registering new ink provider '${message.getStringValue}' from mod ${message.getSender}.")
- try PrintData.addInkProvider(getStaticMethod(message.getStringValue, classOf[ItemStack])) catch {
+ case name: String if message.getMethod == api.IMC.REGISTER_INK_PROVIDER => {
+ OpenComputers.log.debug(s"Registering new ink provider '${name}' from mod ${message.getSenderModId}.")
+ try PrintData.addInkProvider(getStaticMethod(name, classOf[ItemStack])) catch {
case t: Throwable => OpenComputers.log.warn("Failed registering ink provider.", t)
}
}
- else if (message.key == api.IMC.REGISTER_PROGRAM_DISK_LABEL && message.isNBTMessage) {
- OpenComputers.log.debug(s"Registering new program location mapping for program '${message.getNBTValue.getString("program")}' being on disk '${message.getNBTValue.getString("label")}' from mod ${message.getSender}.")
- ProgramLocations.addMapping(message.getNBTValue.getString("program"), message.getNBTValue.getString("label"), message.getNBTValue.getTagList("architectures", NBT.TAG_STRING).map((tag: NBTTagString) => tag.getString()).toArray: _*)
- }
- else {
- OpenComputers.log.warn(s"Got an unrecognized or invalid IMC message '${message.key}' from mod ${message.getSender}.")
+ case diskInfo: CompoundNBT if message.getMethod == api.IMC.REGISTER_PROGRAM_DISK_LABEL => {
+ OpenComputers.log.debug(s"Registering new program location mapping for program '${diskInfo.getString("program")}' being on disk '${diskInfo.getString("label")}' from mod ${message.getSenderModId}.")
+ ProgramLocations.addMapping(diskInfo.getString("program"), diskInfo.getString("label"), diskInfo.getList("architectures", NBT.TAG_STRING).map((tag: StringNBT) => tag.getAsString()).toArray: _*)
}
+ case _ => OpenComputers.log.warn(s"Got an unrecognized or invalid IMC message '${message.getMethod}' from mod ${message.getSenderModId}.")
}
}
diff --git a/src/main/scala/li/cil/oc/common/Loot.scala b/src/main/scala/li/cil/oc/common/Loot.scala
index 511e34ac17..f97c9edd9c 100644
--- a/src/main/scala/li/cil/oc/common/Loot.scala
+++ b/src/main/scala/li/cil/oc/common/Loot.scala
@@ -11,19 +11,22 @@ import li.cil.oc.api
import li.cil.oc.api.fs.FileSystem
import li.cil.oc.common.init.Items
import li.cil.oc.util.Color
-import net.minecraft.item.EnumDyeColor
+import net.minecraft.item.DyeColor
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraftforge.common.DimensionManager
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.ResourceLocation
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.World
+import net.minecraft.world.server.ServerWorld
+import net.minecraft.world.storage.FolderName
import net.minecraftforge.common.util.Constants.NBT
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.Loader
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
-//class Loot extends WeightedRandomChestContent(api.Items.get(Constants.ItemName.Floppy).item(), api.Items.get(Constants.ItemName.Floppy).createItemStack(1).getItemDamage, 1, 1, Settings.get.lootProbability) {
+//class Loot extends WeightedRandomChestContent(api.Items.get(Constants.ItemName.Floppy).item(), api.Items.get(Constants.ItemName.Floppy).createItemStack(1).getDamageValue, 1, 1, Settings.get.lootProbability) {
// override def generateChestContent(random: Random, newInventory: IInventory) =
// Loot.randomDisk(random) match {
// case Some(disk) =>
@@ -39,7 +42,7 @@ object Loot {
// ChestGenHooks.PYRAMID_JUNGLE_CHEST,
// ChestGenHooks.STRONGHOLD_LIBRARY)
- val factories = mutable.Map.empty[String, Callable[FileSystem]]
+ val factories = mutable.Map.empty[ResourceLocation, Callable[FileSystem]]
val globalDisks = mutable.ArrayBuffer.empty[(ItemStack, Int)]
@@ -55,33 +58,27 @@ object Loot {
val disksForClient = mutable.ArrayBuffer.empty[ItemStack]
- def isLootDisk(stack: ItemStack): Boolean = api.Items.get(stack) == api.Items.get(Constants.ItemName.Floppy) && stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "lootFactory", NBT.TAG_STRING)
+ def isLootDisk(stack: ItemStack): Boolean = api.Items.get(stack) == api.Items.get(Constants.ItemName.Floppy) && stack.hasTag && stack.getTag.contains(Settings.namespace + "lootFactory", NBT.TAG_STRING)
def randomDisk(rng: Random) =
if (disksForSampling.nonEmpty) Some(disksForSampling(rng.nextInt(disksForSampling.length)))
else None
- def registerLootDisk(name: String, color: EnumDyeColor, factory: Callable[FileSystem], doRecipeCycling: Boolean): ItemStack = {
- val mod = Loader.instance.activeModContainer.getModId
+ def registerLootDisk(name: String, loc: ResourceLocation, color: DyeColor, factory: Callable[FileSystem], doRecipeCycling: Boolean): ItemStack = {
+ OpenComputers.log.debug(s"Registering loot disk '$name' from mod ${loc.getNamespace}.")
- OpenComputers.log.debug(s"Registering loot disk '$name' from mod $mod.")
+ val data = new CompoundNBT()
+ data.putString(Settings.namespace + "fs.label", name)
- val modSpecificName = mod + ":" + name
-
- val data = new NBTTagCompound()
- data.setString(Settings.namespace + "fs.label", name)
-
- val nbt = new NBTTagCompound()
- nbt.setTag(Settings.namespace + "data", data)
+ val stack = Items.get(Constants.ItemName.Floppy).createItemStack(1)
+ val nbt = stack.getOrCreateTag
+ nbt.put(Settings.namespace + "data", data)
// Store this top level, so it won't get wiped on save.
- nbt.setString(Settings.namespace + "lootFactory", modSpecificName)
- nbt.setInteger(Settings.namespace + "color", color.getDyeDamage)
-
- val stack = Items.get(Constants.ItemName.Floppy).createItemStack(1)
- stack.setTagCompound(nbt)
+ nbt.putString(Settings.namespace + "lootFactory", loc.toString)
+ nbt.putInt(Settings.namespace + "color", color.getId)
- Loot.factories += modSpecificName -> factory
+ Loot.factories += loc -> factory
if(doRecipeCycling) {
Loot.disksForCyclingServer += stack
@@ -103,13 +100,13 @@ object Loot {
}
@SubscribeEvent
- def initForWorld(e: WorldEvent.Load): Unit = if (!e.getWorld.isRemote && e.getWorld.provider.getDimension == 0) {
- worldDisks.clear()
- disksForSampling.clear()
- if (!e.getWorld.isRemote) {
- val path = new io.File(DimensionManager.getCurrentSaveRootDirectory, Settings.savePath + "loot/")
+ def initForWorld(e: WorldEvent.Load): Unit = e.getWorld match {
+ case world: ServerWorld if world.dimension == World.OVERWORLD => {
+ worldDisks.clear()
+ disksForSampling.clear()
+ val path = world.getServer.getWorldPath(new FolderName(Settings.savePath)).toFile
if (path.exists && path.isDirectory) {
- val listFile = new io.File(path, "loot.properties")
+ val listFile = new io.File(path, "loot/loot.properties")
if (listFile.exists && listFile.isFile) {
try {
val listStream = new io.FileInputStream(listFile)
@@ -123,15 +120,16 @@ object Loot {
}
}
}
- }
- for (entry <- globalDisks if !worldDisks.contains(entry)) {
- worldDisks += entry
- }
- for ((stack, count) <- worldDisks) {
- for (i <- 0 until count) {
- disksForSampling += stack
+ for (entry <- globalDisks if !worldDisks.contains(entry)) {
+ worldDisks += entry
+ }
+ for ((stack, count) <- worldDisks) {
+ for (i <- 0 until count) {
+ disksForSampling += stack
+ }
}
}
+ case _ =>
}
private def parseLootDisks(list: java.util.Properties, acc: mutable.ArrayBuffer[(ItemStack, Int)], external: Boolean) {
@@ -139,7 +137,7 @@ object Loot {
val value = list.getProperty(key)
try value.split(":") match {
case Array(name, count, color) =>
- acc += ((createLootDisk(name, key, external, Color.byOreName.get(color)), count.toInt))
+ acc += ((createLootDisk(name, key, external, Some(Color.byName(color))), count.toInt))
case Array(name, count) =>
acc += ((createLootDisk(name, key, external), count.toInt))
case _ =>
@@ -151,14 +149,14 @@ object Loot {
}
}
- def createLootDisk(name: String, path: String, external: Boolean, color: Option[EnumDyeColor] = None) = {
+ def createLootDisk(name: String, path: String, external: Boolean, color: Option[DyeColor] = None) = {
val callable = if (external) new Callable[FileSystem] {
override def call(): FileSystem = api.FileSystem.asReadOnly(api.FileSystem.fromSaveDirectory("loot/" + path, 0, false))
} else new Callable[FileSystem] {
- override def call(): FileSystem = api.FileSystem.fromClass(OpenComputers.getClass, Settings.resourceDomain, "loot/" + path)
+ override def call(): FileSystem = api.FileSystem.fromResource(new ResourceLocation(Settings.resourceDomain, "loot/" + path))
}
- val stack = registerLootDisk(path, color.getOrElse(EnumDyeColor.SILVER), callable, doRecipeCycling = true)
- stack.setStackDisplayName(name)
+ val stack = registerLootDisk(path, new ResourceLocation(Settings.resourceDomain, path), color.getOrElse(DyeColor.LIGHT_GRAY), callable, doRecipeCycling = true)
+ stack.setHoverName(new StringTextComponent(name))
if (!external) {
Items.registerStack(stack, path)
}
diff --git a/src/main/scala/li/cil/oc/common/PacketBuilder.scala b/src/main/scala/li/cil/oc/common/PacketBuilder.scala
index 27d0bb8012..ac524d9183 100644
--- a/src/main/scala/li/cil/oc/common/PacketBuilder.scala
+++ b/src/main/scala/li/cil/oc/common/PacketBuilder.scala
@@ -1,5 +1,7 @@
package li.cil.oc.common
+import java.util.function.Supplier
+
import java.io.BufferedOutputStream
import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
@@ -11,33 +13,36 @@ import io.netty.buffer.Unpooled
import li.cil.oc.OpenComputers
import li.cil.oc.api.network.EnvironmentHost
import net.minecraft.entity.Entity
-import net.minecraft.entity.player.EntityPlayerMP
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompressedStreamTools
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.network.PacketBuffer
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
import net.minecraft.world.World
-import net.minecraftforge.fml.common.FMLCommonHandler
-import net.minecraftforge.fml.common.network.internal.FMLProxyPacket
+import net.minecraftforge.fml.network.PacketDistributor
+import net.minecraftforge.fml.server.ServerLifecycleHooks
+import net.minecraftforge.registries._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
abstract class PacketBuilder(stream: OutputStream) extends DataOutputStream(stream) {
+ def writeRegistryEntry[T <: IForgeRegistryEntry[T]](registry: IForgeRegistry[T], value: T): Unit =
+ writeInt(registry.asInstanceOf[ForgeRegistry[T]].getID(value))
+
def writeTileEntity(t: TileEntity) {
- writeInt(t.getWorld.provider.getDimension)
- writeInt(t.getPos.getX)
- writeInt(t.getPos.getY)
- writeInt(t.getPos.getZ)
+ writeUTF(t.getLevel.dimension.location.toString)
+ writeInt(t.getBlockPos.getX)
+ writeInt(t.getBlockPos.getY)
+ writeInt(t.getBlockPos.getZ)
}
def writeEntity(e: Entity) {
- writeInt(e.world.provider.getDimension)
- writeInt(e.getEntityId)
+ writeUTF(e.level.dimension.location.toString)
+ writeInt(e.getId)
}
- def writeDirection(d: Option[EnumFacing]) = d match {
+ def writeDirection(d: Option[Direction]) = d match {
case Some(side) => writeByte(side.ordinal.toByte)
case _ => writeByte(-1: Byte)
}
@@ -46,11 +51,11 @@ abstract class PacketBuilder(stream: OutputStream) extends DataOutputStream(stre
val haveStack = !stack.isEmpty && stack.getCount > 0
writeBoolean(haveStack)
if (haveStack) {
- writeNBT(stack.writeToNBT(new NBTTagCompound()))
+ writeNBT(stack.save(new CompoundNBT()))
}
}
- def writeNBT(nbt: NBTTagCompound) = {
+ def writeNBT(nbt: CompoundNBT) = {
val haveNbt = nbt != null
writeBoolean(haveNbt)
if (haveNbt) {
@@ -60,32 +65,33 @@ abstract class PacketBuilder(stream: OutputStream) extends DataOutputStream(stre
def writePacketType(pt: PacketType.Value) = writeByte(pt.id)
- def sendToAllPlayers() = OpenComputers.channel.sendToAll(packet)
+ def sendToAllPlayers() = OpenComputers.channel.send(PacketDistributor.ALL.noArg(), packet)
- def sendToPlayersNearEntity(e: Entity, range: Option[Double] = None): Unit = sendToNearbyPlayers(e.getEntityWorld, e.posX, e.posY, e.posZ, range)
+ def sendToPlayersNearEntity(e: Entity, range: Option[Double] = None): Unit = sendToNearbyPlayers(e.level, e.getX, e.getY, e.getZ, range)
- def sendToPlayersNearTileEntity(t: TileEntity, range: Option[Double] = None): Unit = sendToNearbyPlayers(t.getWorld, t.getPos.getX + 0.5, t.getPos.getY + 0.5, t.getPos.getZ + 0.5, range)
+ def sendToPlayersNearTileEntity(t: TileEntity, range: Option[Double] = None): Unit = sendToNearbyPlayers(t.getLevel, t.getBlockPos.getX + 0.5, t.getBlockPos.getY + 0.5, t.getBlockPos.getZ + 0.5, range)
def sendToPlayersNearHost(host: EnvironmentHost, range: Option[Double] = None): Unit = sendToNearbyPlayers(host.world, host.xPosition, host.yPosition, host.zPosition, range)
def sendToNearbyPlayers(world: World, x: Double, y: Double, z: Double, range: Option[Double]) {
- val dimension = world.provider.getDimension
- val server = FMLCommonHandler.instance.getMinecraftServerInstance
+ val server = ServerLifecycleHooks.getCurrentServer
val manager = server.getPlayerList
- for (player <- manager.getPlayers if player.dimension == dimension) {
- val playerRenderDistance = 16 // ObfuscationReflectionHelper.getPrivateValue(classOf[EntityPlayerMP], player, "renderDistance").asInstanceOf[Integer]
+ for (player <- manager.getPlayers if player.level == world) {
+ val playerRenderDistance = 16
val playerSpecificRange = range.getOrElse((manager.getViewDistance min playerRenderDistance) * 16.0)
- if (player.getDistanceSq(x, y, z) < playerSpecificRange * playerSpecificRange) {
+ if (player.distanceToSqr(x, y, z) < playerSpecificRange * playerSpecificRange) {
sendToPlayer(player)
}
}
}
- def sendToPlayer(player: EntityPlayerMP) = OpenComputers.channel.sendTo(packet, player)
+ def sendToPlayer(player: ServerPlayerEntity) = OpenComputers.channel.send(PacketDistributor.PLAYER.`with`(new Supplier[ServerPlayerEntity] {
+ override def get = player
+ }), packet)
def sendToServer() = OpenComputers.channel.sendToServer(packet)
- protected def packet: FMLProxyPacket
+ protected def packet: Array[Byte]
}
// Necessary to keep track of the GZIP stream.
@@ -96,7 +102,7 @@ class SimplePacketBuilder(val packetType: PacketType.Value) extends PacketBuilde
override protected def packet = {
flush()
- new FMLProxyPacket(new PacketBuffer(Unpooled.wrappedBuffer(stream.toByteArray)), "OpenComputers")
+ stream.toByteArray
}
}
@@ -106,7 +112,7 @@ class CompressedPacketBuilder(val packetType: PacketType.Value, private val data
override protected def packet = {
flush()
stream.finish()
- new FMLProxyPacket(new PacketBuffer(Unpooled.wrappedBuffer(data.toByteArray)), "OpenComputers")
+ data.toByteArray
}
}
diff --git a/src/main/scala/li/cil/oc/common/PacketHandler.scala b/src/main/scala/li/cil/oc/common/PacketHandler.scala
index 9b32860ca0..2f5d3ec1a4 100644
--- a/src/main/scala/li/cil/oc/common/PacketHandler.scala
+++ b/src/main/scala/li/cil/oc/common/PacketHandler.scala
@@ -1,58 +1,56 @@
package li.cil.oc.common
+import java.io.ByteArrayInputStream
import java.io.DataInputStream
import java.io.InputStream
import java.util.zip.InflaterInputStream
-import io.netty.buffer.ByteBuf
-import io.netty.buffer.ByteBufInputStream
import li.cil.oc.Constants
import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.common.block.RobotAfterimage
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
+import li.cil.oc.util.RotationHelper
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompressedStreamTools
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.network.INetHandler
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
+import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
-import net.minecraftforge.fml.common.FMLCommonHandler
+import net.minecraftforge.fml.network.NetworkDirection
+import net.minecraftforge.fml.server.ServerLifecycleHooks
+import net.minecraftforge.registries._
+import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTag
import scala.reflect.classTag
-abstract class PacketHandler {
- /** Top level dispatcher based on packet type. */
- protected def onPacketData(handler: INetHandler, data: ByteBuf, player: EntityPlayer) {
- val thread = FMLCommonHandler.instance.getWorldThread(handler)
- if (thread.isCallingFromMinecraftThread) {
- process(data, player)
- }
- else {
- data.retain()
- thread.addScheduledTask(new Runnable {
- override def run(): Unit = {
- process(data, player)
- data.release()
- }
- })
- }
- }
+object PacketHandler {
+ var clientHandler: PacketHandler = _
+
+ var serverHandler: PacketHandler = _
- private def process(data: ByteBuf, player: EntityPlayer): Unit = {
- // Don't crash on badly formatted packets (may have been altered by a
- // malicious client, in which case we don't want to allow it to kill the
- // server like this). Just spam the log a bit... ;)
+ private[oc] def handlePacket(side: NetworkDirection, arr: Array[Byte], player: PlayerEntity): Unit = {
try {
- val stream = new ByteBufInputStream(data)
- if (stream.read() == 0) dispatch(new PacketParser(stream, player))
- else dispatch(new PacketParser(new InflaterInputStream(stream), player))
+ val handler = side match {
+ case NetworkDirection.PLAY_TO_CLIENT => clientHandler
+ case NetworkDirection.PLAY_TO_SERVER => serverHandler
+ case _ => null
+ }
+ if (handler != null) {
+ val stream = new ByteArrayInputStream(arr)
+ if (stream.read() == 0) handler.dispatch(handler.createParser(stream, player))
+ else handler.dispatch(handler.createParser(new InflaterInputStream(stream), player))
+ }
} catch {
+ // Don't crash on badly formatted packets (may have been altered by a
+ // malicious client, in which case we don't want to allow it to kill the
+ // server like this). Just spam the log a bit... ;)
case e: Throwable =>
OpenComputers.log.warn("Received a badly formatted packet.", e)
}
@@ -60,11 +58,13 @@ abstract class PacketHandler {
// Avoid AFK kicks by marking players as non-idle when they send packets.
// This will usually be stuff like typing while in screen GUIs.
player match {
- case mp: EntityPlayerMP => mp.markPlayerActive()
- case _ => // Uh... OK?
+ case mp: ServerPlayerEntity => mp.resetLastActionTime()
+ case _ =>
}
}
+}
+abstract class PacketHandler {
/**
* Gets the world for the specified dimension.
*
@@ -72,17 +72,22 @@ abstract class PacketHandler {
* dimension; None otherwise. For the server it returns the world for the
* specified dimension, if such a dimension exists; None otherwise.
*/
- protected def world(player: EntityPlayer, dimension: Int): Option[World]
+ protected def world(player: PlayerEntity, dimension: ResourceLocation): Option[World]
protected def dispatch(p: PacketParser): Unit
- protected class PacketParser(stream: InputStream, val player: EntityPlayer) extends DataInputStream(stream) {
+ protected def createParser(stream: InputStream, player: PlayerEntity): PacketParser
+
+ private[oc] class PacketParser(stream: InputStream, val player: PlayerEntity) extends DataInputStream(stream) {
val packetType = PacketType(readByte())
- def getTileEntity[T: ClassTag](dimension: Int, x: Int, y: Int, z: Int): Option[T] = {
+ def readRegistryEntry[T <: IForgeRegistryEntry[T]](registry: IForgeRegistry[T]): T =
+ registry.asInstanceOf[ForgeRegistry[T]].getValue(readInt())
+
+ def getBlockEntity[T: ClassTag](dimension: ResourceLocation, x: Int, y: Int, z: Int): Option[T] = {
world(player, dimension) match {
case Some(world) if world.blockExists(BlockPosition(x, y, z)) =>
- val t = world.getTileEntity(BlockPosition(x, y, z))
+ val t = world.getBlockEntity(BlockPosition(x, y, z))
if (t != null && classTag[T].runtimeClass.isAssignableFrom(t.getClass)) {
return Some(t.asInstanceOf[T])
}
@@ -102,10 +107,10 @@ abstract class PacketHandler {
None
}
- def getEntity[T: ClassTag](dimension: Int, id: Int): Option[T] = {
+ def getEntity[T: ClassTag](dimension: ResourceLocation, id: Int): Option[T] = {
world(player, dimension) match {
case Some(world) =>
- val e = world.getEntityByID(id)
+ val e = world.getEntity(id)
if (e != null && classTag[T].runtimeClass.isAssignableFrom(e.getClass)) {
return Some(e.asInstanceOf[T])
}
@@ -114,34 +119,34 @@ abstract class PacketHandler {
None
}
- def readTileEntity[T: ClassTag](): Option[T] = {
- val dimension = readInt()
+ def readBlockEntity[T: ClassTag](): Option[T] = {
+ val dimension = new ResourceLocation(readUTF())
val x = readInt()
val y = readInt()
val z = readInt()
- getTileEntity(dimension, x, y, z)
+ getBlockEntity(dimension, x, y, z)
}
def readEntity[T: ClassTag](): Option[T] = {
- val dimension = readInt()
+ val dimension = new ResourceLocation(readUTF())
val id = readInt()
getEntity[T](dimension, id)
}
- def readDirection(): Option[EnumFacing] = readByte() match {
+ def readDirection(): Option[Direction] = readByte() match {
case id if id < 0 => None
- case id => Option(EnumFacing.getFront(id))
+ case id => Option(Direction.from3DDataValue(id))
}
def readItemStack(): ItemStack = {
val haveStack = readBoolean()
if (haveStack) {
- new ItemStack(readNBT())
+ ItemStack.of(readNBT())
}
else ItemStack.EMPTY
}
- def readNBT(): NBTTagCompound = {
+ def readNBT(): CompoundNBT = {
val haveNbt = readBoolean()
if (haveNbt) {
CompressedStreamTools.read(this)
@@ -151,5 +156,4 @@ abstract class PacketHandler {
def readPacketType() = PacketType(readByte())
}
-
}
diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala
index eaa0ca14ad..2e8728bb13 100644
--- a/src/main/scala/li/cil/oc/common/PacketType.scala
+++ b/src/main/scala/li/cil/oc/common/PacketType.scala
@@ -81,6 +81,7 @@ object PacketType extends Enumeration {
DronePower,
KeyDown,
KeyUp,
+ TextInput,
Clipboard,
MachineItemStateRequest,
MachineItemStateResponse,
diff --git a/src/main/scala/li/cil/oc/common/Proxy.scala b/src/main/scala/li/cil/oc/common/Proxy.scala
index 72c1b90ab8..9f7585da5b 100644
--- a/src/main/scala/li/cil/oc/common/Proxy.scala
+++ b/src/main/scala/li/cil/oc/common/Proxy.scala
@@ -1,70 +1,63 @@
package li.cil.oc.common
-import java.io.File
+import java.util.function.Supplier
import com.google.common.base.Strings
import li.cil.oc._
+import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
import li.cil.oc.common.capabilities.Capabilities
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.entity.Drone
+import li.cil.oc.common.entity.EntityTypes
import li.cil.oc.common.init.Blocks
import li.cil.oc.common.init.Items
-import li.cil.oc.common.item.Delegator
-import li.cil.oc.common.item.traits.Delegate
-import li.cil.oc.common.recipe.Recipes
+import li.cil.oc.common.tileentity.TileEntityTypes
+import li.cil.oc.common.recipe.RecipeSerializers
import li.cil.oc.integration.Mods
+import li.cil.oc.server
import li.cil.oc.server._
+import li.cil.oc.server.loot.LootFunctions
import li.cil.oc.server.machine.luac.LuaStateFactory
import li.cil.oc.server.machine.luac.NativeLua52Architecture
import li.cil.oc.server.machine.luac.NativeLua53Architecture
import li.cil.oc.server.machine.luaj.LuaJLuaArchitecture
import net.minecraft.block.Block
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.inventory.container.Container
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
+import net.minecraft.network.PacketBuffer
+import net.minecraft.tags.ItemTags
import net.minecraft.util.ResourceLocation
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.World
import net.minecraftforge.common.MinecraftForge
+import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.RegistryEvent.MissingMappings
-import net.minecraftforge.fml.common.FMLLog
-import net.minecraftforge.fml.common.event._
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.network.NetworkRegistry
-import net.minecraftforge.fml.common.registry.{EntityRegistry}
-import net.minecraftforge.oredict.OreDictionary
-
-import scala.collection.convert.WrapAsScala._
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
+import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent
+import net.minecraftforge.fml.network.NetworkEvent
+import net.minecraftforge.fml.network.NetworkRegistry
+import net.minecraftforge.registries.ForgeRegistries
+import net.minecraftforge.scorge.lang.ScorgeModLoadingContext
+
+import scala.jdk.CollectionConverters._
import scala.reflect.ClassTag
class Proxy {
- def preInit(e: FMLPreInitializationEvent) {
- checkForBrokenJavaVersion()
-
- Settings.load(new File(e.getModConfigurationDirectory, "opencomputers" + File.separator + "settings.conf"))
-
- MinecraftForge.EVENT_BUS.register(this)
-
- OpenComputers.log.debug("Initializing blocks and items.")
-
- Blocks.init()
- Items.init()
-
- OpenComputers.log.debug("Initializing additional OreDict entries.")
-
- OreDictionary.registerOre("craftingPiston", net.minecraft.init.Blocks.PISTON)
- OreDictionary.registerOre("craftingPiston", net.minecraft.init.Blocks.STICKY_PISTON)
- OreDictionary.registerOre("torchRedstoneActive", net.minecraft.init.Blocks.REDSTONE_TORCH)
- OreDictionary.registerOre("materialEnderPearl", net.minecraft.init.Items.ENDER_PEARL)
-
- // Make mods that use old wireless card name not have broken recipes
- OreDictionary.registerOre("oc:wlanCard", Items.get(Constants.ItemName.WirelessNetworkCardTier2).createItemStack(1))
-
- tryRegisterNugget[item.DiamondChip](Constants.ItemName.DiamondChip, "chipDiamond", net.minecraft.init.Items.DIAMOND, "gemDiamond")
-
- // Avoid issues with Extra Utilities registering colored obsidian as `obsidian`
- // oredict entry, but not normal obsidian, breaking some recipes.
- OreDictionary.registerOre("obsidian", net.minecraft.init.Blocks.OBSIDIAN)
-
- // To still allow using normal endstone for crafting drones.
- OreDictionary.registerOre("oc:stoneEndstone", net.minecraft.init.Blocks.END_STONE)
-
+ protected val modBus = ScorgeModLoadingContext.get.getModEventBus
+ modBus.register(classOf[ContainerTypes])
+ modBus.register(classOf[EntityTypes])
+ modBus.register(classOf[TileEntityTypes])
+ modBus.register(classOf[RecipeSerializers])
+ LootFunctions.init()
+
+ def preInit() {
OpenComputers.log.info("Initializing OpenComputers API.")
api.CreativeTab.instance = CreativeTab
@@ -98,67 +91,45 @@ class Proxy {
api.Machine.LuaArchitecture =
if (Settings.get.forceLuaJ) classOf[LuaJLuaArchitecture]
- else api.Machine.architectures.head
+ else api.Machine.architectures.asScala.head
}
- def init(e: FMLInitializationEvent) {
- OpenComputers.channel = NetworkRegistry.INSTANCE.newEventDrivenChannel("OpenComputers")
- OpenComputers.channel.register(server.PacketHandler)
-
- Loot.init()
- Achievement.init()
-
- EntityRegistry.registerModEntity(new ResourceLocation(Settings.resourceDomain, "drone"), classOf[Drone], "Drone", 0, OpenComputers, 80, 1, true)
-
- OpenComputers.log.debug("Initializing mod integration.")
- Mods.init()
-
- OpenComputers.log.debug("Initializing recipes.")
- Recipes.init()
-
- OpenComputers.log.info("Initializing capabilities.")
- Capabilities.init()
-
- api.API.isPowerEnabled = !Settings.get.ignorePower
+ @SubscribeEvent
+ def init(e: FMLCommonSetupEvent) {
+ e.enqueueWork((() => {
+ OpenComputers.channel = NetworkRegistry.newSimpleChannel(new ResourceLocation(OpenComputers.ID, "net_main"), () => "", "".equals(_), "".equals(_))
+ OpenComputers.channel.registerMessage(0, classOf[Array[Byte]],
+ (msg: Array[Byte], buff: PacketBuffer) => buff.writeByteArray(msg), _.readByteArray(),
+ (msg: Array[Byte], ctx: Supplier[NetworkEvent.Context]) => {
+ val context = ctx.get
+ context.enqueueWork(() => CommonPacketHandler.handlePacket(context.getDirection, msg, context.getSender))
+ context.setPacketHandled(true)
+ })
+ CommonPacketHandler.serverHandler = server.PacketHandler
+
+ Loot.init()
+ Achievement.init()
+
+ OpenComputers.log.debug("Initializing mod integration.")
+ Mods.init()
+
+ OpenComputers.log.info("Initializing capabilities.")
+ Capabilities.init()
+
+ api.API.isPowerEnabled = !Settings.get.ignorePower
+ }): Runnable)
}
- def postInit(e: FMLPostInitializationEvent) {
+ @SubscribeEvent
+ def postInit(e: FMLLoadCompleteEvent) {
// Don't allow driver registration after this point, to avoid issues.
driver.Registry.locked = true
}
- def tryRegisterNugget[TItem <: Delegate : ClassTag](nuggetItemName: String, nuggetOredictName: String, ingotItem: Item, ingotOredictName: String): Unit = {
- val nugget = Items.get(nuggetItemName).createItemStack(1)
-
- registerExclusive(nuggetOredictName, nugget)
-
- Delegator.subItem(nugget) match {
- case Some(subItem: TItem) =>
- if (OreDictionary.getOres(nuggetOredictName).exists(nugget.isItemEqual)) {
- Recipes.addSubItem(subItem, nuggetItemName)
- Recipes.addItem(ingotItem, ingotOredictName)
- }
- else {
- subItem.showInItemList = false
- }
- case _ =>
- }
- }
-
- def registerModel(instance: Delegate, id: String): Unit = {}
-
def registerModel(instance: Item, id: String): Unit = {}
def registerModel(instance: Block, id: String): Unit = {}
- private def registerExclusive(name: String, items: ItemStack*) {
- if (OreDictionary.getOres(name).isEmpty) {
- for (item <- items) {
- OreDictionary.registerOre(name, item)
- }
- }
- }
-
// Yes, this could be boiled down even further, but I like to keep it
// explicit like this, because it makes it a) clearer, b) easier to
// extend, in case that should ever be needed.
@@ -177,11 +148,11 @@ class Proxy {
@SubscribeEvent
def missingBlockMappings(e: MissingMappings[Block]) {
- for (missing <- e.getMappings) {
- blockRenames.get(missing.key.getResourcePath) match {
+ for (missing <- e.getMappings(OpenComputers.ID).asScala) {
+ blockRenames.get(missing.key.getPath) match {
case Some(name) =>
if (Strings.isNullOrEmpty(name)) missing.ignore()
- else missing.remap(Block.REGISTRY.getObject(new ResourceLocation(OpenComputers.ID, name)))
+ else missing.remap(ForgeRegistries.BLOCKS.getValue(new ResourceLocation(OpenComputers.ID, name)))
case _ => missing.warn()
}
}
@@ -189,27 +160,13 @@ class Proxy {
@SubscribeEvent
def missingItemMappings(e: MissingMappings[Item]) {
- for (missing <- e.getMappings) {
- itemRenames.get(missing.key.getResourcePath) match {
+ for (missing <- e.getMappings(OpenComputers.ID).asScala) {
+ itemRenames.get(missing.key.getPath) match {
case Some(name) =>
if (Strings.isNullOrEmpty(name)) missing.ignore()
- else missing.remap(Item.REGISTRY.getObject(new ResourceLocation(OpenComputers.ID, name)))
+ else missing.remap(ForgeRegistries.ITEMS.getValue(new ResourceLocation(OpenComputers.ID, name)))
case _ => missing.warn()
}
}
}
-
- // OK, seriously now, I've gotten one too many bug reports because of this Java version being broken.
-
- private final val BrokenJavaVersions = Set("1.6.0_65, Apple Inc.")
-
- def isBrokenJavaVersion = {
- val javaVersion = System.getProperty("java.version") + ", " + System.getProperty("java.vendor")
- BrokenJavaVersions.contains(javaVersion)
- }
-
- def checkForBrokenJavaVersion() = if (isBrokenJavaVersion) {
- FMLLog.bigWarning("You're using a broken Java version! Please update now, or remove OpenComputers. DO NOT REPORT THIS! UPDATE YOUR JAVA!")
- throw new Exception("You're using a broken Java version! Please update now, or remove OpenComputers. DO NOT REPORT THIS! UPDATE YOUR JAVA!")
- }
}
diff --git a/src/main/scala/li/cil/oc/common/SaveHandler.scala b/src/main/scala/li/cil/oc/common/SaveHandler.scala
index 5dfd4bc9ce..332277d699 100644
--- a/src/main/scala/li/cil/oc/common/SaveHandler.scala
+++ b/src/main/scala/li/cil/oc/common/SaveHandler.scala
@@ -18,13 +18,15 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.SafeThreadPool
import li.cil.oc.util.ThreadPoolFactory
import net.minecraft.nbt.CompressedStreamTools
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.ChunkPos
import net.minecraft.world.World
-import net.minecraftforge.common.DimensionManager
+import net.minecraft.world.storage.FolderName
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.eventhandler.EventPriority
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.EventPriority
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.fml.server.ServerLifecycleHooks
import org.apache.commons.lang3.JavaVersion
import org.apache.commons.lang3.SystemUtils
@@ -48,10 +50,10 @@ object SaveHandler {
// which takes a lot of time and is completely unnecessary in those cases.
var savingForClients = false
- class SaveDataEntry(val data: Array[Byte], val pos: ChunkPos, val name: String, val dimension: Int) extends Runnable {
+ class SaveDataEntry(val data: Array[Byte], val pos: ChunkPos, val name: String, val dimension: ResourceLocation) extends Runnable {
override def run(): Unit = {
val path = statePath
- val dimPath = new io.File(path, dimension.toString)
+ val dimPath = new io.File(path, dimension.toString.replace(':', '/').replace('.', '/'))
val chunkPath = new io.File(dimPath, s"${this.pos.x}.${this.pos.z}")
chunkDirs.add(chunkPath)
if (!chunkPath.exists()) {
@@ -75,46 +77,46 @@ object SaveHandler {
val chunkDirs = new ConcurrentLinkedDeque[io.File]()
val saving = mutable.HashMap.empty[String, Future[_]]
- def savePath = new io.File(DimensionManager.getCurrentSaveRootDirectory, Settings.savePath)
+ def savePath = ServerLifecycleHooks.getCurrentServer.getWorldPath(new FolderName(Settings.savePath)).toFile
def statePath = new io.File(savePath, "state")
- def scheduleSave(host: MachineHost, nbt: NBTTagCompound, name: String, data: Array[Byte]) {
+ def scheduleSave(host: MachineHost, nbt: CompoundNBT, name: String, data: Array[Byte]) {
scheduleSave(BlockPosition(host), nbt, name, data)
}
- def scheduleSave(host: MachineHost, nbt: NBTTagCompound, name: String, save: NBTTagCompound => Unit) {
+ def scheduleSave(host: MachineHost, nbt: CompoundNBT, name: String, save: CompoundNBT => Unit) {
scheduleSave(host, nbt, name, writeNBT(save))
}
- def scheduleSave(host: EnvironmentHost, nbt: NBTTagCompound, name: String, save: NBTTagCompound => Unit) {
+ def scheduleSave(host: EnvironmentHost, nbt: CompoundNBT, name: String, save: CompoundNBT => Unit) {
scheduleSave(BlockPosition(host), nbt, name, writeNBT(save))
}
- def scheduleSave(world: World, x: Double, z: Double, nbt: NBTTagCompound, name: String, data: Array[Byte]) {
+ def scheduleSave(world: World, x: Double, z: Double, nbt: CompoundNBT, name: String, data: Array[Byte]) {
scheduleSave(BlockPosition(x, 0, z, world), nbt, name, data)
}
- def scheduleSave(world: World, x: Double, z: Double, nbt: NBTTagCompound, name: String, save: NBTTagCompound => Unit) {
+ def scheduleSave(world: World, x: Double, z: Double, nbt: CompoundNBT, name: String, save: CompoundNBT => Unit) {
scheduleSave(world, x, z, nbt, name, writeNBT(save))
}
- def scheduleSave(position: BlockPosition, nbt: NBTTagCompound, name: String, data: Array[Byte]) {
+ def scheduleSave(position: BlockPosition, nbt: CompoundNBT, name: String, data: Array[Byte]) {
val world = position.world.get
- val dimension = world.provider.getDimension
+ val dimension = world.dimension.location
val chunk = new ChunkPos(position.x >> 4, position.z >> 4)
// We have to save the dimension and chunk coordinates, because they are
// not available on load / may have changed if the computer was moved.
- nbt.setInteger("dimension", dimension)
- nbt.setInteger("chunkX", chunk.x)
- nbt.setInteger("chunkZ", chunk.z)
+ nbt.putString("dimension", dimension.toString)
+ nbt.putInt("chunkX", chunk.x)
+ nbt.putInt("chunkZ", chunk.z)
scheduleSave(dimension, chunk, name, data)
}
- private def writeNBT(save: NBTTagCompound => Unit) = {
- val tmpNbt = new NBTTagCompound()
+ private def writeNBT(save: CompoundNBT => Unit) = {
+ val tmpNbt = new CompoundNBT()
save(tmpNbt)
val baos = new ByteArrayOutputStream()
val dos = new DataOutputStream(baos)
@@ -122,7 +124,7 @@ object SaveHandler {
baos.toByteArray
}
- def loadNBT(nbt: NBTTagCompound, name: String): NBTTagCompound = {
+ def loadNBT(nbt: CompoundNBT, name: String): CompoundNBT = {
val data = load(nbt, name)
if (data.length > 0) try {
val bais = new ByteArrayInputStream(data)
@@ -132,17 +134,17 @@ object SaveHandler {
catch {
case t: Throwable =>
OpenComputers.log.warn("There was an error trying to restore a block's state from external data. This indicates that data was somehow corrupted.", t)
- new NBTTagCompound()
+ new CompoundNBT()
}
- else new NBTTagCompound()
+ else new CompoundNBT()
}
- def load(nbt: NBTTagCompound, name: String): Array[Byte] = {
+ def load(nbt: CompoundNBT, name: String): Array[Byte] = {
// Since we have no world yet, we rely on the dimension we were saved in.
// Same goes for the chunk. This also works around issues with computers
// being moved (e.g. Redstone in Motion).
- val dimension = nbt.getInteger("dimension")
- val chunk = new ChunkPos(nbt.getInteger("chunkX"), nbt.getInteger("chunkZ"))
+ val dimension = nbt.getString("dimension")
+ val chunk = new ChunkPos(nbt.getInt("chunkX"), nbt.getInt("chunkZ"))
// Wait for the latest save task for the requested file to complete.
// This prevents the chance of loading an outdated version
@@ -155,10 +157,10 @@ object SaveHandler {
})
saving.remove(name)
- load(dimension, chunk, name)
+ load(new ResourceLocation(dimension), chunk, name)
}
- def scheduleSave(dimension: Int, chunk: ChunkPos, name: String, data: Array[Byte]): Unit = {
+ def scheduleSave(dimension: ResourceLocation, chunk: ChunkPos, name: String, data: Array[Byte]): Unit = {
if (chunk == null) throw new IllegalArgumentException("chunk is null")
else {
// Disregarding whether or not there already was a
@@ -169,11 +171,11 @@ object SaveHandler {
}
}
- def load(dimension: Int, chunk: ChunkPos, name: String): Array[Byte] = {
+ def load(dimension: ResourceLocation, chunk: ChunkPos, name: String): Array[Byte] = {
if (chunk == null) throw new IllegalArgumentException("chunk is null")
val path = statePath
- val dimPath = new io.File(path, dimension.toString)
+ val dimPath = new io.File(path, dimension.toString.replace(':', '/').replace('.', '/'))
val chunkPath = new io.File(dimPath, s"${chunk.x}.${chunk.z}")
val file = new io.File(chunkPath, name)
if (!file.exists()) return Array.empty[Byte]
@@ -219,7 +221,7 @@ object SaveHandler {
@SubscribeEvent(priority = EventPriority.HIGHEST)
def onWorldLoad(e: WorldEvent.Load) {
- if (!e.getWorld.isRemote) {
+ if (!e.getWorld.isClientSide) {
// Touch all externally saved data when loading, to avoid it getting
// deleted in the next save (because the now - save time will usually
// be larger than the time out after loading a world again).
diff --git a/src/main/scala/li/cil/oc/common/ToolDurabilityProviders.scala b/src/main/scala/li/cil/oc/common/ToolDurabilityProviders.scala
index 23b6dda932..20d0a65c05 100644
--- a/src/main/scala/li/cil/oc/common/ToolDurabilityProviders.scala
+++ b/src/main/scala/li/cil/oc/common/ToolDurabilityProviders.scala
@@ -17,7 +17,7 @@ object ToolDurabilityProviders {
if (!durability.isNaN) return Option(durability)
}
// Fall back to vanilla damage values.
- if (stack.isItemStackDamageable) Option(1.0 - stack.getItemDamage.toDouble / stack.getMaxDamage.toDouble)
+ if (stack.getItem.canBeDepleted) Option(1.0 - stack.getDamageValue.toDouble / stack.getMaxDamage.toDouble)
else None
}
}
diff --git a/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala b/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala
deleted file mode 100644
index ff9c1aa9d3..0000000000
--- a/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala
+++ /dev/null
@@ -1,415 +0,0 @@
-package li.cil.oc.common.asm
-
-import li.cil.oc.common.asm.template.SimpleComponentImpl
-import li.cil.oc.integration.Mods
-import net.minecraft.launchwrapper.IClassTransformer
-import net.minecraft.launchwrapper.LaunchClassLoader
-import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper
-import org.apache.logging.log4j.LogManager
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.ClassWriter
-import org.objectweb.asm.Opcodes
-import org.objectweb.asm.tree._
-
-import scala.annotation.tailrec
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
-
-object ObfNames {
- final val Class_EntityHanging = Array("net/minecraft/entity/EntityHanging")
- final val Class_EntityLiving = Array("net/minecraft/entity/EntityLiving")
- final val Class_RenderLiving = Array("net/minecraft/client/renderer/entity/RenderLiving")
- final val Class_TileEntity = Array("net/minecraft/tileentity/TileEntity")
- final val Field_leashNBTTag = Array("leashNBTTag", "field_110170_bx")
- final val Field_leashedToEntity = Array("leashedToEntity", "leashHolder", "field_110168_bw")
- final val Method_recreateLeash = Array("recreateLeash", "func_110165_bF")
- final val Method_recreateLeashDesc = Array("()V")
- final val Method_renderLeash = Array("renderLeash", "func_110827_b")
- final val Method_renderLeashDesc = Array("(Lnet/minecraft/entity/EntityLiving;DDDFF)V")
- final val Method_validate = Array("validate", "func_145829_t")
- final val Method_invalidate = Array("invalidate", "func_145843_s")
- final val Method_onChunkUnload = Array("onChunkUnload", "func_76623_d")
- final val Method_readFromNBT = Array("readFromNBT", "func_145839_a")
- final val Method_writeToNBT = Array("writeToNBT", "func_189515_b")
-}
-
-object ClassTransformer {
- var hadErrors = false
- var hadSimpleComponentErrors = false
-}
-
-class ClassTransformer extends IClassTransformer {
- private val loader = classOf[ClassTransformer].getClassLoader.asInstanceOf[LaunchClassLoader]
- private val log = LogManager.getLogger("OpenComputers")
-
- override def transform(obfName: String, name: String, basicClass: Array[Byte]): Array[Byte] = {
- if (basicClass == null || name.startsWith("scala.")) return basicClass
- var transformedClass = basicClass
- try {
- if (!name.startsWith("net.minecraft.")
- && !name.startsWith("net.minecraftforge.")
- && !name.startsWith("li.cil.oc.common.asm.")
- && !name.startsWith("li.cil.oc.integration.")) {
- if (name.startsWith("li.cil.oc.")) {
- // Strip foreign interfaces from scala generated classes. This is
- // primarily intended to clean up mix-ins / synthetic classes
- // generated by Scala.
- val classNode = newClassNode(transformedClass)
- val missingInterfaces = classNode.interfaces.filter(!classExists(_))
- for (interfaceName <- missingInterfaces) {
- log.trace(s"Stripping interface $interfaceName from class $name because it is missing.")
- }
- classNode.interfaces.removeAll(missingInterfaces)
-
- val missingClasses = classNode.innerClasses.filter(clazz => clazz.outerName != null && !classExists(clazz.outerName))
- for (innerClass <- missingClasses) {
- log.trace(s"Stripping inner class ${innerClass.name} from class $name because its type ${innerClass.outerName} is missing.")
- }
- classNode.innerClasses.removeAll(missingClasses)
-
- val incompleteMethods = classNode.methods.filter(method => missingFromSignature(method.desc).nonEmpty)
- for (method <- incompleteMethods) {
- val missing = missingFromSignature(method.desc).mkString(", ")
- log.trace(s"Stripping method ${method.name} from class $name because the following types in its signature are missing: $missing")
- }
- classNode.methods.removeAll(incompleteMethods)
-
- // Inject available interfaces where requested.
- if (classNode.visibleAnnotations != null) {
- def injectInterface(annotation: AnnotationNode): Unit = {
- val values = annotation.values.grouped(2).map(buffer => buffer.head -> buffer.last).toMap
- (values.get("value"), values.get("modid")) match {
- case (Some(interfaceName: String), Some(modid: String)) =>
- Mods.All.find(_.id == modid) match {
- case Some(mod) =>
- if (mod.isModAvailable) {
- val interfaceDesc = interfaceName.replaceAllLiterally(".", "/")
- val node = classNodeFor(interfaceDesc)
- if (node == null) {
- log.warn(s"Interface $interfaceName not found, skipping injection.")
- }
- else {
- val missing = node.methods.filterNot(im => classNode.methods.exists(cm => im.name == cm.name && im.desc == cm.desc)).map(method => s"Missing implementation of ${method.name + method.desc}")
- if (missing.isEmpty) {
- log.info(s"Injecting interface $interfaceName into $name.")
- classNode.interfaces.add(interfaceDesc)
- }
- else {
- log.warn(s"Missing implementations for interface $interfaceName, skipping injection.")
- missing.foreach(log.warn)
- ClassTransformer.hadErrors = true
- }
- }
- }
- else {
- log.info(s"Skipping interface $interfaceName from missing mod $modid.")
- }
- case _ =>
- log.warn(s"Skipping interface $interfaceName from unknown mod $modid.")
- ClassTransformer.hadErrors = true
- }
- case _ =>
- }
- }
- classNode.visibleAnnotations.find(_.desc == "Lli/cil/oc/common/asm/Injectable$Interface;") match {
- case Some(annotation) =>
- injectInterface(annotation)
- case _ =>
- }
- classNode.visibleAnnotations.find(_.desc == "Lli/cil/oc/common/asm/Injectable$InterfaceList;") match {
- case Some(annotation) =>
- val values = annotation.values.grouped(2).map(buffer => buffer.head -> buffer.last).toMap
- values.get("value") match {
- case Some(interfaceList: java.lang.Iterable[AnnotationNode]@unchecked) =>
- interfaceList.foreach(injectInterface)
- case _ =>
- }
- case _ =>
- }
- }
-
- transformedClass = writeClass(classNode)
- }
- {
- val classNode = newClassNode(transformedClass)
- if (classNode.interfaces.contains("li/cil/oc/api/network/SimpleComponent") &&
- (classNode.visibleAnnotations == null || !classNode.visibleAnnotations.
- exists(annotation => annotation != null && annotation.desc == "Lli/cil/oc/api/network/SimpleComponent$SkipInjection;"))) {
- try {
- transformedClass = injectEnvironmentImplementation(classNode)
- log.info(s"Successfully injected component logic into class $name.")
- }
- catch {
- case e: Throwable =>
- log.warn(s"Failed injecting component logic into class $name.", e)
- ClassTransformer.hadSimpleComponentErrors = true
- }
- }
- }
- }
-
- // Inject some code into the EntityLiving classes recreateLeash method to allow
- // proper loading of leashes tied to entities using the leash upgrade. This is
- // necessary because entities only save the entity they are leashed to if that
- // entity is an EntityLivingBase - which drones, for example, are not, for good
- // reason. We work around this by re-leashing them in the load method of the
- // leash upgrade. The leashed entity would then still unleash itself and, more
- // problematically drop a leash item. To avoid this, we extend the
- // if (this.isLeashed && this.field_110170_bx != null)
- // check to read
- // if (this.isLeashed && this.field_110170_bx != null && this.leashedToEntity == null)
- // which should not interfere with any existing logic, but avoid leashing
- // restored manually in the load phase to not be broken again.
- if (ObfNames.Class_EntityLiving.contains(name.replace('.', '/'))) {
- val classNode = newClassNode(transformedClass)
- insertInto(classNode, ObfNames.Method_recreateLeash, ObfNames.Method_recreateLeashDesc, instructions => instructions.toArray.sliding(3, 1).exists {
- case Array(varNode: VarInsnNode, fieldNode: FieldInsnNode, jumpNode: JumpInsnNode)
- if varNode.getOpcode == Opcodes.ALOAD && varNode.`var` == 0 &&
- fieldNode.getOpcode == Opcodes.GETFIELD && ObfNames.Field_leashNBTTag.contains(fieldNode.name) &&
- jumpNode.getOpcode == Opcodes.IFNULL =>
- classNode.fields.find(field => ObfNames.Field_leashedToEntity.contains(field.name)) match {
- case Some(field) =>
- val toInject = new InsnList()
- toInject.add(new VarInsnNode(Opcodes.ALOAD, 0))
- toInject.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, field.name, field.desc))
- toInject.add(new JumpInsnNode(Opcodes.IFNONNULL, jumpNode.label))
- instructions.insert(jumpNode, toInject)
- true
- case _ =>
- false
- }
- case _ =>
- false
- }) match {
- case Some(data) => transformedClass = data
- case _ =>
- }
- }
-
- // Little change to the renderer used to render leashes to center it on drones.
- // This injects the code
- // if (entity instanceof Drone) {
- // d5 = 0.0;
- // d6 = 0.0;
- // d7 = -0.25;
- // }
- // before the `instanceof EntityHanging` check in func_110827_b.
- if (ObfNames.Class_RenderLiving.contains(name.replace('.', '/'))) {
- val classNode = newClassNode(transformedClass)
- insertInto(classNode, ObfNames.Method_renderLeash, ObfNames.Method_renderLeashDesc, instructions => instructions.toArray.sliding(3, 1).exists {
- case Array(varNode: VarInsnNode, typeNode: TypeInsnNode, jumpNode: JumpInsnNode)
- if varNode.getOpcode == Opcodes.ALOAD && varNode.`var` == 10 &&
- typeNode.getOpcode == Opcodes.INSTANCEOF && ObfNames.Class_EntityHanging.contains(typeNode.desc) &&
- jumpNode.getOpcode == Opcodes.IFEQ =>
- val toInject = new InsnList()
- toInject.add(new VarInsnNode(Opcodes.ALOAD, 10))
- toInject.add(new TypeInsnNode(Opcodes.INSTANCEOF, "li/cil/oc/common/entity/Drone"))
- val skip = new LabelNode()
- toInject.add(new JumpInsnNode(Opcodes.IFEQ, skip))
- toInject.add(new LdcInsnNode(Double.box(0.0)))
- toInject.add(new VarInsnNode(Opcodes.DSTORE, 17))
- toInject.add(new LdcInsnNode(Double.box(0.0)))
- toInject.add(new VarInsnNode(Opcodes.DSTORE, 19))
- toInject.add(new LdcInsnNode(Double.box(-0.25)))
- toInject.add(new VarInsnNode(Opcodes.DSTORE, 21))
- toInject.add(skip)
- instructions.insertBefore(varNode, toInject)
- true
- case _ =>
- false
- }) match {
- case Some(data) => transformedClass = data
- case _ =>
- }
- }
-
- transformedClass
- }
- catch {
- case t: Throwable =>
- log.warn("Something went wrong!", t)
- ClassTransformer.hadErrors = true
- basicClass
- }
- }
-
- private def insertInto(classNode: ClassNode, methodNames: Array[String], methodDescs: Array[String], inserter: (InsnList) => Boolean): Option[Array[Byte]] = {
- classNode.methods.find(method => methodNames.contains(method.name) && methodDescs.contains(method.desc)) match {
- case Some(methodNode) =>
- if (inserter(methodNode.instructions)) {
- log.info(s"Successfully patched ${classNode.name}.${methodNames(0)}.")
- Option(writeClass(classNode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES))
- }
- else {
- log.warn(s"Failed patching ${classNode.name}.${methodNames(0)}, injection point not found.")
- ClassTransformer.hadErrors = true
- None
- }
- case _ =>
- log.warn(s"Failed patching ${classNode.name}.${methodNames(0)}, method not found.")
- ClassTransformer.hadErrors = true
- None
- }
- }
-
- private def classExists(name: String) = {
- loader.getClassBytes(name) != null ||
- loader.getClassBytes(FMLDeobfuscatingRemapper.INSTANCE.unmap(name)) != null ||
- (try loader.findClass(name.replace('/', '.')) != null catch {
- case _: ClassNotFoundException => false
- })
- }
-
- private def missingFromSignature(desc: String) = {
- """L([^;]+);""".r.findAllMatchIn(desc).map(_.group(1)).filter(!classExists(_))
- }
-
- def injectEnvironmentImplementation(classNode: ClassNode): Array[Byte] = {
- log.trace(s"Injecting methods from Environment interface into ${classNode.name}.")
- if (!isTileEntity(classNode)) {
- throw new InjectionFailedException("Found SimpleComponent on something that isn't a tile entity, ignoring.")
- }
-
- val template = classNodeFor("li/cil/oc/common/asm/template/SimpleEnvironment")
- if (template == null) {
- throw new InjectionFailedException("Could not find SimpleComponent template!")
- }
-
- def inject(methodName: String, signature: String, required: Boolean = false) {
- def filter(method: MethodNode) = method.name == methodName && method.desc == signature
- if (classNode.methods.exists(filter)) {
- if (required) {
- throw new InjectionFailedException(s"Could not inject method '$methodName$signature' because it was already present!")
- }
- }
- else template.methods.find(filter) match {
- case Some(method) => classNode.methods.add(method)
- case _ => throw new AssertionError()
- }
- }
- inject("node", "()Lli/cil/oc/api/network/Node;", required = true)
- inject("onConnect", "(Lli/cil/oc/api/network/Node;)V")
- inject("onDisconnect", "(Lli/cil/oc/api/network/Node;)V")
- inject("onMessage", "(Lli/cil/oc/api/network/Message;)V")
-
- log.trace("Injecting / wrapping overrides for required tile entity methods.")
- def replace(methodName: String, methodNameSrg: String, desc: String) {
- val mapper = FMLDeobfuscatingRemapper.INSTANCE
- def filter(method: MethodNode) = {
- val descDeObf = mapper.mapMethodDesc(method.desc)
- val methodNameDeObf = mapper.mapMethodName(mapper.unmap(ObfNames.Class_TileEntity(0)), method.name, method.desc)
- val areSamePlain = method.name + descDeObf == methodName + desc
- val areSameDeObf = methodNameDeObf + descDeObf == methodNameSrg + desc
- areSamePlain || areSameDeObf
- }
- if (classNode.methods.exists(method => method.name == methodName + SimpleComponentImpl.PostFix && mapper.mapMethodDesc(method.desc) == desc)) {
- throw new InjectionFailedException(s"Delegator method name '${methodName + SimpleComponentImpl.PostFix}' is already in use.")
- }
- classNode.methods.find(filter) match {
- case Some(method) =>
- log.trace(s"Found original implementation of '$methodName', wrapping.")
- method.name = methodName + SimpleComponentImpl.PostFix
- case _ =>
- log.trace(s"No original implementation of '$methodName', will inject override.")
- @tailrec def ensureNonFinalIn(name: String) {
- if (name != null) {
- val node = classNodeFor(name)
- if (node != null) {
- node.methods.find(filter) match {
- case Some(method) =>
- if ((method.access & Opcodes.ACC_FINAL) != 0) {
- throw new InjectionFailedException(s"Method '$methodName' is final in superclass ${node.name.replace('/', '.')}.")
- }
- case _ =>
- }
- ensureNonFinalIn(node.superName)
- }
- }
- }
- ensureNonFinalIn(classNode.superName)
- template.methods.find(_.name == methodName + SimpleComponentImpl.PostFix) match {
- case Some(method) => classNode.methods.add(method)
- case _ => throw new AssertionError(s"Couldn't find '${methodName + SimpleComponentImpl.PostFix}' in template implementation.")
- }
- }
- template.methods.find(filter) match {
- case Some(method) => classNode.methods.add(method)
- case _ => throw new AssertionError(s"Couldn't find '$methodName' in template implementation.")
- }
- }
- replace(ObfNames.Method_validate(0), ObfNames.Method_validate(1), "()V")
- replace(ObfNames.Method_invalidate(0), ObfNames.Method_invalidate(1), "()V")
- replace(ObfNames.Method_onChunkUnload(0), ObfNames.Method_onChunkUnload(1), "()V")
- replace(ObfNames.Method_readFromNBT(0), ObfNames.Method_readFromNBT(1), "(Lnet/minecraft/nbt/NBTTagCompound;)V")
- replace(ObfNames.Method_writeToNBT(0), ObfNames.Method_writeToNBT(1), "(Lnet/minecraft/nbt/NBTTagCompound;)Lnet/minecraft/nbt/NBTTagCompound;")
-
- log.trace("Injecting interface.")
- classNode.interfaces.add("li/cil/oc/common/asm/template/SimpleComponentImpl")
-
- writeClass(classNode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES)
- }
-
- @tailrec final def isTileEntity(classNode: ClassNode): Boolean = {
- if (classNode == null) false
- else {
- log.trace(s"Checking if class ${classNode.name} is a TileEntity...")
- ObfNames.Class_TileEntity.contains(FMLDeobfuscatingRemapper.INSTANCE.map(classNode.name)) ||
- (classNode.superName != null && isTileEntity(classNodeFor(classNode.superName)))
- }
- }
-
- @tailrec final def isAssignable(parent: ClassNode, child: ClassNode): Boolean = parent != null && child != null && !isFinal(parent) && {
- parent.name == "java/lang/Object" ||
- parent.name == child.name ||
- parent.name == child.superName ||
- child.interfaces.contains(parent.name) ||
- (child.superName != null && isAssignable(parent, classNodeFor(child.superName)))
- }
-
- def isFinal(node: ClassNode): Boolean = (node.access & Opcodes.ACC_FINAL) != 0
-
- def isInterface(node: ClassNode): Boolean = node != null && (node.access & Opcodes.ACC_INTERFACE) != 0
-
- def classNodeFor(name: String) = {
- val namePlain = name.replace('/', '.')
- val bytes = loader.getClassBytes(namePlain)
- if (bytes != null) newClassNode(bytes)
- else {
- val nameObfed = FMLDeobfuscatingRemapper.INSTANCE.unmap(name).replace('/', '.')
- val bytes = loader.getClassBytes(nameObfed)
- if (bytes == null) null
- else newClassNode(bytes)
- }
- }
-
- def newClassNode(data: Array[Byte]) = {
- val classNode = new ClassNode()
- new ClassReader(data).accept(classNode, 0)
- classNode
- }
-
- def writeClass(classNode: ClassNode, flags: Int = ClassWriter.COMPUTE_MAXS) = {
- val writer = new ClassWriter(flags) {
- // Implementation without class loads, avoids https://github.com/MinecraftForge/FML/issues/655
- override def getCommonSuperClass(type1: String, type2: String): String = {
- val node1 = classNodeFor(type1)
- val node2 = classNodeFor(type2)
- if (isAssignable(node1, node2)) node1.name
- else if (isAssignable(node2, node1)) node2.name
- else if (isInterface(node1) || isInterface(node2)) "java/lang/Object"
- else {
- var parent = Option(node1).map(_.superName).map(classNodeFor).orNull
- while (parent != null && parent.superName != null && !isAssignable(parent, node2)) {
- parent = classNodeFor(parent.superName)
- }
- if (parent == null) "java/lang/Object" else parent.name
- }
- }
- }
- classNode.accept(writer)
- writer.toByteArray
- }
-
- class InjectionFailedException(message: String) extends Exception(message)
-
-}
diff --git a/src/main/scala/li/cil/oc/common/asm/Injectable.java b/src/main/scala/li/cil/oc/common/asm/Injectable.java
deleted file mode 100644
index f08dba3208..0000000000
--- a/src/main/scala/li/cil/oc/common/asm/Injectable.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package li.cil.oc.common.asm;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This interface is kind of the opposite to FML's Optional annotations.
- *
- * Instead of stripping interfaces if they are not present, it will inject them
- * when they are present. This helps with some strange cases where
- * stripping does not work as it should.
- */
-public final class Injectable {
- /**
- * Not constructable.
- */
- private Injectable() {
- }
-
- /**
- * Mark a list of interfaces as injectable.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface InterfaceList {
- public Interface[] value();
- }
-
- /**
- * Used to inject optional interfaces.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface Interface {
- /**
- * The fully qualified name of the interface to inject.
- */
- public String value();
-
- /**
- * The modid that is required to be present for the injecting to occur.
- *
- * Note that injection will not occur if the interface is not fully
- * implemented.
- */
- public String modid();
- }
-}
diff --git a/src/main/scala/li/cil/oc/common/block/Adapter.scala b/src/main/scala/li/cil/oc/common/block/Adapter.scala
index 8f4e66152b..38c086d9df 100644
--- a/src/main/scala/li/cil/oc/common/block/Adapter.scala
+++ b/src/main/scala/li/cil/oc/common/block/Adapter.scala
@@ -1,53 +1,60 @@
package li.cil.oc.common.block
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.Wrench
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.world.IBlockReader
+import net.minecraft.world.IWorldReader
import net.minecraft.world.World
-class Adapter extends SimpleBlock with traits.GUI {
- override def guiType = GuiType.Adapter
+class Adapter(props: Properties) extends SimpleBlock(props) with traits.GUI {
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Adapter => ContainerTypes.openAdapterGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Adapter()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Adapter(tileentity.TileEntityTypes.ADAPTER)
// ----------------------------------------------------------------------- //
- override def neighborChanged(state: IBlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos): Unit =
- world.getTileEntity(pos) match {
+ @Deprecated
+ override def neighborChanged(state: BlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos, b: Boolean): Unit =
+ world.getBlockEntity(pos) match {
case adapter: tileentity.Adapter => adapter.neighborChanged()
case _ => // Ignore.
}
- override def onNeighborChange(world: IBlockAccess, pos: BlockPos, neighbor: BlockPos) =
- world.getTileEntity(pos) match {
+ override def onNeighborChange(state: BlockState, world: IWorldReader, pos: BlockPos, neighbor: BlockPos) =
+ world.getBlockEntity(pos) match {
case adapter: tileentity.Adapter =>
// TODO can we just pass the blockpos?
val side =
- if (neighbor == pos.down()) EnumFacing.DOWN
- else if (neighbor == pos.up()) EnumFacing.UP
- else if (neighbor == pos.north()) EnumFacing.NORTH
- else if (neighbor == pos.south()) EnumFacing.SOUTH
- else if (neighbor == pos.west()) EnumFacing.WEST
- else if (neighbor == pos.east()) EnumFacing.EAST
+ if (neighbor == (pos.below():BlockPos)) Direction.DOWN
+ else if (neighbor == (pos.above():BlockPos)) Direction.UP
+ else if (neighbor == pos.north()) Direction.NORTH
+ else if (neighbor == pos.south()) Direction.SOUTH
+ else if (neighbor == pos.west()) Direction.WEST
+ else if (neighbor == pos.east()) Direction.EAST
else throw new IllegalArgumentException("not a neighbor") // TODO wat
adapter.neighborChanged(side)
case _ => // Ignore.
}
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
if (Wrench.holdsApplicableWrench(player, pos)) {
- val sideToToggle = if (player.isSneaking) side.getOpposite else side
- world.getTileEntity(pos) match {
+ val sideToToggle = if (player.isCrouching) side.getOpposite else side
+ world.getBlockEntity(pos) match {
case adapter: tileentity.Adapter =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
val oldValue = adapter.openSides(sideToToggle.ordinal())
adapter.setSideOpen(sideToToggle, !oldValue)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Assembler.scala b/src/main/scala/li/cil/oc/common/block/Assembler.scala
index f79f960e20..052b8b2da0 100644
--- a/src/main/scala/li/cil/oc/common/block/Assembler.scala
+++ b/src/main/scala/li/cil/oc/common/block/Assembler.scala
@@ -1,28 +1,35 @@
package li.cil.oc.common.block
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.util.EnumFacing
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Assembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI {
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN || side == EnumFacing.UP
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN || side == EnumFacing.UP
+class Assembler(props: Properties) extends SimpleBlock(props) with traits.PowerAcceptor with traits.StateAware with traits.GUI {
+ override def energyThroughput = Settings.get.assemblerRate
- // ----------------------------------------------------------------------- //
+ val blockShape = {
+ val bottom = Block.box(0, 0, 0, 16, 7, 16)
+ val mid = Block.box(2, 7, 2, 14, 9, 14)
+ val top = Block.box(0, 9, 0, 16, 16, 16)
+ VoxelShapes.or(top, bottom, mid)
+ }
- override def energyThroughput = Settings.get.assemblerRate
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = blockShape
- override def guiType = GuiType.Assembler
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Assembler => ContainerTypes.openAssemblerGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Assembler()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Assembler(tileentity.TileEntityTypes.ASSEMBLER)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Cable.scala b/src/main/scala/li/cil/oc/common/block/Cable.scala
index cd6f2314d3..2431469a7f 100644
--- a/src/main/scala/li/cil/oc/common/block/Cable.scala
+++ b/src/main/scala/li/cil/oc/common/block/Cable.scala
@@ -2,27 +2,35 @@ package li.cil.oc.common.block
import java.util
-import li.cil.oc.common.block.property.UnlistedInteger
+import li.cil.oc.common.block.property.PropertyCableConnection
import li.cil.oc.common.capabilities.Capabilities
import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
+import li.cil.oc.util.ExtendedWorld._
+import li.cil.oc.util.ItemColorizer
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.{Entity, EntityLivingBase}
-import net.minecraft.item.{EnumDyeColor, ItemStack}
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.{Entity, LivingEntity}
+import net.minecraft.item.{BlockItemUseContext, DyeColor, ItemStack}
+import net.minecraft.state.StateContainer
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.{AxisAlignedBB, BlockPos, RayTraceResult, Vec3d}
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.Direction
+import net.minecraft.util.math.{BlockPos, RayTraceResult}
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.world.IBlockReader
+import net.minecraft.world.IWorld
import net.minecraft.world.World
-import net.minecraftforge.common.property.ExtendedBlockState
-import net.minecraftforge.common.property.IExtendedBlockState
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.common.extensions.IForgeBlock
-import scala.collection.JavaConversions._
+import scala.collection.JavaConverters._
import scala.reflect.ClassTag
-class Cable(protected implicit val tileTag: ClassTag[tileentity.Cable]) extends SimpleBlock with traits.CustomDrops[tileentity.Cable] {
+class Cable(props: Properties) extends SimpleBlock(props) with IForgeBlock {
// For Immibis Microblock support.
val ImmibisMicroblocks_TransformableBlockMarker = null
@@ -31,88 +39,71 @@ class Cable(protected implicit val tileTag: ClassTag[tileentity.Cable]) extends
// ----------------------------------------------------------------------- //
- override def createBlockState() = new ExtendedBlockState(this, Array.empty, Array(Cable.NeighborsProp,Cable.ColorProp, Cable.IsSideCableProp))
-
- override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos): IBlockState =
- (state, world.getTileEntity(pos)) match {
- case (extendedState: IExtendedBlockState, cable: tileentity.Cable) =>
- var isCableMask = 0
- for (side <- EnumFacing.values) {
- if (world.getTileEntity(pos.offset(side)).isInstanceOf[tileentity.Cable]){
- isCableMask = Cable.mask(side, isCableMask)
- }
- }
- extendedState.withProperty(Cable.NeighborsProp, Int.box(Cable.neighbors(world,pos))).withProperty(Cable.ColorProp, Int.box(cable.getColor)).withProperty(Cable.IsSideCableProp, Int.box(isCableMask))
- case _ => state
- }
-
- // ----------------------------------------------------------------------- //
-
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
+ override protected def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) = {
+ builder.add(PropertyCableConnection.DOWN, PropertyCableConnection.UP,
+ PropertyCableConnection.NORTH, PropertyCableConnection.SOUTH,
+ PropertyCableConnection.WEST, PropertyCableConnection.EAST)
+ }
- // ----------------------------------------------------------------------- //
+ registerDefaultState(defaultBlockState.
+ setValue(PropertyCableConnection.DOWN, PropertyCableConnection.Shape.NONE).
+ setValue(PropertyCableConnection.UP, PropertyCableConnection.Shape.NONE).
+ setValue(PropertyCableConnection.NORTH, PropertyCableConnection.Shape.NONE).
+ setValue(PropertyCableConnection.SOUTH, PropertyCableConnection.Shape.NONE).
+ setValue(PropertyCableConnection.WEST, PropertyCableConnection.Shape.NONE).
+ setValue(PropertyCableConnection.EAST, PropertyCableConnection.Shape.NONE))
+
+ override def getStateForPlacement(ctx: BlockItemUseContext): BlockState = {
+ val color = Cable.getConnectionColor(ctx.getItemInHand)
+ val fromPos = new BlockPos.Mutable()
+ Direction.values.foldLeft(defaultBlockState)((state, fromSide) => {
+ fromPos.setWithOffset(ctx.getClickedPos, fromSide)
+ val fromState = ctx.getLevel.getBlockState(fromPos)
+ Cable.updateState(state, null, color, fromSide, fromState, ctx.getLevel, fromPos)
+ })
+ }
- override def getPickBlock(state: IBlockState, target: RayTraceResult, world: World, pos: BlockPos, player: EntityPlayer) =
- world.getTileEntity(pos) match {
+ override def getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity) =
+ world.getBlockEntity(pos) match {
case t: tileentity.Cable => t.createItemStack()
case _ => createItemStack()
}
- override def getBoundingBox(state: IBlockState, world: IBlockAccess, pos: BlockPos): AxisAlignedBB = Cable.bounds(world, pos)
-
- override def addCollisionBoxToList(state: IBlockState, worldIn: World, pos: BlockPos, entityBox: AxisAlignedBB, collidingBoxes: util.List[AxisAlignedBB], entityIn: Entity, isActualState: Boolean): Unit = {
- Cable.parts(worldIn, pos, entityBox, collidingBoxes)
- }
-
- override def collisionRayTrace(state: IBlockState, world: World, pos: BlockPos, start: Vec3d, end: Vec3d): RayTraceResult = {
- var distance = Double.PositiveInfinity
- var result: RayTraceResult = null
-
- val boxes = new util.ArrayList[AxisAlignedBB]
- Cable.parts(world, pos, Block.FULL_BLOCK_AABB.offset(pos), boxes)
- for (part: AxisAlignedBB <- boxes) {
- val hit = part.calculateIntercept(start, end)
- if (hit != null) {
- val hitDistance = hit.hitVec.squareDistanceTo(start)
- if (hitDistance < distance) {
- distance = hitDistance;
- result = hit;
- }
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = Cable.shape(state)
+
+ override def neighborChanged(state: BlockState, world: World, pos: BlockPos, other: Block, otherPos: BlockPos, moved: Boolean): Unit = {
+ if (world.isClientSide) return
+ val newState = world.getBlockEntity(pos) match {
+ case t: tileentity.Cable => {
+ val fromPos = new BlockPos.Mutable()
+ Direction.values.foldLeft(state)((state, fromSide) => {
+ fromPos.setWithOffset(pos, fromSide)
+ val fromState = world.getBlockState(fromPos)
+ Cable.updateState(state, t, -1, fromSide, fromState, world, fromPos)
+ })
}
+ case _ => state
}
-
- if (result == null) null
- else new RayTraceResult(result.hitVec, result.sideHit, pos)
+ if (newState != state) world.setBlock(pos, newState, 0x13)
}
- // ----------------------------------------------------------------------- //
-
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Cable()
+ override def updateShape(state: BlockState, fromSide: Direction, fromState: BlockState, world: IWorld, pos: BlockPos, fromPos: BlockPos): BlockState =
+ Cable.updateState(state, world.getBlockEntity(pos), -1, fromSide, fromState, world, fromPos)
// ----------------------------------------------------------------------- //
- override def neighborChanged(state: IBlockState, world: World, pos: BlockPos, neighborBlock: Block, sourcePos: BlockPos) {
- world.notifyBlockUpdate(pos, state, state, 3)
- super.neighborChanged(state, world, pos, neighborBlock, sourcePos)
- }
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Cable(tileentity.TileEntityTypes.CABLE)
- override protected def doCustomInit(tileEntity: tileentity.Cable, player: EntityLivingBase, stack: ItemStack): Unit = {
- super.doCustomInit(tileEntity, player, stack)
- if (!tileEntity.world.isRemote) {
- tileEntity.fromItemStack(stack)
- }
- }
+ // ----------------------------------------------------------------------- //
- override protected def doCustomDrops(tileEntity: tileentity.Cable, player: EntityPlayer, willHarvest: Boolean): Unit = {
- super.doCustomDrops(tileEntity, player, willHarvest)
- if (!player.capabilities.isCreativeMode) {
- Block.spawnAsEntity(tileEntity.world, tileEntity.getPos, tileEntity.createItemStack())
+ override def setPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity, stack: ItemStack): Unit = {
+ super.setPlacedBy(world, pos, state, placer, stack)
+ world.getBlockEntity(pos) match {
+ case tileEntity: tileentity.Cable => {
+ tileEntity.fromItemStack(stack)
+ state.updateNeighbourShapes(world, pos, 2)
+ }
+ case _ =>
}
}
}
@@ -121,108 +112,100 @@ object Cable {
final val MIN = 0.375
final val MAX = 1 - MIN
- final val DefaultBounds: AxisAlignedBB = new AxisAlignedBB(MIN, MIN, MIN, MAX, MAX, MAX)
+ final val DefaultShape: VoxelShape = VoxelShapes.box(MIN, MIN, MIN, MAX, MAX, MAX)
- final val CachedParts: Array[AxisAlignedBB] = Array(
- new AxisAlignedBB( MIN, 0, MIN, MAX, MIN, MAX ), // Down
- new AxisAlignedBB( MIN, MAX, MIN, MAX, 1, MAX ), // Up
- new AxisAlignedBB( MIN, MIN, 0, MAX, MAX, MIN ), // North
- new AxisAlignedBB( MIN, MIN, MAX, MAX, MAX, 1 ), // South
- new AxisAlignedBB( 0, MIN, MIN, MIN, MAX, MAX ), // West
- new AxisAlignedBB( MAX, MIN, MIN, 1, MAX, MAX )) // East
+ final val CachedParts: Array[VoxelShape] = Array(
+ VoxelShapes.box( MIN, 0, MIN, MAX, MIN, MAX ), // Down
+ VoxelShapes.box( MIN, MAX, MIN, MAX, 1, MAX ), // Up
+ VoxelShapes.box( MIN, MIN, 0, MAX, MAX, MIN ), // North
+ VoxelShapes.box( MIN, MIN, MAX, MAX, MAX, 1 ), // South
+ VoxelShapes.box( 0, MIN, MIN, MIN, MAX, MAX ), // West
+ VoxelShapes.box( MAX, MIN, MIN, 1, MAX, MAX )) // East
final val CachedBounds = {
// 6 directions = 6 bits = 11111111b >> 2 = 0xFF >> 2
(0 to 0xFF >> 2).map(mask => {
- EnumFacing.VALUES.foldLeft(DefaultBounds)((bound, side) => {
- if (((1 << side.getIndex) & mask) != 0) bound.union(CachedParts(side.ordinal()))
- else bound
+ Direction.values.foldLeft(DefaultShape)((shape, side) => {
+ if (((1 << side.get3DDataValue) & mask) != 0) VoxelShapes.or(shape, CachedParts(side.ordinal()))
+ else shape
})
}).toArray
}
- final val NeighborsProp = new UnlistedInteger("neighbors")
- final val ColorProp = new UnlistedInteger("color")
- final val IsSideCableProp = new UnlistedInteger("is_cable")
+ def mask(side: Direction, value: Int = 0) = value | (1 << side.get3DDataValue)
- def mask(side: EnumFacing, value: Int = 0) = value | (1 << side.getIndex)
-
- def neighbors(world: IBlockAccess, pos: BlockPos) = {
+ def shape(state: BlockState): VoxelShape = {
var result = 0
- val tileEntity = world.getTileEntity(pos)
- for (side <- EnumFacing.values) {
- val tpos = pos.offset(side)
- val hasNode = hasNetworkNode(tileEntity, side)
- if (hasNode && (world match {
- case world: World => world.isBlockLoaded(tpos)
- case _ => !world.isAirBlock(tpos)
- })) {
- val neighborTileEntity = world.getTileEntity(tpos)
- if (neighborTileEntity != null && neighborTileEntity.getWorld != null) {
- val neighborHasNode = hasNetworkNode(neighborTileEntity, side.getOpposite)
- val canConnectColor = canConnectBasedOnColor(tileEntity, neighborTileEntity)
- val canConnectIM = canConnectFromSideIM(tileEntity, side) && canConnectFromSideIM(neighborTileEntity, side.getOpposite)
- if (neighborHasNode && canConnectColor && canConnectIM) {
- result = mask(side, result)
- }
- }
+ for (side <- Direction.values) {
+ val sideShape = state.getValue(PropertyCableConnection.BY_DIRECTION.get(side))
+ if (sideShape != PropertyCableConnection.Shape.NONE) {
+ result = mask(side, result)
}
}
- result
+ Cable.CachedBounds(result)
}
- def bounds(world: IBlockAccess, pos: BlockPos) = Cable.CachedBounds(Cable.neighbors(world, pos))
-
- def parts(world: IBlockAccess, pos: BlockPos, entityBox : AxisAlignedBB, boxes : util.List[AxisAlignedBB]) = {
- val center = Cable.DefaultBounds.offset(pos)
- if (entityBox.intersects(center)) boxes.add(center)
-
- val mask = Cable.neighbors(world, pos)
- for (side <- EnumFacing.VALUES) {
- if(((1 << side.getIndex) & mask) != 0) {
- val part = Cable.CachedParts(side.ordinal()).offset(pos)
- if (entityBox.intersects(part)) boxes.add(part)
+ def updateState(state: BlockState, tileEntity: TileEntity, defaultColor: Int, fromSide: Direction, fromState: BlockState, world: IBlockReader, fromPos: BlockPos): BlockState = {
+ val prop = PropertyCableConnection.BY_DIRECTION.get(fromSide)
+ val neighborTileEntity = world.getBlockEntity(fromPos)
+ if (neighborTileEntity != null && neighborTileEntity.getLevel != null) {
+ val neighborHasNode = hasNetworkNode(neighborTileEntity, fromSide.getOpposite)
+ val canConnectColor = canConnectBasedOnColor(tileEntity, neighborTileEntity, defaultColor)
+ val canConnectIM = canConnectFromSideIM(tileEntity, fromSide) && canConnectFromSideIM(neighborTileEntity, fromSide.getOpposite)
+ if (neighborHasNode && canConnectColor && canConnectIM) {
+ if (fromState.is(state.getBlock)) {
+ return state.setValue(prop, PropertyCableConnection.Shape.CABLE)
+ }
+ else {
+ return state.setValue(prop, PropertyCableConnection.Shape.DEVICE)
+ }
}
}
+ state.setValue(prop, PropertyCableConnection.Shape.NONE)
}
- private def hasNetworkNode(tileEntity: TileEntity, side: EnumFacing): Boolean = {
+ private def hasNetworkNode(tileEntity: TileEntity, side: Direction): Boolean = {
if (tileEntity != null) {
if (tileEntity.isInstanceOf[tileentity.RobotProxy]) return false
- if (tileEntity.hasCapability(Capabilities.SidedEnvironmentCapability, side)) {
- val host = tileEntity.getCapability(Capabilities.SidedEnvironmentCapability, side)
+ if (tileEntity.getCapability(Capabilities.SidedEnvironmentCapability, side).isPresent) {
+ val host = tileEntity.getCapability(Capabilities.SidedEnvironmentCapability, side).orElse(null)
if (host != null) {
- return if (tileEntity.getWorld.isRemote) host.canConnect(side) else host.sidedNode(side) != null
+ return if (tileEntity.getLevel.isClientSide) host.canConnect(side) else host.sidedNode(side) != null
}
}
- if (tileEntity.hasCapability(Capabilities.EnvironmentCapability, side)) {
+ if (tileEntity.getCapability(Capabilities.EnvironmentCapability, side).isPresent) {
val host = tileEntity.getCapability(Capabilities.EnvironmentCapability, side)
- if (host != null) return true
+ if (host.isPresent) return true
}
}
false
}
+ private def getConnectionColor(stack: ItemStack): Int = {
+ val color = ItemColorizer.getColor(stack)
+ if (color == -1) Color.rgbValues(DyeColor.LIGHT_GRAY) else color
+ }
+
private def getConnectionColor(tileEntity: TileEntity): Int = {
if (tileEntity != null) {
- if (tileEntity.hasCapability(Capabilities.ColoredCapability, null)) {
- val colored = tileEntity.getCapability(Capabilities.ColoredCapability, null)
+ if (tileEntity.getCapability(Capabilities.ColoredCapability, null).isPresent) {
+ val colored = tileEntity.getCapability(Capabilities.ColoredCapability, null).orElse(null)
if (colored != null && colored.controlsConnectivity) return colored.getColor
}
}
- Color.rgbValues(EnumDyeColor.SILVER)
+ Color.rgbValues(DyeColor.LIGHT_GRAY)
}
- private def canConnectBasedOnColor(te1: TileEntity, te2: TileEntity) = {
- val (c1, c2) = (getConnectionColor(te1), getConnectionColor(te2))
- c1 == c2 || c1 == Color.rgbValues(EnumDyeColor.SILVER) || c2 == Color.rgbValues(EnumDyeColor.SILVER)
+ private def canConnectBasedOnColor(te1: TileEntity, te2: TileEntity, c1Default: Int = Color.rgbValues(DyeColor.LIGHT_GRAY)) = {
+ val (c1, c2) = (if (te1 == null) c1Default else getConnectionColor(te1), getConnectionColor(te2))
+ c1 == c2 || c1 == Color.rgbValues(DyeColor.LIGHT_GRAY) || c2 == Color.rgbValues(DyeColor.LIGHT_GRAY)
}
- private def canConnectFromSideIM(tileEntity: TileEntity, side: EnumFacing) =
+ private def canConnectFromSideIM(tileEntity: TileEntity, side: Direction) =
tileEntity match {
case im: tileentity.traits.ImmibisMicroblock => im.ImmibisMicroblocks_isSideOpen(side.ordinal)
case _ => true
diff --git a/src/main/scala/li/cil/oc/common/block/Capacitor.scala b/src/main/scala/li/cil/oc/common/block/Capacitor.scala
index 54fb043f3a..1d792ef4a0 100644
--- a/src/main/scala/li/cil/oc/common/block/Capacitor.scala
+++ b/src/main/scala/li/cil/oc/common/block/Capacitor.scala
@@ -3,37 +3,40 @@ package li.cil.oc.common.block
import java.util.Random
import li.cil.oc.common.tileentity
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
+import net.minecraft.world.server.ServerWorld
-class Capacitor extends SimpleBlock {
- setTickRandomly(true)
+class Capacitor(props: Properties) extends SimpleBlock(props) {
+ @Deprecated
+ override def isRandomlyTicking(state: BlockState) = true
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Capacitor()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Capacitor(tileentity.TileEntityTypes.CAPACITOR)
// ----------------------------------------------------------------------- //
- override def hasComparatorInputOverride(state: IBlockState): Boolean = true
+ override def hasAnalogOutputSignal(state: BlockState): Boolean = true
- override def getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int =
- world.getTileEntity(pos) match {
- case capacitor: tileentity.Capacitor if !world.isRemote =>
+ override def getAnalogOutputSignal(state: BlockState, world: World, pos: BlockPos): Int =
+ world.getBlockEntity(pos) match {
+ case capacitor: tileentity.Capacitor if !world.isClientSide =>
math.round(15 * capacitor.node.localBuffer / capacitor.node.localBufferSize).toInt
case _ => 0
}
- override def updateTick(world: World, pos: BlockPos, state: IBlockState, rand: Random): Unit = {
- world.notifyNeighborsOfStateChange(pos, this, false)
+ override def tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random): Unit = {
+ world.updateNeighborsAt(pos, this)
}
- override def tickRate(world: World) = 1
-
- override def neighborChanged(state: IBlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos): Unit =
- world.getTileEntity(pos) match {
+ @Deprecated
+ override def neighborChanged(state: BlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos, b: Boolean): Unit =
+ world.getBlockEntity(pos) match {
case capacitor: tileentity.Capacitor => capacitor.recomputeCapacity()
case _ =>
}
diff --git a/src/main/scala/li/cil/oc/common/block/CarpetedCapacitor.scala b/src/main/scala/li/cil/oc/common/block/CarpetedCapacitor.scala
index 03108dce6d..14606b4034 100644
--- a/src/main/scala/li/cil/oc/common/block/CarpetedCapacitor.scala
+++ b/src/main/scala/li/cil/oc/common/block/CarpetedCapacitor.scala
@@ -1,8 +1,9 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
-import net.minecraft.world.World
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.world.IBlockReader
-class CarpetedCapacitor extends Capacitor {
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.CarpetedCapacitor()
+class CarpetedCapacitor(props: Properties) extends Capacitor(props) {
+ override def newBlockEntity(world: IBlockReader) = new tileentity.CarpetedCapacitor(tileentity.TileEntityTypes.CARPETED_CAPACITOR)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Case.scala b/src/main/scala/li/cil/oc/common/block/Case.scala
index 08cf662b55..58ab6f67db 100644
--- a/src/main/scala/li/cil/oc/common/block/Case.scala
+++ b/src/main/scala/li/cil/oc/common/block/Case.scala
@@ -3,34 +3,39 @@ package li.cil.oc.common.block
import java.util
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.tileentity
-import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.fluid.FluidState
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.state.StateContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with traits.StateAware with traits.GUI {
- override def createBlockState() = new BlockStateContainer(this, PropertyRotatable.Facing, property.PropertyRunning.Running)
+import scala.collection.convert.ImplicitConversionsToScala._
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Facing, EnumFacing.getHorizontal(meta >> 1))
-
- override def getMetaFromState(state: IBlockState): Int = state.getValue(PropertyRotatable.Facing).getHorizontalIndex << 1 | (if (state.getValue(property.PropertyRunning.Running)) 1 else 0)
+class Case(props: Properties, val tier: Int) extends RedstoneAware(props) with traits.PowerAcceptor with traits.StateAware with traits.GUI {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Facing, property.PropertyRunning.Running)
// ----------------------------------------------------------------------- //
- override def rarity(stack: ItemStack) = Rarity.byTier(tier)
-
- override protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase, slots))
+ override protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ for (curr <- Tooltip.get(getClass.getSimpleName.toLowerCase, slots)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
private def slots = tier match {
@@ -44,16 +49,19 @@ class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with t
override def energyThroughput = Settings.get.caseRate(tier)
- override def guiType = GuiType.Case
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Case if te.stillValid(player) => ContainerTypes.openCaseGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Case(tier)
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Case(tileentity.TileEntityTypes.CASE, tier)
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- if (player.isSneaking) {
- if (!world.isRemote) world.getTileEntity(pos) match {
- case computer: tileentity.Case if !computer.machine.isRunning && computer.isUsableByPlayer(player) => computer.machine.start()
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = {
+ if (player.isCrouching) {
+ if (!world.isClientSide) world.getBlockEntity(pos) match {
+ case computer: tileentity.Case if !computer.machine.isRunning && computer.stillValid(player) => computer.machine.start()
case _ =>
}
true
@@ -61,11 +69,11 @@ class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with t
else super.localOnBlockActivated(world, pos, player, hand, heldItem, side, hitX, hitY, hitZ)
}
- override def removedByPlayer(state: IBlockState, world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean): Boolean =
- world.getTileEntity(pos) match {
+ override def removedByPlayer(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, willHarvest: Boolean, fluid: FluidState): Boolean =
+ world.getBlockEntity(pos) match {
case c: tileentity.Case =>
- if (c.isCreative && (!player.capabilities.isCreativeMode || !c.canInteract(player.getName))) false
- else c.canInteract(player.getName) && super.removedByPlayer(state, world, pos, player, willHarvest)
- case _ => super.removedByPlayer(state, world, pos, player, willHarvest)
+ if (c.isCreative && (!player.isCreative || !c.canInteract(player.getName.getString))) false
+ else c.canInteract(player.getName.getString) && super.removedByPlayer(state, world, pos, player, willHarvest, fluid)
+ case _ => super.removedByPlayer(state, world, pos, player, willHarvest, fluid)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/ChameliumBlock.scala b/src/main/scala/li/cil/oc/common/block/ChameliumBlock.scala
index dbbe315f88..4dc38c6d90 100644
--- a/src/main/scala/li/cil/oc/common/block/ChameliumBlock.scala
+++ b/src/main/scala/li/cil/oc/common/block/ChameliumBlock.scala
@@ -1,27 +1,42 @@
package li.cil.oc.common.block
-import net.minecraft.block.material.Material
-import net.minecraft.block.properties.PropertyEnum
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
-import net.minecraft.item.EnumDyeColor
+import java.util.List
+
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.item.BlockItemUseContext
+import net.minecraft.item.DyeColor
+import net.minecraft.item.ItemGroup
+import net.minecraft.item.ItemStack
+import net.minecraft.state.EnumProperty
+import net.minecraft.state.StateContainer
+import net.minecraft.util.NonNullList
+import net.minecraft.util.math.BlockPos
+import net.minecraft.world.IBlockReader
object ChameliumBlock {
- final val Color = PropertyEnum.create("color", classOf[EnumDyeColor])
+ final val Color = EnumProperty.create("color", classOf[DyeColor])
}
-class ChameliumBlock extends SimpleBlock(Material.ROCK) {
- setDefaultState(blockState.getBaseState.withProperty(ChameliumBlock.Color, EnumDyeColor.BLACK))
-
- override def damageDropped(state: IBlockState): Int = getMetaFromState(state)
-
- override def getStateFromMeta(meta: Int): IBlockState =
- getDefaultState.withProperty(ChameliumBlock.Color, EnumDyeColor.byDyeDamage(meta))
-
- override def getMetaFromState(state: IBlockState): Int =
- state.getValue(ChameliumBlock.Color).getDyeDamage
-
- override def createBlockState() = new BlockStateContainer(this, ChameliumBlock.Color)
-
- override def hasTileEntity(state: IBlockState): Boolean = false
+class ChameliumBlock(props: Properties) extends SimpleBlock(props) {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]): Unit = {
+ builder.add(ChameliumBlock.Color)
+ }
+ registerDefaultState(stateDefinition.any.setValue(ChameliumBlock.Color, DyeColor.BLACK))
+
+ override def getCloneItemStack(world: IBlockReader, pos: BlockPos, state: BlockState): ItemStack = {
+ val stack = new ItemStack(this)
+ stack.setDamageValue(state.getValue(ChameliumBlock.Color).getId)
+ stack
+ }
+
+ override def getStateForPlacement(ctx: BlockItemUseContext): BlockState =
+ defaultBlockState.setValue(ChameliumBlock.Color, DyeColor.byId(ctx.getItemInHand.getDamageValue))
+
+ override def fillItemCategory(tab: ItemGroup, list: NonNullList[ItemStack]) {
+ val stack = new ItemStack(this, 1)
+ stack.setDamageValue(defaultBlockState.getValue(ChameliumBlock.Color).getId)
+ list.add(stack)
+ }
}
diff --git a/src/main/scala/li/cil/oc/common/block/Charger.scala b/src/main/scala/li/cil/oc/common/block/Charger.scala
index 70e953d019..985a6000ba 100644
--- a/src/main/scala/li/cil/oc/common/block/Charger.scala
+++ b/src/main/scala/li/cil/oc/common/block/Charger.scala
@@ -1,47 +1,49 @@
package li.cil.oc.common.block
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.Wrench
import li.cil.oc.server.PacketSender
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.state.StateContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Charger extends RedstoneAware with traits.PowerAcceptor with traits.StateAware with traits.GUI {
- override def createBlockState() = new BlockStateContainer(this, PropertyRotatable.Facing)
-
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Facing, EnumFacing.getHorizontal(meta))
-
- override def getMetaFromState(state: IBlockState): Int = state.getValue(PropertyRotatable.Facing).getHorizontalIndex
+class Charger(props: Properties) extends RedstoneAware(props) with traits.PowerAcceptor with traits.StateAware with traits.GUI {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Facing)
// ----------------------------------------------------------------------- //
override def energyThroughput = Settings.get.chargerRate
- override def guiType = GuiType.Charger
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Charger => ContainerTypes.openChargerGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Charger()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Charger(tileentity.TileEntityTypes.CHARGER)
// ----------------------------------------------------------------------- //
- override def canConnectRedstone(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = true
+ override def canConnectRedstone(state: BlockState, world: IBlockReader, pos: BlockPos, side: Direction): Boolean = true
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) =
- if (Wrench.holdsApplicableWrench(player, pos)) world.getTileEntity(pos) match {
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float) =
+ if (Wrench.holdsApplicableWrench(player, pos)) world.getBlockEntity(pos) match {
case charger: tileentity.Charger =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
charger.invertSignal = !charger.invertSignal
charger.chargeSpeed = 1.0 - charger.chargeSpeed
PacketSender.sendChargerState(charger)
@@ -52,11 +54,12 @@ class Charger extends RedstoneAware with traits.PowerAcceptor with traits.StateA
}
else super.localOnBlockActivated(world, pos, player, hand, heldItem, side, hitX, hitY, hitZ)
- override def neighborChanged(state: IBlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos): Unit = {
- world.getTileEntity(pos) match {
+ @Deprecated
+ override def neighborChanged(state: BlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos, b: Boolean): Unit = {
+ world.getBlockEntity(pos) match {
case charger: tileentity.Charger => charger.onNeighborChanged()
case _ =>
}
- super.neighborChanged(state, world, pos, block, fromPos)
+ super.neighborChanged(state, world, pos, block, fromPos, b)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/Disassembler.scala b/src/main/scala/li/cil/oc/common/block/Disassembler.scala
index d938805201..058cc5bbea 100644
--- a/src/main/scala/li/cil/oc/common/block/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/common/block/Disassembler.scala
@@ -3,25 +3,38 @@ package li.cil.oc.common.block
import java.util
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.tileentity
import li.cil.oc.util.Tooltip
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
+import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Disassembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI {
- override protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase, (Settings.get.disassemblerBreakChance * 100).toInt.toString))
+import scala.collection.convert.ImplicitConversionsToScala._
+
+class Disassembler(props: Properties) extends SimpleBlock(props) with traits.PowerAcceptor with traits.StateAware with traits.GUI {
+ override protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ for (curr <- Tooltip.get(getClass.getSimpleName.toLowerCase, (Settings.get.disassemblerBreakChance * 100).toInt.toString)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
// ----------------------------------------------------------------------- //
override def energyThroughput = Settings.get.disassemblerRate
- override def guiType = GuiType.Disassembler
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Disassembler => ContainerTypes.openDisassemblerGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Disassembler()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Disassembler(tileentity.TileEntityTypes.DISASSEMBLER)
}
diff --git a/src/main/scala/li/cil/oc/common/block/DiskDrive.scala b/src/main/scala/li/cil/oc/common/block/DiskDrive.scala
index 3c4e1ef5b4..e42d5fb0e2 100644
--- a/src/main/scala/li/cil/oc/common/block/DiskDrive.scala
+++ b/src/main/scala/li/cil/oc/common/block/DiskDrive.scala
@@ -2,73 +2,77 @@ package li.cil.oc.common.block
import java.util
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
import li.cil.oc.util.Tooltip
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.state.StateContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class DiskDrive extends SimpleBlock with traits.GUI {
- override def createBlockState() = new BlockStateContainer(this, PropertyRotatable.Facing)
+import scala.collection.convert.ImplicitConversionsToScala._
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Facing, EnumFacing.getHorizontal(meta))
-
- override def getMetaFromState(state: IBlockState): Int = state.getValue(PropertyRotatable.Facing).getHorizontalIndex
+class DiskDrive(props: Properties) extends SimpleBlock(props) with traits.GUI {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Facing)
// ----------------------------------------------------------------------- //
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, flag)
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.tooltipTail(stack, world, tooltip, flag)
if (Mods.ComputerCraft.isModAvailable) {
- tooltip.addAll(Tooltip.get(getClass.getSimpleName + ".CC"))
+ for (curr <- Tooltip.get(getClass.getSimpleName + ".CC")) tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
}
}
// ----------------------------------------------------------------------- //
- override def guiType = GuiType.DiskDrive
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.DiskDrive => ContainerTypes.openDiskDriveGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.DiskDrive()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.DiskDrive(tileentity.TileEntityTypes.DISK_DRIVE)
// ----------------------------------------------------------------------- //
- override def hasComparatorInputOverride(state: IBlockState): Boolean = true
+ override def hasAnalogOutputSignal(state: BlockState): Boolean = true
- override def getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int =
- world.getTileEntity(pos) match {
- case drive: tileentity.DiskDrive if !drive.getStackInSlot(0).isEmpty => 15
+ override def getAnalogOutputSignal(state: BlockState, world: World, pos: BlockPos): Int =
+ world.getBlockEntity(pos) match {
+ case drive: tileentity.DiskDrive if !drive.getItem(0).isEmpty => 15
case _ => 0
}
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
// Behavior: sneaking -> Insert[+Eject], not sneaking -> GUI.
- if (player.isSneaking) world.getTileEntity(pos) match {
+ if (player.isCrouching) world.getBlockEntity(pos) match {
case drive: tileentity.DiskDrive =>
- val isDiskInDrive = drive.getStackInSlot(0) != null
- val isHoldingDisk = drive.isItemValidForSlot(0, heldItem)
+ val isDiskInDrive = drive.getItem(0) != null
+ val isHoldingDisk = drive.canPlaceItem(0, heldItem)
if (isDiskInDrive) {
- if (!world.isRemote) {
+ if (!world.isClientSide) {
drive.dropSlot(0, 1, Option(drive.facing))
}
}
if (isHoldingDisk) {
// Insert the disk.
- drive.setInventorySlotContents(0, heldItem.copy().splitStack(1))
- if (hand == EnumHand.MAIN_HAND)
- player.inventory.decrStackSize(player.inventory.currentItem, 1)
- else
- player.inventory.offHandInventory.get(0).shrink(1)
+ drive.setItem(0, heldItem.split(1))
}
isDiskInDrive || isHoldingDisk
case _ => false
diff --git a/src/main/scala/li/cil/oc/common/block/FakeEndstone.scala b/src/main/scala/li/cil/oc/common/block/FakeEndstone.scala
index 97297061f8..e6f17bc1ae 100644
--- a/src/main/scala/li/cil/oc/common/block/FakeEndstone.scala
+++ b/src/main/scala/li/cil/oc/common/block/FakeEndstone.scala
@@ -1,11 +1,8 @@
package li.cil.oc.common.block
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
import net.minecraft.block.material.Material
-import net.minecraft.block.state.IBlockState
-class FakeEndstone extends SimpleBlock(Material.ROCK) {
- setHardness(3)
- setResistance(15)
-
- override def hasTileEntity(state: IBlockState): Boolean = false
+class FakeEndstone(props: Properties) extends SimpleBlock(props) {
}
diff --git a/src/main/scala/li/cil/oc/common/block/Geolyzer.scala b/src/main/scala/li/cil/oc/common/block/Geolyzer.scala
index 0f87c555d7..7a3d059b35 100644
--- a/src/main/scala/li/cil/oc/common/block/Geolyzer.scala
+++ b/src/main/scala/li/cil/oc/common/block/Geolyzer.scala
@@ -1,8 +1,10 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Geolyzer extends SimpleBlock {
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Geolyzer()
+class Geolyzer(props: Properties) extends SimpleBlock(props) {
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Geolyzer(tileentity.TileEntityTypes.GEOLYZER)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Hologram.scala b/src/main/scala/li/cil/oc/common/block/Hologram.scala
index 05ad5ad18a..1dae9a89ec 100644
--- a/src/main/scala/li/cil/oc/common/block/Hologram.scala
+++ b/src/main/scala/li/cil/oc/common/block/Hologram.scala
@@ -5,47 +5,39 @@ import java.util
import li.cil.oc.common.tileentity
import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
-import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-class Hologram(val tier: Int) extends SimpleBlock {
- val bounds = new AxisAlignedBB(0, 0, 0, 1, 0.5f, 1)
+import scala.collection.convert.ImplicitConversionsToScala._
- // ----------------------------------------------------------------------- //
-
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN
+class Hologram(props: Properties, val tier: Int) extends SimpleBlock(props) {
+ val shape = VoxelShapes.box(0, 0, 0, 1, 0.5, 1)
- @SideOnly(Side.CLIENT)
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = {
- super.shouldSideBeRendered(state, world, pos, side) || side == EnumFacing.UP
- }
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN
+ // ----------------------------------------------------------------------- //
- override def getBoundingBox(state: IBlockState, world: IBlockAccess, pos: BlockPos): AxisAlignedBB = bounds
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = shape
// ----------------------------------------------------------------------- //
- override def rarity(stack: ItemStack) = Rarity.byTier(tier)
-
- override protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase() + tier))
+ override protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ for (curr <- Tooltip.get(getClass.getSimpleName.toLowerCase() + tier)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Hologram(tier)
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Hologram(tileentity.TileEntityTypes.HOLOGRAM, tier)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Item.scala b/src/main/scala/li/cil/oc/common/block/Item.scala
index 929196193d..6f11d82e38 100644
--- a/src/main/scala/li/cil/oc/common/block/Item.scala
+++ b/src/main/scala/li/cil/oc/common/block/Item.scala
@@ -5,52 +5,51 @@ import java.util
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
+import li.cil.oc.common.block
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
import li.cil.oc.util.ItemColorizer
+import li.cil.oc.util.Rarity
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumDyeColor
-import net.minecraft.item.EnumRarity
-import net.minecraft.item.ItemBlock
+import net.minecraft.block.BlockState
+import net.minecraft.item // Rarity
+import net.minecraft.item.BlockItem
+import net.minecraft.item.BlockItemUseContext
+import net.minecraft.item.DyeColor
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.BlockPos
-import net.minecraft.world.World
+import net.minecraft.util.Direction
+import net.minecraft.util.math.BlockRayTraceResult
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
-class Item(value: Block) extends ItemBlock(value) {
- setHasSubtypes(true)
-
- override def addInformation(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- super.addInformation(stack, world, tooltip, flag)
- block match {
- case (simple: SimpleBlock) =>
- simple.addInformation(getMetadata(stack.getItemDamage), stack, world, tooltip, flag)
- case _ =>
+class Item(value: Block, props: Properties) extends BlockItem(value, props) {
+ override def getRarity(stack: ItemStack): item.Rarity = getBlock match {
+ case _: block.Microcontroller => {
+ val data = new MicrocontrollerData(stack)
+ Rarity.byTier(data.tier)
}
+ case _: block.RobotProxy => {
+ val data = new RobotData(stack)
+ Rarity.byTier(data.tier)
+ }
+ case _ => super.getRarity(stack)
}
- override def getRarity(stack: ItemStack): EnumRarity = block match {
- case simple: SimpleBlock => simple.rarity(stack)
- case _ => EnumRarity.COMMON
- }
-
- override def getMetadata(itemDamage: Int): Int = itemDamage
-
- override def getItemStackDisplayName(stack: ItemStack): String = {
+ override def getName(stack: ItemStack): ITextComponent = {
if (api.Items.get(stack) == api.Items.get(Constants.BlockName.Print)) {
val data = new PrintData(stack)
- data.label.getOrElse(super.getItemStackDisplayName(stack))
+ data.label.map(new StringTextComponent(_)).getOrElse(super.getName(stack))
}
- else super.getItemStackDisplayName(stack)
+ else super.getName(stack)
}
- override def getUnlocalizedName: String = block match {
- case simple: SimpleBlock => simple.getUnlocalizedName
+ @Deprecated
+ override def getDescriptionId: String = getBlock match {
+ case simple: SimpleBlock => simple.getDescriptionId
case _ => Settings.namespace + "tile"
}
@@ -59,14 +58,14 @@ class Item(value: Block) extends ItemBlock(value) {
if (ItemColorizer.hasColor(stack)) {
ItemColorizer.getColor(stack)
}
- else Color.rgbValues(EnumDyeColor.SILVER)
+ else Color.rgbValues(DyeColor.LIGHT_GRAY)
}
else super.getDamage(stack)
}
override def setDamage(stack: ItemStack, damage: Int): Unit = {
if (api.Items.get(stack) == api.Items.get(Constants.BlockName.Cable)) {
- if(damage != Color.rgbValues(EnumDyeColor.SILVER)) {
+ if(damage != Color.rgbValues(DyeColor.LIGHT_GRAY)) {
ItemColorizer.setColor(stack, damage)
} else {
ItemColorizer.removeColor(stack)
@@ -75,24 +74,25 @@ class Item(value: Block) extends ItemBlock(value) {
else super.setDamage(stack, damage)
}
- override def isBookEnchantable(a: ItemStack, b: ItemStack) = false
-
- override def placeBlockAt(stack: ItemStack, player: EntityPlayer, world: World, pos: BlockPos, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, newState: IBlockState): Boolean = {
+ override def placeBlock(ctx: BlockItemUseContext, newState: BlockState): Boolean = {
// When placing robots in creative mode, we have to copy the stack
// manually before it's placed to ensure different component addresses
// in the different robots, to avoid interference of screens e.g.
- val needsCopying = player.capabilities.isCreativeMode && api.Items.get(stack) == api.Items.get(Constants.BlockName.Robot)
- val stackToUse = if (needsCopying) new RobotData(stack).copyItemStack() else stack
- if (super.placeBlockAt(stackToUse, player, world, pos, side, hitX, hitY, hitZ, newState)) {
+ val needsCopying = ctx.getPlayer.isCreative && api.Items.get(ctx.getItemInHand) == api.Items.get(Constants.BlockName.Robot)
+ val ctxToUse = if (needsCopying) {
+ val stackToUse = new RobotData(ctx.getItemInHand).copyItemStack()
+ val hitResult = new BlockRayTraceResult(ctx.getClickLocation, ctx.getClickedFace, ctx.getClickedPos, ctx.isInside)
+ new BlockItemUseContext(ctx.getLevel, ctx.getPlayer, ctx.getHand, stackToUse, hitResult)
+ }
+ else ctx
+ if (super.placeBlock(ctxToUse, newState)) {
// If it's a rotatable block try to make it face the player.
- world.getTileEntity(pos) match {
- case keyboard: tileentity.Keyboard =>
- keyboard.setFromEntityPitchAndYaw(player)
- keyboard.setFromFacing(side)
+ ctx.getLevel.getBlockEntity(ctxToUse.getClickedPos) match {
+ case keyboard: tileentity.Keyboard => // Ignore.
case rotatable: tileentity.traits.Rotatable =>
- rotatable.setFromEntityPitchAndYaw(player)
+ rotatable.setFromEntityPitchAndYaw(ctxToUse.getPlayer)
if (!rotatable.validFacings.contains(rotatable.pitch)) {
- rotatable.pitch = rotatable.validFacings.headOption.getOrElse(EnumFacing.NORTH)
+ rotatable.pitch = rotatable.validFacings.headOption.getOrElse(Direction.NORTH)
}
if (!rotatable.isInstanceOf[tileentity.RobotProxy]) {
rotatable.invertRotation()
diff --git a/src/main/scala/li/cil/oc/common/block/Keyboard.scala b/src/main/scala/li/cil/oc/common/block/Keyboard.scala
index 0054c5ba37..bc2a5064b7 100644
--- a/src/main/scala/li/cil/oc/common/block/Keyboard.scala
+++ b/src/main/scala/li/cil/oc/common/block/Keyboard.scala
@@ -2,6 +2,7 @@ package li.cil.oc.common.block
import java.util.Random
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.common.block.property.PropertyRotatable
@@ -9,123 +10,127 @@ import li.cil.oc.common.tileentity
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedEnumFacing._
import li.cil.oc.util.InventoryUtils
+import li.cil.oc.util.RotationHelper
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.material.Material
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.Blocks
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.BlockItemUseContext
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.state.StateContainer
+import net.minecraft.world.IBlockReader
+import net.minecraft.world.IWorldReader
import net.minecraft.world.World
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-class Keyboard extends SimpleBlock(Material.ROCK) {
- setLightOpacity(0)
-
+class Keyboard(props: Properties) extends SimpleBlock(props) {
// For Immibis Microblock support.
val ImmibisMicroblocks_TransformableBlockMarker = null
- override def createBlockState() = new BlockStateContainer(this, PropertyRotatable.Pitch, PropertyRotatable.Yaw)
-
- override def getMetaFromState(state: IBlockState): Int = (state.getValue(PropertyRotatable.Pitch).ordinal() << 2) | state.getValue(PropertyRotatable.Yaw).getHorizontalIndex
-
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Pitch, EnumFacing.getFront(meta >> 2)).withProperty(PropertyRotatable.Yaw, EnumFacing.getHorizontal(meta & 0x3))
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Pitch, PropertyRotatable.Yaw)
// ----------------------------------------------------------------------- //
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def getBoundingBox(state: IBlockState, world: IBlockAccess, pos: BlockPos): AxisAlignedBB =
- world.getTileEntity(pos) match {
- case keyboard: tileentity.Keyboard =>
- val (pitch, yaw) = (keyboard.pitch, keyboard.yaw)
- val (forward, up) = pitch match {
- case side@(EnumFacing.DOWN | EnumFacing.UP) => (side, yaw)
- case _ => (yaw, EnumFacing.UP)
- }
- val side = forward.getRotation(up)
- val sizes = Array(7f / 16f, 4f / 16f, 7f / 16f)
- val x0 = -up.getFrontOffsetX * sizes(1) - side.getFrontOffsetX * sizes(2) - forward.getFrontOffsetX * sizes(0)
- val x1 = up.getFrontOffsetX * sizes(1) + side.getFrontOffsetX * sizes(2) - forward.getFrontOffsetX * 0.5f
- val y0 = -up.getFrontOffsetY * sizes(1) - side.getFrontOffsetY * sizes(2) - forward.getFrontOffsetY * sizes(0)
- val y1 = up.getFrontOffsetY * sizes(1) + side.getFrontOffsetY * sizes(2) - forward.getFrontOffsetY * 0.5f
- val z0 = -up.getFrontOffsetZ * sizes(1) - side.getFrontOffsetZ * sizes(2) - forward.getFrontOffsetZ * sizes(0)
- val z1 = up.getFrontOffsetZ * sizes(1) + side.getFrontOffsetZ * sizes(2) - forward.getFrontOffsetZ * 0.5f
- new AxisAlignedBB(x0, y0, z0, x1, y1, z1).offset(0.5, 0.5, 0.5)
- case _ => super.getBoundingBox(state, world, pos)
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = {
+ val (pitch, yaw) = (state.getValue(PropertyRotatable.Pitch), state.getValue(PropertyRotatable.Yaw))
+ val (forward, up) = pitch match {
+ case side@(Direction.DOWN | Direction.UP) => (side, yaw)
+ case _ => (yaw, Direction.UP)
}
-
- // ----------------------------------------------------------------------- //
-
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true
-
- override def preItemRender(metadata: Int) {
- GlStateManager.translate(-0.75f, 0, 0)
- GlStateManager.scale(1.5f, 1.5f, 1.5f)
+ val side = forward.getRotation(up)
+ val sizes = Array(7f / 16f, 4f / 16f, 7f / 16f)
+ val x0 = -up.getStepX * sizes(1) - side.getStepX * sizes(2) - forward.getStepX * sizes(0)
+ val x1 = up.getStepX * sizes(1) + side.getStepX * sizes(2) - forward.getStepX * 0.5f
+ val y0 = -up.getStepY * sizes(1) - side.getStepY * sizes(2) - forward.getStepY * sizes(0)
+ val y1 = up.getStepY * sizes(1) + side.getStepY * sizes(2) - forward.getStepY * 0.5f
+ val z0 = -up.getStepZ * sizes(1) - side.getStepZ * sizes(2) - forward.getStepZ * sizes(0)
+ val z1 = up.getStepZ * sizes(1) + side.getStepZ * sizes(2) - forward.getStepZ * 0.5f
+ VoxelShapes.box(0.5 + x0, 0.5 + y0, 0.5 + z0, 0.5 + x1, 0.5 + y1, 0.5 + z1)
}
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Keyboard()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Keyboard(tileentity.TileEntityTypes.KEYBOARD)
// ----------------------------------------------------------------------- //
- override def updateTick(world: World, pos: BlockPos, state: IBlockState, rand: Random) =
- world.getTileEntity(pos) match {
+ override def onPlace(state: BlockState, world: World, pos: BlockPos, prevState: BlockState, moved: Boolean): Unit = {
+ if (!world.isClientSide) {
+ world.asInstanceOf[ServerWorld].getBlockTicks.scheduleTick(pos, this, 10)
+ }
+ }
+
+ override def tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) = {
+ world.getBlockEntity(pos) match {
case keyboard: tileentity.Keyboard => api.Network.joinOrCreateNetwork(keyboard)
case _ =>
}
+ world.getBlockTicks.scheduleTick(pos, this, 10)
+ }
- override def canPlaceBlockOnSide(world: World, pos: BlockPos, side: EnumFacing) = {
- world.isSideSolid(pos.offset(side.getOpposite), side) &&
- (world.getTileEntity(pos.offset(side.getOpposite)) match {
+ override def getStateForPlacement(ctx: BlockItemUseContext): BlockState = {
+ val (pitch, yaw) = ctx.getClickedFace match {
+ case side@(Direction.DOWN | Direction.UP) => (side, ctx.getHorizontalDirection)
+ case side => (Direction.NORTH, side)
+ }
+ super.getStateForPlacement(ctx).setValue(PropertyRotatable.Pitch, pitch).setValue(PropertyRotatable.Yaw, yaw)
+ }
+
+ override def canSurvive(state: BlockState, world: IWorldReader, pos: BlockPos) = {
+ // Check without the TE because this is called to check if the block may be placed.
+ val side = state.getValue(PropertyRotatable.Pitch) match {
+ case pitch@(Direction.UP | Direction.DOWN) => pitch
+ case _ => state.getValue(PropertyRotatable.Yaw)
+ }
+ val sidePos = pos.relative(side.getOpposite)
+ world.getBlockState(sidePos).isFaceSturdy(world, sidePos, side) &&
+ (world.getBlockEntity(pos.relative(side.getOpposite)) match {
case screen: tileentity.Screen => screen.facing != side
case _ => true
})
}
- override def neighborChanged(state: IBlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos): Unit =
- world.getTileEntity(pos) match {
- case keyboard: tileentity.Keyboard =>
- if (!canPlaceBlockOnSide(world, pos, keyboard.facing)) {
- world.setBlockToAir(pos)
- InventoryUtils.spawnStackInWorld(BlockPosition(pos, world), api.Items.get(Constants.BlockName.Keyboard).createItemStack(1))
- }
- case _ =>
+ @Deprecated
+ override def neighborChanged(state: BlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos, b: Boolean): Unit =
+ if (!canSurvive(world.getBlockState(pos), world, pos)) {
+ world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState)
+ InventoryUtils.spawnStackInWorld(BlockPosition(pos, world), api.Items.get(Constants.BlockName.Keyboard).createItemStack(1))
}
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) =
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float) =
adjacencyInfo(world, pos) match {
case Some((keyboard, screen, blockPos, facing)) => screen.rightClick(world, blockPos, player, hand, heldItem, facing, 0, 0, 0, force = true)
case _ => false
}
def adjacencyInfo(world: World, pos: BlockPos) =
- world.getTileEntity(pos) match {
+ world.getBlockEntity(pos) match {
case keyboard: tileentity.Keyboard =>
- val blockPos = pos.offset(keyboard.facing.getOpposite)
+ val blockPos = pos.relative(keyboard.facing.getOpposite)
world.getBlockState(blockPos).getBlock match {
case screen: Screen => Some((keyboard, screen, blockPos, keyboard.facing.getOpposite))
case _ =>
// Special case #1: check for screen in front of the keyboard.
val forward = keyboard.facing match {
- case EnumFacing.UP | EnumFacing.DOWN => keyboard.yaw
- case _ => EnumFacing.UP
+ case Direction.UP | Direction.DOWN => keyboard.yaw
+ case _ => Direction.UP
}
- val blockPos = pos.offset(forward)
+ val blockPos = pos.relative(forward)
world.getBlockState(blockPos).getBlock match {
case screen: Screen => Some((keyboard, screen, blockPos, forward))
- case _ if keyboard.facing != EnumFacing.UP && keyboard.facing != EnumFacing.DOWN =>
+ case _ if keyboard.facing != Direction.UP && keyboard.facing != Direction.DOWN =>
// Special case #2: check for screen below keyboards on walls.
- val blockPos = pos.offset(forward.getOpposite)
+ val blockPos = pos.relative(forward.getOpposite)
world.getBlockState(blockPos).getBlock match {
case screen: Screen => Some((keyboard, screen, blockPos, forward.getOpposite))
case _ => None
diff --git a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala
index ab5979b96a..465d947cc0 100644
--- a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala
+++ b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala
@@ -10,75 +10,72 @@ import li.cil.oc.common.Tier
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.util.ItemBlacklist
import li.cil.oc.integration.util.Wrench
+import li.cil.oc.server.loot.LootFunctions
import li.cil.oc.util.InventoryUtils
-import li.cil.oc.util.Rarity
import li.cil.oc.util.StackOption._
+import li.cil.oc.util.Tooltip
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumRarity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.loot.LootContext
+import net.minecraft.loot.LootParameters
+import net.minecraft.state.StateContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.RayTraceResult
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeBlock
import scala.reflect.ClassTag
-class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microcontroller]) extends RedstoneAware with traits.PowerAcceptor with traits.StateAware with traits.CustomDrops[tileentity.Microcontroller] {
- setCreativeTab(null)
- ItemBlacklist.hide(this)
+class Microcontroller(props: Properties)
+ extends RedstoneAware(props) with IForgeBlock with traits.PowerAcceptor with traits.StateAware {
- override def createBlockState() = new BlockStateContainer(this, PropertyRotatable.Facing)
-
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Facing, EnumFacing.getHorizontal(meta))
-
- override def getMetaFromState(state: IBlockState): Int = state.getValue(PropertyRotatable.Facing).getHorizontalIndex
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Facing)
// ----------------------------------------------------------------------- //
- override def getPickBlock(state: IBlockState, target: RayTraceResult, world: World, pos: BlockPos, player: EntityPlayer): ItemStack =
- world.getTileEntity(pos) match {
+ override def getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack =
+ world.getBlockEntity(pos) match {
case mcu: tileentity.Microcontroller => mcu.info.copyItemStack()
case _ => ItemStack.EMPTY
}
// ----------------------------------------------------------------------- //
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, advanced)
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ super.tooltipTail(stack, world, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
val info = new MicrocontrollerData(stack)
for (component <- info.components if !component.isEmpty) {
- tooltip.add("- " + component.getDisplayName)
+ tooltip.add(new StringTextComponent("- " + component.getHoverName.getString).setStyle(Tooltip.DefaultStyle))
}
}
}
- override def rarity(stack: ItemStack): EnumRarity = {
- val data = new MicrocontrollerData(stack)
- Rarity.byTier(data.tier)
- }
-
// ----------------------------------------------------------------------- //
override def energyThroughput: Double = Settings.get.caseRate(Tier.One)
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Microcontroller()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Microcontroller(tileentity.TileEntityTypes.MICROCONTROLLER)
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
if (!Wrench.holdsApplicableWrench(player, pos)) {
- if (!player.isSneaking) {
- if (!world.isRemote) {
- world.getTileEntity(pos) match {
+ if (!player.isCrouching) {
+ if (!world.isClientSide) {
+ world.getBlockEntity(pos) match {
case mcu: tileentity.Microcontroller =>
if (mcu.machine.isRunning) mcu.machine.stop()
else mcu.machine.start()
@@ -88,10 +85,10 @@ class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microc
true
}
else if (api.Items.get(heldItem) == api.Items.get(Constants.ItemName.EEPROM)) {
- if (!world.isRemote) {
- world.getTileEntity(pos) match {
+ if (!world.isClientSide) {
+ world.getBlockEntity(pos) match {
case mcu: tileentity.Microcontroller =>
- val newEeprom = player.inventory.decrStackSize(player.inventory.currentItem, 1)
+ val newEeprom = player.inventory.removeItem(player.inventory.selected, 1)
mcu.changeEEPROM(newEeprom) match {
case SomeStack(oldEeprom) => InventoryUtils.addToPlayerInventory(oldEeprom, player)
case _ =>
@@ -105,18 +102,39 @@ class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microc
else false
}
- override protected def doCustomInit(tileEntity: tileentity.Microcontroller, player: EntityLivingBase, stack: ItemStack): Unit = {
- super.doCustomInit(tileEntity, player, stack)
- if (!tileEntity.world.isRemote) {
- tileEntity.info.load(stack)
- tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer)
+ override def setPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity, stack: ItemStack): Unit = {
+ super.setPlacedBy(world, pos, state, placer, stack)
+ world.getBlockEntity(pos) match {
+ case tileEntity: tileentity.Microcontroller if !world.isClientSide => {
+ tileEntity.info.loadData(stack)
+ tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer)
+ }
+ case _ =>
}
}
- override protected def doCustomDrops(tileEntity: tileentity.Microcontroller, player: EntityPlayer, willHarvest: Boolean): Unit = {
- super.doCustomDrops(tileEntity, player, willHarvest)
- tileEntity.saveComponents()
- tileEntity.info.storedEnergy = tileEntity.snooperNode.localBuffer.toInt
- Block.spawnAsEntity(tileEntity.world, tileEntity.getPos, tileEntity.info.createItemStack())
+ override def getDrops(state: BlockState, ctx: LootContext.Builder): util.List[ItemStack] = {
+ val newCtx = ctx.withDynamicDrop(LootFunctions.DYN_ITEM_DATA, (c, f) => {
+ c.getParamOrNull(LootParameters.BLOCK_ENTITY) match {
+ case tileEntity: tileentity.Microcontroller => {
+ tileEntity.saveComponents()
+ tileEntity.info.storedEnergy = tileEntity.snooperNode.localBuffer.toInt
+ f.accept(tileEntity.info.createItemStack())
+ }
+ case _ =>
+ }
+ })
+ super.getDrops(state, newCtx)
+ }
+
+ override def playerWillDestroy(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
+ if (!world.isClientSide && player.isCreative) {
+ world.getBlockEntity(pos) match {
+ case tileEntity: tileentity.Microcontroller =>
+ Block.dropResources(state, world, pos, tileEntity, player, player.getMainHandItem)
+ case _ =>
+ }
+ }
+ super.playerWillDestroy(world, pos, state, player)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/MotionSensor.scala b/src/main/scala/li/cil/oc/common/block/MotionSensor.scala
index 82cf657bf9..de4731bf63 100644
--- a/src/main/scala/li/cil/oc/common/block/MotionSensor.scala
+++ b/src/main/scala/li/cil/oc/common/block/MotionSensor.scala
@@ -1,8 +1,10 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class MotionSensor extends SimpleBlock {
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.MotionSensor()
+class MotionSensor(props: Properties) extends SimpleBlock(props) {
+ override def newBlockEntity(world: IBlockReader) = new tileentity.MotionSensor(tileentity.TileEntityTypes.MOTION_SENSOR)
}
diff --git a/src/main/scala/li/cil/oc/common/block/NetSplitter.scala b/src/main/scala/li/cil/oc/common/block/NetSplitter.scala
index 76ca51eb69..90f2e57ce9 100644
--- a/src/main/scala/li/cil/oc/common/block/NetSplitter.scala
+++ b/src/main/scala/li/cil/oc/common/block/NetSplitter.scala
@@ -1,53 +1,39 @@
package li.cil.oc.common.block
-import li.cil.oc.common.block.property.PropertyTile
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.Wrench
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.BlockRayTraceResult
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-import net.minecraftforge.common.property.ExtendedBlockState
-import net.minecraftforge.common.property.IExtendedBlockState
-class NetSplitter extends RedstoneAware {
- override def createBlockState() = new ExtendedBlockState(this, Array.empty, Array(PropertyTile.Tile))
-
- override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos): IBlockState =
- (state, world.getTileEntity(pos)) match {
- case (extendedState: IExtendedBlockState, t: tileentity.NetSplitter) =>
- extendedState.withProperty(property.PropertyTile.Tile, t)
- case _ => state
- }
-
- // ----------------------------------------------------------------------- //
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = false
-
- // ----------------------------------------------------------------------- //
-
- override def createNewTileEntity(world: World, meta: Int) = new tileentity.NetSplitter()
+class NetSplitter(props: Properties) extends RedstoneAware(props) {
+ override def newBlockEntity(world: IBlockReader) = new tileentity.NetSplitter(tileentity.TileEntityTypes.NET_SPLITTER)
// ----------------------------------------------------------------------- //
// NOTE: must not be final for immibis microblocks to work.
- override def onBlockActivated(world: World, pos: BlockPos, state: IBlockState, player: EntityPlayer, hand: EnumHand, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ override def use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, trace: BlockRayTraceResult): ActionResultType = {
if (Wrench.holdsApplicableWrench(player, pos)) {
- val sideToToggle = if (player.isSneaking) side.getOpposite else side
- world.getTileEntity(pos) match {
+ val side = trace.getDirection
+ val sideToToggle = if (player.isCrouching) side.getOpposite else side
+ world.getBlockEntity(pos) match {
case splitter: tileentity.NetSplitter =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
val oldValue = splitter.openSides(sideToToggle.ordinal())
splitter.setSideOpen(sideToToggle, !oldValue)
}
- true
- case _ => false
+ ActionResultType.sidedSuccess(world.isClientSide)
+ case _ => ActionResultType.PASS
}
}
- else super.onBlockActivated(world, pos, state, player, hand, side, hitX, hitY, hitZ)
+ else super.use(state, world, pos, player, hand, trace)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/PowerConverter.scala b/src/main/scala/li/cil/oc/common/block/PowerConverter.scala
index 75eee1da08..8ff3f4e6cd 100644
--- a/src/main/scala/li/cil/oc/common/block/PowerConverter.scala
+++ b/src/main/scala/li/cil/oc/common/block/PowerConverter.scala
@@ -1,54 +1,12 @@
package li.cil.oc.common.block
-import java.text.DecimalFormat
-import java.util
-
import li.cil.oc.Settings
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.ItemBlacklist
-import li.cil.oc.util.Tooltip
-import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.item.ItemStack
-import net.minecraft.world.World
-
-class PowerConverter extends SimpleBlock with traits.PowerAcceptor {
- if (Settings.get.ignorePower) {
- setCreativeTab(null)
- ItemBlacklist.hide(this)
- }
-
- private val formatter = new DecimalFormat("#.#")
-
- // ----------------------------------------------------------------------- //
-
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, advanced)
-// TODO more generic way of integration modules of power providing mods to provide tooltip lines
-// if (Mods.Factorization.isAvailable) {
-// addRatio(tooltip, "Factorization", Settings.get.ratioFactorization)
-// }
- if (Mods.IndustrialCraft2.isModAvailable) {
- addRatio(tooltip, "IndustrialCraft2", Settings.get.ratioIndustrialCraft2)
- }
- }
-
- private def addExtension(x: Double) =
- if (x >= 1e9) formatter.format(x / 1e9) + "G"
- else if (x >= 1e6) formatter.format(x / 1e6) + "M"
- else if (x >= 1e3) formatter.format(x / 1e3) + "K"
- else formatter.format(x)
-
- private def addRatio(tooltip: util.List[String], name: String, ratio: Double) {
- val (a, b) =
- if (ratio > 1) (1.0, ratio)
- else (1.0 / ratio, 1.0)
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase + "." + name, addExtension(a), addExtension(b)))
- }
-
- // ----------------------------------------------------------------------- //
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.world.IBlockReader
+class PowerConverter(props: Properties) extends SimpleBlock(props) with traits.PowerAcceptor {
override def energyThroughput: Double = Settings.get.powerConverterRate
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.PowerConverter()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.PowerConverter(tileentity.TileEntityTypes.POWER_CONVERTER)
}
diff --git a/src/main/scala/li/cil/oc/common/block/PowerDistributor.scala b/src/main/scala/li/cil/oc/common/block/PowerDistributor.scala
index ab71ceb3a5..d12d940ae5 100644
--- a/src/main/scala/li/cil/oc/common/block/PowerDistributor.scala
+++ b/src/main/scala/li/cil/oc/common/block/PowerDistributor.scala
@@ -1,9 +1,11 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class PowerDistributor extends SimpleBlock {
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.PowerDistributor()
+class PowerDistributor(props: Properties) extends SimpleBlock(props) {
+ override def newBlockEntity(world: IBlockReader) = new tileentity.PowerDistributor(tileentity.TileEntityTypes.POWER_DISTRIBUTOR)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala
index e385129aa7..95152f23a1 100644
--- a/src/main/scala/li/cil/oc/common/block/Print.scala
+++ b/src/main/scala/li/cil/oc/common/block/Print.scala
@@ -5,148 +5,108 @@ import java.util.Random
import li.cil.oc.Localization
import li.cil.oc.Settings
-import li.cil.oc.common.block.property.PropertyTile
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.util.ItemBlacklist
-import li.cil.oc.util.InventoryUtils
-import net.minecraft.block.state.IBlockState
+import li.cil.oc.server.loot.LootFunctions
+import li.cil.oc.util.Tooltip
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLiving.SpawnPlacementType
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util._
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.loot.LootContext
+import net.minecraft.loot.LootParameters
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
+import net.minecraft.util.math.BlockRayTraceResult
import net.minecraft.util.math.RayTraceResult
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-import net.minecraftforge.common.property.ExtendedBlockState
-import net.minecraftforge.common.property.IExtendedBlockState
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.common.extensions.IForgeBlock
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.reflect.ClassTag
-class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends RedstoneAware with traits.CustomDrops[tileentity.Print] {
- setLightOpacity(1)
- setHardness(1)
- setCreativeTab(null)
- ItemBlacklist.hide(this)
+class Print(props: Properties) extends RedstoneAware(props) with IForgeBlock {
+ @Deprecated
+ override def propagatesSkylightDown(state: BlockState, world: IBlockReader, pos: BlockPos) = false
// ----------------------------------------------------------------------- //
- override def createBlockState() = new ExtendedBlockState(this, Array.empty, Array(PropertyTile.Tile))
-
- override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos): IBlockState =
- (state, world.getTileEntity(pos)) match {
- case (extendedState: IExtendedBlockState, t: tileentity.Print) =>
- extendedState.withProperty(property.PropertyTile.Tile, t)
- case _ => state
- }
-
- // ----------------------------------------------------------------------- //
-
- override def canRenderInLayer(state: IBlockState, layer: BlockRenderLayer): Boolean = layer == BlockRenderLayer.CUTOUT_MIPPED
-
- override protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) = {
- super.tooltipBody(metadata, stack, world, tooltip, advanced)
+ override protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) = {
+ super.tooltipBody(stack, world, tooltip, advanced)
val data = new PrintData(stack)
- data.tooltip.foreach(s => tooltip.addAll(s.lines.toIterable))
+ data.tooltip.foreach(s => tooltip.addAll(s.lines.map(new StringTextComponent(_).setStyle(Tooltip.DefaultStyle)).toIterable))
}
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) = {
- super.tooltipTail(metadata, stack, world, tooltip, advanced)
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) = {
+ super.tooltipTail(stack, world, tooltip, advanced)
val data = new PrintData(stack)
if (data.isBeaconBase) {
- tooltip.add(Localization.Tooltip.PrintBeaconBase)
+ tooltip.add(new StringTextComponent(Localization.Tooltip.PrintBeaconBase).setStyle(Tooltip.DefaultStyle))
}
if (data.emitRedstone) {
- tooltip.add(Localization.Tooltip.PrintRedstoneLevel(data.redstoneLevel))
+ tooltip.add(new StringTextComponent(Localization.Tooltip.PrintRedstoneLevel(data.redstoneLevel)).setStyle(Tooltip.DefaultStyle))
}
if (data.emitLight) {
- tooltip.add(Localization.Tooltip.PrintLightValue(data.lightLevel))
+ tooltip.add(new StringTextComponent(Localization.Tooltip.PrintLightValue(data.lightLevel)).setStyle(Tooltip.DefaultStyle))
}
}
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def getLightValue(state: IBlockState, world: IBlockAccess, pos: BlockPos): Int =
+ override def getLightValue(state: BlockState, world: IBlockReader, pos: BlockPos): Int =
world match {
- case world: World if world.isBlockLoaded(pos) => world.getTileEntity(pos) match {
+ case world: World if world.isLoaded(pos) => world.getBlockEntity(pos) match {
case print: tileentity.Print => print.data.lightLevel
case _ => super.getLightValue(state, world, pos)
}
case _ => super.getLightValue(state, world, pos)
}
- override def getLightOpacity(state: IBlockState, world: IBlockAccess, pos: BlockPos): Int =
+ @Deprecated
+ override def getLightBlock(state: BlockState, world: IBlockReader, pos: BlockPos): Int =
world match {
- case world: World if world.isBlockLoaded(pos) => world.getTileEntity(pos) match {
+ case world: World if world.isLoaded(pos) => world.getBlockEntity(pos) match {
case print: tileentity.Print if Settings.get.printsHaveOpacity => (print.data.opacity * 4).toInt
- case _ => super.getLightOpacity(state, world, pos)
+ case _ => super.getLightBlock(state, world, pos)
}
- case _ => super.getLightOpacity(state, world, pos)
- }
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true
-
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean =
- world.getTileEntity(pos) match {
- case print: tileentity.Print => print.isSideSolid(side)
- case _ => false
+ case _ => super.getLightBlock(state, world, pos)
}
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean =
- isBlockSolid(world, pos, side)
-
- override def getPickBlock(state: IBlockState, target: RayTraceResult, world: World, pos: BlockPos, player: EntityPlayer): ItemStack = {
- world.getTileEntity(pos) match {
+ override def getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack = {
+ world.getBlockEntity(pos) match {
case print: tileentity.Print => print.data.createItemStack()
case _ => ItemStack.EMPTY
}
}
- override def getBoundingBox(state: IBlockState, world: IBlockAccess, pos: BlockPos): AxisAlignedBB = {
- world.getTileEntity(pos) match {
- case print: tileentity.Print => print.bounds
- case _ => super.getBoundingBox(state, world, pos)
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = {
+ world.getBlockEntity(pos) match {
+ case print: tileentity.Print => print.shape
+ case _ => super.getShape(state, world, pos, ctx)
}
}
- override def addCollisionBoxToList(state: IBlockState, world: World, pos: BlockPos, mask: AxisAlignedBB, list: util.List[AxisAlignedBB], entity: Entity, par7: Boolean): Unit = {
- world.getTileEntity(pos) match {
- case print: tileentity.Print => print.addCollisionBoxesToList(mask, list, pos)
- case _ => super.addCollisionBoxToList(state, world, pos, mask, list, entity, par7)
- }
- }
+ def tickRate(world: World) = 20
- override def collisionRayTrace(state: IBlockState, world: World, pos: BlockPos, start: Vec3d, end: Vec3d): RayTraceResult = {
- world.getTileEntity(pos) match {
- case print: tileentity.Print => print.rayTrace(start, end, pos)
- case _ => super.collisionRayTrace(state, world, pos, start, end)
- }
- }
-
- override def canCreatureSpawn(state: IBlockState, world: IBlockAccess, pos: BlockPos, `type`: SpawnPlacementType): Boolean = true
-
- override def tickRate(world: World) = 20
-
- override def updateTick(world: World, pos: BlockPos, state: IBlockState, rand: Random): Unit = {
- if (!world.isRemote) world.getTileEntity(pos) match {
+ override def tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random): Unit = {
+ if (!world.isClientSide) world.getBlockEntity(pos) match {
case print: tileentity.Print =>
if (print.state) print.toggleState()
- if (print.state) world.scheduleUpdate(pos, state.getBlock, tickRate(world))
case _ =>
}
}
- override def isBeaconBase(world: IBlockAccess, pos: BlockPos, beacon: BlockPos): Boolean = {
- world.getTileEntity(pos) match {
+ @Deprecated
+ def isBeaconBase(world: IBlockReader, pos: BlockPos, beacon: BlockPos): Boolean = {
+ world.getBlockEntity(pos) match {
case print: tileentity.Print => print.data.isBeaconBase
case _ => false
}
@@ -154,41 +114,49 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(worldIn: World, meta: Int) = new tileentity.Print()
+ override def newBlockEntity(worldIn: IBlockReader) = new tileentity.Print(tileentity.TileEntityTypes.PRINT)
// ----------------------------------------------------------------------- //
- override def onBlockActivated(world: World, pos: BlockPos, state: IBlockState, player: EntityPlayer, hand: EnumHand, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- world.getTileEntity(pos) match {
- case print: tileentity.Print => print.activate()
- case _ => super.onBlockActivated(world, pos, state, player, hand, side, hitX, hitY, hitZ)
+ override def use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, trace: BlockRayTraceResult): ActionResultType = {
+ world.getBlockEntity(pos) match {
+ case print: tileentity.Print => if (print.activate()) ActionResultType.sidedSuccess(world.isClientSide) else ActionResultType.PASS
+ case _ => super.use(state, world, pos, player, hand, trace)
}
}
- override protected def doCustomInit(tileEntity: tileentity.Print, player: EntityLivingBase, stack: ItemStack): Unit = {
- super.doCustomInit(tileEntity, player, stack)
- tileEntity.data.load(stack)
- tileEntity.updateBounds()
- tileEntity.updateRedstone()
- tileEntity.getWorld.checkLight(tileEntity.getPos)
- }
-
- override protected def doCustomDrops(tileEntity: tileentity.Print, player: EntityPlayer, willHarvest: Boolean): Unit = {
- super.doCustomDrops(tileEntity, player, willHarvest)
- if (!player.capabilities.isCreativeMode) {
- InventoryUtils.spawnStackInWorld(tileEntity.position, tileEntity.data.createItemStack())
+ override def onRemove(state: BlockState, world: World, pos: BlockPos, newState: BlockState, moved: Boolean): Unit = {
+ world.getBlockEntity(pos) match {
+ case print: tileentity.Print if print.data.emitRedstone(print.state) =>
+ world.updateNeighborsAt(pos, this)
+ for (side <- Direction.values) {
+ world.updateNeighborsAt(pos.relative(side), this)
+ }
+ case _ =>
}
+ super.onRemove(state, world, pos, newState, moved)
}
- override def breakBlock(world: World, pos: BlockPos, state: IBlockState): Unit = {
- world.getTileEntity(pos) match {
- case print: tileentity.Print if print.data.emitRedstone(print.state) =>
- world.notifyNeighborsOfStateChange(pos, this, false)
- for (side <- EnumFacing.values) {
- world.notifyNeighborsOfStateChange(pos.offset(side), this, false)
- }
+ override def setPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity, stack: ItemStack): Unit = {
+ super.setPlacedBy(world, pos, state, placer, stack)
+ world.getBlockEntity(pos) match {
+ case tileEntity: tileentity.Print => {
+ tileEntity.data.loadData(stack)
+ tileEntity.updateShape()
+ tileEntity.updateRedstone()
+ tileEntity.getLevel.getLightEngine.checkBlock(tileEntity.getBlockPos)
+ }
case _ =>
}
- super.breakBlock(world, pos, state)
+ }
+
+ override def getDrops(state: BlockState, ctx: LootContext.Builder): util.List[ItemStack] = {
+ val newCtx = ctx.withDynamicDrop(LootFunctions.DYN_ITEM_DATA, (c, f) => {
+ c.getParamOrNull(LootParameters.BLOCK_ENTITY) match {
+ case tileEntity: tileentity.Print => f.accept(tileEntity.data.createItemStack())
+ case _ =>
+ }
+ })
+ super.getDrops(state, newCtx)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/Printer.scala b/src/main/scala/li/cil/oc/common/block/Printer.scala
index 78bc42fd20..90cf805894 100644
--- a/src/main/scala/li/cil/oc/common/block/Printer.scala
+++ b/src/main/scala/li/cil/oc/common/block/Printer.scala
@@ -1,25 +1,35 @@
package li.cil.oc.common.block
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.util.EnumFacing
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.shapes.IBooleanFunction
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Printer extends SimpleBlock with traits.StateAware with traits.GUI {
- override def isOpaqueCube(state: IBlockState): Boolean = false
+class Printer(props: Properties) extends SimpleBlock(props) with traits.StateAware with traits.GUI {
+ val blockShape = {
+ val base = Block.box(0, 0, 0, 16, 8, 16)
+ val pillars = VoxelShapes.or(Block.box(0, 8, 0, 3, 13, 3), Block.box(13, 8, 0, 16, 13, 3),
+ Block.box(13, 8, 13, 16, 13, 16), Block.box(0, 8, 13, 3, 13, 16))
+ val ring = VoxelShapes.join(Block.box(0, 13, 0, 16, 16, 16),
+ Block.box(3, 13, 3, 13, 16, 13), IBooleanFunction.ONLY_FIRST)
+ VoxelShapes.or(base, pillars, ring)
+ }
- override def isFullCube(state: IBlockState): Boolean = false
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = blockShape
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Printer => ContainerTypes.openPrinterGui(player, te)
+ case _ =>
+ }
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN
-
- // ----------------------------------------------------------------------- //
-
- override def guiType = GuiType.Printer
-
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Printer()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Printer(tileentity.TileEntityTypes.PRINTER)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Rack.scala b/src/main/scala/li/cil/oc/common/block/Rack.scala
index e2e20051ed..f5de252cb9 100644
--- a/src/main/scala/li/cil/oc/common/block/Rack.scala
+++ b/src/main/scala/li/cil/oc/common/block/Rack.scala
@@ -2,124 +2,57 @@ package li.cil.oc.common.block
import li.cil.oc.Settings
import li.cil.oc.api.component.RackMountable
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumFacing.Axis
-import net.minecraft.util.EnumHand
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.state.StateContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.Direction.Axis
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.RayTraceResult
import net.minecraft.util.math.RayTraceResult
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-import net.minecraftforge.common.property.ExtendedBlockState
-import net.minecraftforge.common.property.IExtendedBlockState
-class Rack extends RedstoneAware with traits.PowerAcceptor with traits.StateAware with traits.GUI {
- override def createBlockState() = new ExtendedBlockState(this, Array(PropertyRotatable.Facing), Array(property.PropertyTile.Tile))
-
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Facing, EnumFacing.getHorizontal(meta))
-
- override def getMetaFromState(state: IBlockState): Int = state.getValue(PropertyRotatable.Facing).getHorizontalIndex
-
- override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos): IBlockState = {
- ((state, world.getTileEntity(pos)) match {
- case (extendedState: IExtendedBlockState, tile: tileentity.traits.TileEntity) =>
- extendedState.withProperty(property.PropertyTile.Tile, tile)
- case _ => state
- }).withProperty(PropertyRotatable.Facing, getFacing(world, pos))
- }
-
- // @SideOnly(Side.CLIENT)
- // override def getMixedBrightnessForBlock(world: IBlockAccess, pos: BlockPos) = {
- // if (pos.getY >= 0 && pos.getY < 256) world.getTileEntity(pos) match {
- // case rack: tileentity.Rack =>
- // def brightness(pos: BlockPos) = world.getCombinedLight(pos, world.getBlockState(pos).getBlock.getLightValue(world, pos))
- // val value = brightness(pos.offset(rack.facing))
- // val skyBrightness = (value >> 20) & 15
- // val blockBrightness = (value >> 4) & 15
- // ((skyBrightness * 3 / 4) << 20) | ((blockBrightness * 3 / 4) << 4)
- // case _ => super.getMixedBrightnessForBlock(world, pos)
- // }
- // else super.getMixedBrightnessForBlock(world, pos)
- // }
-
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.SOUTH
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = toLocal(world, pos, side) != EnumFacing.SOUTH
+class Rack(props: Properties) extends RedstoneAware(props) with traits.PowerAcceptor with traits.StateAware with traits.GUI {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Facing)
// ----------------------------------------------------------------------- //
override def energyThroughput = Settings.get.serverRackRate
- override def guiType = GuiType.Rack
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Rack => ContainerTypes.openRackGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Rack()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Rack(tileentity.TileEntityTypes.RACK)
// ----------------------------------------------------------------------- //
- final val collisionBounds = Array(
- new AxisAlignedBB(0, 0, 0, 1, 1 / 16f, 1),
- new AxisAlignedBB(0, 15 / 16f, 0, 1, 1, 1),
- new AxisAlignedBB(0, 0, 0, 1, 1, 1 / 16f),
- new AxisAlignedBB(0, 0, 15 / 16f, 1, 1, 1),
- new AxisAlignedBB(0, 0, 0, 1 / 16f, 1, 1),
- new AxisAlignedBB(15 / 16f, 0, 0, 1, 1, 1),
- new AxisAlignedBB(0.5f / 16f, 0.5f / 16f, 0.5f / 16f, 15.5f / 16f, 15.5f / 16f, 15.5f / 16f)
- )
-
- override def collisionRayTrace(state: IBlockState, world: World, pos: BlockPos, start: Vec3d, end: Vec3d): RayTraceResult = {
- world.getTileEntity(pos) match {
- case rack: tileentity.Rack =>
- var closestDistance = Double.PositiveInfinity
- var closest: Option[RayTraceResult] = None
-
- def intersect(bounds: AxisAlignedBB): Unit = {
- val hit = bounds.offset(pos.getX, pos.getY, pos.getZ).calculateIntercept(start, end)
- if (hit != null) {
- val distance = hit.hitVec.distanceTo(start)
- if (distance < closestDistance) {
- closestDistance = distance
- closest = Option(hit)
- }
- }
- }
- val facings = EnumFacing.VALUES
- for (i <- 0 until facings.length) {
- if (rack.facing != facings(i)) {
- intersect(collisionBounds(i))
- }
- }
- intersect(collisionBounds.last)
- closest.map(hit => new RayTraceResult(hit.hitVec, hit.sideHit, pos)).orNull
- case _ => super.collisionRayTrace(state, world, pos, start, end)
- }
- }
-
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- world.getTileEntity(pos) match {
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ world.getBlockEntity(pos) match {
case rack: tileentity.Rack => rack.slotAt(side, hitX, hitY, hitZ) match {
case Some(slot) =>
// Snap to grid to get same behavior on client and server...
- val hitVec = new Vec3d((hitX * 16f).toInt / 16f, (hitY * 16f).toInt / 16f, (hitZ * 16f).toInt / 16f)
+ val hitVec = new Vector3d((hitX * 16f).toInt / 16f, (hitY * 16f).toInt / 16f, (hitZ * 16f).toInt / 16f)
val rotation = side match {
- case EnumFacing.WEST => Math.toRadians(90).toFloat
- case EnumFacing.NORTH => Math.toRadians(180).toFloat
- case EnumFacing.EAST => Math.toRadians(270).toFloat
+ case Direction.WEST => Math.toRadians(90).toFloat
+ case Direction.NORTH => Math.toRadians(180).toFloat
+ case Direction.EAST => Math.toRadians(270).toFloat
case _ => 0
}
// Rotate *centers* of pixels to keep association when reversing axis.
- val localHitVec = rotate(hitVec.addVector(-0.5 + 1 / 32f, -0.5 + 1 / 32f, -0.5 + 1 / 32f), rotation).addVector(0.5 - 1 / 32f, 0.5 - 1 / 32f, 0.5 - 1 / 32f)
+ val localHitVec = rotate(hitVec.add(-0.5 + 1 / 32f, -0.5 + 1 / 32f, -0.5 + 1 / 32f), rotation).add(0.5 - 1 / 32f, 0.5 - 1 / 32f, 0.5 - 1 / 32f)
val globalX = (localHitVec.x * 16.05f).toInt // [0, 15], work around floating point inaccuracies
val globalY = (localHitVec.y * 16.05f).toInt // [0, 15], work around floating point inaccuracies
val localX = (if (side.getAxis != Axis.Z) 15 - globalX else globalX) - 1
@@ -135,9 +68,9 @@ class Rack extends RedstoneAware with traits.PowerAcceptor with traits.StateAwar
super.localOnBlockActivated(world, pos, player, hand, heldItem, side, hitX, hitY, hitZ)
}
- def rotate(v: Vec3d, t: Float): Vec3d = {
+ def rotate(v: Vector3d, t: Float): Vector3d = {
val cos = Math.cos(t)
val sin = Math.sin(t)
- new Vec3d(v.x * cos - v.z * sin, v.y, v.x * sin + v.z * cos)
+ new Vector3d(v.x * cos - v.z * sin, v.y, v.x * sin + v.z * cos)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/Raid.scala b/src/main/scala/li/cil/oc/common/block/Raid.scala
index b230a8b924..0bb5fb63aa 100644
--- a/src/main/scala/li/cil/oc/common/block/Raid.scala
+++ b/src/main/scala/li/cil/oc/common/block/Raid.scala
@@ -3,81 +3,113 @@ package li.cil.oc.common.block
import java.util
import li.cil.oc.client.KeyBindings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.item.data.RaidData
import li.cil.oc.common.tileentity
+import li.cil.oc.server.loot.LootFunctions
+import li.cil.oc.util.Tooltip
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
+import net.minecraft.state.StateContainer
+import net.minecraft.loot.LootContext
+import net.minecraft.loot.LootParameters
+import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeBlock
import scala.reflect.ClassTag
-class Raid(protected implicit val tileTag: ClassTag[tileentity.Raid]) extends SimpleBlock with traits.GUI with traits.CustomDrops[tileentity.Raid] {
- override def createBlockState() = new BlockStateContainer(this, PropertyRotatable.Facing)
+class Raid(props: Properties) extends SimpleBlock(props) with IForgeBlock with traits.GUI {
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Facing, EnumFacing.getHorizontal(meta))
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Facing)
- override def getMetaFromState(state: IBlockState): Int = state.getValue(PropertyRotatable.Facing).getHorizontalIndex
-
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, advanced)
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ super.tooltipTail(stack, world, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
val data = new RaidData(stack)
for (disk <- data.disks if !disk.isEmpty) {
- tooltip.add("- " + disk.getDisplayName)
+ tooltip.add(new StringTextComponent("- " + disk.getHoverName.getString).setStyle(Tooltip.DefaultStyle))
}
}
}
// ----------------------------------------------------------------------- //
- override def guiType = GuiType.Raid
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Raid => ContainerTypes.openRaidGui(player, te)
+ case _ =>
+ }
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Raid()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Raid(tileentity.TileEntityTypes.RAID)
// ----------------------------------------------------------------------- //
- override def hasComparatorInputOverride(state: IBlockState): Boolean = true
+ override def hasAnalogOutputSignal(state: BlockState): Boolean = true
- override def getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int =
- world.getTileEntity(pos) match {
+ override def getAnalogOutputSignal(state: BlockState, world: World, pos: BlockPos): Int =
+ world.getBlockEntity(pos) match {
case raid: tileentity.Raid if raid.presence.forall(ok => ok) => 15
case _ => 0
}
- override protected def doCustomInit(tileEntity: tileentity.Raid, player: EntityLivingBase, stack: ItemStack): Unit = {
- super.doCustomInit(tileEntity, player, stack)
- if (!tileEntity.world.isRemote) {
- val data = new RaidData(stack)
- for (i <- 0 until math.min(data.disks.length, tileEntity.getSizeInventory)) {
- tileEntity.setInventorySlotContents(i, data.disks(i))
- }
- data.label.foreach(tileEntity.label.setLabel)
- if (!data.filesystem.hasNoTags) {
- tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address"))
- tileEntity.filesystem.foreach(_.load(data.filesystem))
+ override def setPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity, stack: ItemStack): Unit = {
+ super.setPlacedBy(world, pos, state, placer, stack)
+ world.getBlockEntity(pos) match {
+ case tileEntity: tileentity.Raid if !world.isClientSide => {
+ val data = new RaidData(stack)
+ for (i <- 0 until math.min(data.disks.length, tileEntity.getContainerSize)) {
+ tileEntity.setItem(i, data.disks(i))
+ }
+ data.label.foreach(tileEntity.label.setLabel)
+ if (!data.filesystem.isEmpty) {
+ tileEntity.tryCreateRaid(data.filesystem.getCompound("node").getString("address"))
+ tileEntity.filesystem.foreach(_.loadData(data.filesystem))
+ }
}
+ case _ =>
}
}
- override protected def doCustomDrops(tileEntity: tileentity.Raid, player: EntityPlayer, willHarvest: Boolean): Unit = {
- super.doCustomDrops(tileEntity, player, willHarvest)
- val stack = createItemStack()
- if (tileEntity.items.exists(!_.isEmpty)) {
- val data = new RaidData()
- data.disks = tileEntity.items.clone()
- tileEntity.filesystem.foreach(_.save(data.filesystem))
- data.label = Option(tileEntity.label.getLabel)
- data.save(stack)
+ override def getDrops(state: BlockState, ctx: LootContext.Builder): util.List[ItemStack] = {
+ val newCtx = ctx.withDynamicDrop(LootFunctions.DYN_ITEM_DATA, (c, f) => {
+ c.getParamOrNull(LootParameters.BLOCK_ENTITY) match {
+ case tileEntity: tileentity.Raid => {
+ val stack = createItemStack()
+ if (tileEntity.items.exists(!_.isEmpty)) {
+ val data = new RaidData()
+ data.disks = tileEntity.items.clone()
+ tileEntity.filesystem.foreach(_.saveData(data.filesystem))
+ data.label = Option(tileEntity.label.getLabel)
+ data.saveData(stack)
+ }
+ f.accept(stack)
+ }
+ case _ =>
+ }
+ })
+ super.getDrops(state, newCtx)
+ }
+
+ override def playerWillDestroy(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
+ if (!world.isClientSide && player.isCreative) {
+ world.getBlockEntity(pos) match {
+ case tileEntity: tileentity.Raid if tileEntity.items.exists(!_.isEmpty) =>
+ Block.dropResources(state, world, pos, tileEntity, player, player.getMainHandItem)
+ case _ =>
+ }
}
- Block.spawnAsEntity(tileEntity.world, tileEntity.getPos, stack)
+ super.playerWillDestroy(world, pos, state, player)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/Redstone.scala b/src/main/scala/li/cil/oc/common/block/Redstone.scala
index 3e4288b422..3cc588e5f5 100644
--- a/src/main/scala/li/cil/oc/common/block/Redstone.scala
+++ b/src/main/scala/li/cil/oc/common/block/Redstone.scala
@@ -5,24 +5,27 @@ import java.util
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
import li.cil.oc.util.Tooltip
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Redstone extends RedstoneAware {
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, advanced)
+import scala.collection.convert.ImplicitConversionsToScala._
+
+class Redstone(props: Properties) extends RedstoneAware(props) {
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ super.tooltipTail(stack, world, tooltip, advanced)
// todo more generic way for redstone mods to provide lines
if (Mods.ProjectRedTransmission.isModAvailable) {
- tooltip.addAll(Tooltip.get("RedstoneCard.ProjectRed"))
- }
- if (Mods.Charset.isModAvailable) {
- tooltip.addAll(Tooltip.get("RedstoneCard.Charset"))
+ for (curr <- Tooltip.get("redstonecard.ProjectRed")) tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
}
}
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Redstone()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Redstone(tileentity.TileEntityTypes.REDSTONE_IO)
}
diff --git a/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala
index 8be1840b00..868b7e89ce 100644
--- a/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala
+++ b/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala
@@ -1,35 +1,38 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
+import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
-import net.minecraft.util.EnumFacing
+import net.minecraft.block.BlockState
+import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-abstract class RedstoneAware extends SimpleBlock {
- override def canProvidePower(state: IBlockState): Boolean = true
+abstract class RedstoneAware(props: Properties) extends SimpleBlock(props) {
+ override def isSignalSource(state: BlockState): Boolean = true
- override def canConnectRedstone(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean =
- world.getTileEntity(pos) match {
+ override def canConnectRedstone(state: BlockState, world: IBlockReader, pos: BlockPos, side: Direction): Boolean =
+ world.getBlockEntity(pos) match {
case redstone: tileentity.traits.RedstoneAware => redstone.isOutputEnabled
case _ => false
}
- override def getStrongPower(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) =
- getWeakPower(state, world, pos, side)
+ override def getDirectSignal(state: BlockState, world: IBlockReader, pos: BlockPos, side: Direction) =
+ getSignal(state, world, pos, side)
- override def getWeakPower(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) =
- world.getTileEntity(pos) match {
+ @Deprecated
+ override def getSignal(state: BlockState, world: IBlockReader, pos: BlockPos, side: Direction) =
+ world.getBlockEntity(pos) match {
case redstone: tileentity.traits.RedstoneAware if side != null => redstone.getOutput(side.getOpposite) max 0
- case _ => super.getWeakPower(state, world, pos, side)
+ case _ => super.getSignal(state, world, pos, side)
}
// ----------------------------------------------------------------------- //
- override def neighborChanged(state: IBlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos): Unit = {
- world.getTileEntity(pos) match {
+ @Deprecated
+ override def neighborChanged(state: BlockState, world: World, pos: BlockPos, block: Block, fromPos: BlockPos, b: Boolean): Unit = {
+ world.getBlockEntity(pos) match {
case redstone: tileentity.traits.RedstoneAware => redstone.checkRedstoneInputChanged()
case _ => // Ignore.
}
diff --git a/src/main/scala/li/cil/oc/common/block/Relay.scala b/src/main/scala/li/cil/oc/common/block/Relay.scala
index 2d9ea12b20..9bc69b21a0 100644
--- a/src/main/scala/li/cil/oc/common/block/Relay.scala
+++ b/src/main/scala/li/cil/oc/common/block/Relay.scala
@@ -1,14 +1,21 @@
package li.cil.oc.common.block
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.tileentity
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.util.math.BlockPos
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Relay extends SimpleBlock with traits.GUI with traits.PowerAcceptor {
- override def guiType = GuiType.Relay
+class Relay(props: Properties) extends SimpleBlock(props) with traits.GUI with traits.PowerAcceptor {
+ override def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos): Unit = world.getBlockEntity(pos) match {
+ case te: tileentity.Relay => ContainerTypes.openRelayGui(player, te)
+ case _ =>
+ }
override def energyThroughput = Settings.get.accessPointRate
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Relay()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Relay(tileentity.TileEntityTypes.RELAY)
}
diff --git a/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala b/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala
index 7d8e890daf..4cf5fbdf8b 100644
--- a/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala
+++ b/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala
@@ -5,105 +5,81 @@ import java.util.Random
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
-import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.util.ItemBlacklist
-import li.cil.oc.util.Rarity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Blocks
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.fluid.FluidState
import net.minecraft.item.ItemStack
-import net.minecraft.util._
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
+import net.minecraft.util.math.BlockRayTraceResult
import net.minecraft.util.math.RayTraceResult
-import net.minecraft.util.math.Vec3i
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
+import net.minecraft.world.server.ServerWorld
-class RobotAfterimage extends SimpleBlock {
- setLightOpacity(0)
- setCreativeTab(null)
- ItemBlacklist.hide(this)
-
- // ----------------------------------------------------------------------- //
-
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def getPickBlock(state: IBlockState, target: RayTraceResult, world: World, pos: BlockPos, player: EntityPlayer): ItemStack =
+class RobotAfterimage(props: Properties) extends SimpleBlock(props) {
+ override def getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack =
findMovingRobot(world, pos) match {
case Some(robot) => robot.info.createItemStack()
case _ => ItemStack.EMPTY
}
- override def getBoundingBox(state: IBlockState, world: IBlockAccess, pos: BlockPos): AxisAlignedBB = {
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = {
findMovingRobot(world, pos) match {
case Some(robot) =>
- val block = robot.getBlockType.asInstanceOf[SimpleBlock]
- val bounds = block.getBoundingBox(state, world, robot.getPos)
- val delta = robot.moveFrom.fold(Vec3i.NULL_VECTOR)(vec => {
- val blockPos = robot.getPos
+ val block = robot.getBlockState.getBlock.asInstanceOf[SimpleBlock]
+ val shape = block.getShape(state, world, robot.getBlockPos, ctx)
+ val delta = robot.moveFrom.fold(BlockPos.ZERO)(vec => {
+ val blockPos = robot.getBlockPos
new BlockPos(blockPos.getX - vec.getX, blockPos.getY - vec.getY, blockPos.getZ - vec.getZ)
})
- bounds.offset(delta.getX, delta.getY, delta.getZ)
- case _ => super.getBoundingBox(state, world, pos)
+ shape.move(delta.getX, delta.getY, delta.getZ)
+ case _ => super.getShape(state, world, pos, ctx)
}
}
// ----------------------------------------------------------------------- //
- override def hasTileEntity(state: IBlockState): Boolean = false
-
- override def createNewTileEntity(worldIn: World, meta: Int) = null
-
- // ----------------------------------------------------------------------- //
-
- override def rarity(stack: ItemStack) = {
- val data = new RobotData(stack)
- Rarity.byTier(data.tier)
- }
-
- override def isAir(state: IBlockState, world: IBlockAccess, pos: BlockPos): Boolean = true
-
- // ----------------------------------------------------------------------- //
-
- override def onBlockAdded(world: World, pos: BlockPos, state: IBlockState) {
- world.scheduleUpdate(pos, this, Math.max((Settings.get.moveDelay * 20).toInt, 1) - 1)
+ override def onPlace(state: BlockState, world: World, pos: BlockPos, prevState: BlockState, moved: Boolean): Unit = {
+ if (!world.isClientSide) {
+ world.asInstanceOf[ServerWorld].getBlockTicks.scheduleTick(pos, this, Math.max((Settings.get.moveDelay * 20).toInt, 1) - 1)
+ }
}
- override def updateTick(world: World, pos: BlockPos, state: IBlockState, rand: Random) {
- world.setBlockToAir(pos)
+ override def tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
+ world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState)
}
- override def removedByPlayer(state: IBlockState, world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean): Boolean = {
+ override def removedByPlayer(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, willHarvest: Boolean, fluid: FluidState): Boolean = {
findMovingRobot(world, pos) match {
case Some(robot) if robot.isAnimatingMove && robot.moveFrom.contains(pos) =>
- robot.proxy.getBlockType.removedByPlayer(state, world, pos, player, false)
- case _ => super.removedByPlayer(state, world, pos, player, willHarvest) // Probably broken by the robot we represent.
+ robot.proxy.getBlockState.getBlock.removedByPlayer(state, world, pos, player, false, fluid)
+ case _ => super.removedByPlayer(state, world, pos, player, willHarvest, fluid) // Probably broken by the robot we represent.
}
}
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
+ @Deprecated
+ override def use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, trace: BlockRayTraceResult): ActionResultType = {
findMovingRobot(world, pos) match {
- case Some(robot) => api.Items.get(Constants.BlockName.Robot).block.onBlockActivated(world, robot.getPos, world.getBlockState(robot.getPos), player, hand, side, hitX, hitY, hitZ)
- case _ => world.setBlockToAir(pos)
+ case Some(robot) => api.Items.get(Constants.BlockName.Robot).block.use(world.getBlockState(robot.getBlockPos), world, robot.getBlockPos, player, hand, trace)
+ case _ => if (world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState)) ActionResultType.sidedSuccess(world.isClientSide) else ActionResultType.PASS
}
}
- def findMovingRobot(world: IBlockAccess, pos: BlockPos): Option[tileentity.Robot] = {
- for (side <- EnumFacing.values) {
- val tpos = pos.offset(side)
+ def findMovingRobot(world: IBlockReader, pos: BlockPos): Option[tileentity.Robot] = {
+ for (side <- Direction.values) {
+ val tpos = pos.relative(side)
if (world match {
- case world: World => world.isBlockLoaded(tpos)
+ case world: World => world.isLoaded(tpos)
case _ => true
- }) world.getTileEntity(tpos) match {
+ }) world.getBlockEntity(tpos) match {
case proxy: tileentity.RobotProxy if proxy.robot.moveFrom.contains(pos) => return Some(proxy.robot)
case _ =>
}
diff --git a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala
index 437b13dc45..af4c8bb981 100644
--- a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala
+++ b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala
@@ -3,41 +3,46 @@ package li.cil.oc.common.block
import java.util
import li.cil.oc.Constants
-import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.client.KeyBindings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.util.ItemBlacklist
import li.cil.oc.server.PacketSender
import li.cil.oc.server.agent
+import li.cil.oc.server.loot.LootFunctions
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.InventoryUtils
-import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumRarity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.fluid.FluidState
import net.minecraft.item.ItemStack
-import net.minecraft.util._
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.loot.LootContext
+import net.minecraft.loot.LootParameters
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.RayTraceResult
-import net.minecraft.util.math.Vec3d
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.shapes.ISelectionContext
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class RobotProxy extends RedstoneAware with traits.StateAware {
- setLightOpacity(0)
- setCreativeTab(null)
- ItemBlacklist.hide(this)
+import scala.collection.convert.ImplicitConversionsToScala._
- override val getUnlocalizedName = "robot"
+class RobotProxy(props: Properties) extends RedstoneAware(props) with traits.StateAware {
+ val shape = VoxelShapes.box(0.1, 0.1, 0.1, 0.9, 0.9, 0.9)
+
+ override val getDescriptionId = "robot"
var moving = new ThreadLocal[Option[tileentity.Robot]] {
override protected def initialValue = None
@@ -45,82 +50,74 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
// ----------------------------------------------------------------------- //
- override def isOpaqueCube(state: IBlockState): Boolean = false
-
- override def isFullCube(state: IBlockState): Boolean = false
-
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
-
- override def getPickBlock(state: IBlockState, target: RayTraceResult, world: World, pos: BlockPos, player: EntityPlayer): ItemStack =
- world.getTileEntity(pos) match {
+ override def getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack =
+ world.getBlockEntity(pos) match {
case proxy: tileentity.RobotProxy => proxy.robot.info.copyItemStack()
case _ => ItemStack.EMPTY
}
- override def getBoundingBox(state: IBlockState, world: IBlockAccess, pos: BlockPos): AxisAlignedBB = {
- world.getTileEntity(pos) match {
+ override def getShape(state: BlockState, world: IBlockReader, pos: BlockPos, ctx: ISelectionContext): VoxelShape = {
+ world.getBlockEntity(pos) match {
case proxy: tileentity.RobotProxy =>
val robot = proxy.robot
- val bounds = new AxisAlignedBB(0.1, 0.1, 0.1, 0.9, 0.9, 0.9)
if (robot.isAnimatingMove) {
val remaining = robot.animationTicksLeft.toDouble / robot.animationTicksTotal.toDouble
val blockPos = robot.moveFrom.get
- val vec = robot.getPos
+ val vec = robot.getBlockPos
val delta = new BlockPos(blockPos.getX - vec.getX, blockPos.getY - vec.getY, blockPos.getZ - vec.getZ)
- bounds.offset(delta.getX * remaining, delta.getY * remaining, delta.getZ * remaining)
+ shape.move(delta.getX * remaining, delta.getY * remaining, delta.getZ * remaining)
}
- else bounds
- case _ => super.getBoundingBox(state, world, pos)
+ else shape
+ case _ => super.getShape(state, world, pos, ctx)
}
}
// ----------------------------------------------------------------------- //
- override def rarity(stack: ItemStack): EnumRarity = {
- val data = new RobotData(stack)
- Rarity.byTier(data.tier)
- }
-
- override protected def tooltipHead(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- super.tooltipHead(metadata, stack, world, tooltip, advanced)
+ override protected def tooltipHead(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ super.tooltipHead(stack, world, tooltip, advanced)
addLines(stack, tooltip)
}
- override protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- tooltip.addAll(Tooltip.get("robot"))
+ override protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ for (curr <- Tooltip.get("robot")) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, flag)
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.tooltipTail(stack, world, tooltip, flag)
if (KeyBindings.showExtendedTooltips) {
val info = new RobotData(stack)
val components = info.containers ++ info.components
if (components.length > 0) {
- tooltip.addAll(Tooltip.get("server.Components"))
+ for (curr <- Tooltip.get("server.Components")) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
for (component <- components if !component.isEmpty) {
- tooltip.add("- " + component.getDisplayName)
+ tooltip.add(new StringTextComponent("- " + component.getHoverName.getString).setStyle(Tooltip.DefaultStyle))
}
}
}
}
- private def addLines(stack: ItemStack, tooltip: util.List[String]) {
- if (stack.hasTagCompound) {
- if (stack.getTagCompound.hasKey(Settings.namespace + "xp")) {
- val xp = stack.getTagCompound.getDouble(Settings.namespace + "xp")
+ private def addLines(stack: ItemStack, tooltip: util.List[ITextComponent]) {
+ if (stack.hasTag) {
+ if (stack.getTag.contains(Settings.namespace + "xp")) {
+ val xp = stack.getTag.getDouble(Settings.namespace + "xp")
val level = Math.min((Math.pow(xp - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt, 30)
if (level > 0) {
- tooltip.addAll(Tooltip.get(getUnlocalizedName + "_level", level))
+ for (curr <- Tooltip.get(getDescriptionId + "_level", level)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
}
- if (stack.getTagCompound.hasKey(Settings.namespace + "storedEnergy")) {
- val energy = stack.getTagCompound.getInteger(Settings.namespace + "storedEnergy")
+ if (stack.getTag.contains(Settings.namespace + "storedEnergy")) {
+ val energy = stack.getTag.getInt(Settings.namespace + "storedEnergy")
if (energy > 0) {
- tooltip.addAll(Tooltip.get(getUnlocalizedName + "_storedenergy", energy))
+ for (curr <- Tooltip.get(getDescriptionId + "_storedenergy", energy)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
}
}
@@ -128,20 +125,16 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int): tileentity.RobotProxy = {
+ override def newBlockEntity(world: IBlockReader): tileentity.RobotProxy = {
moving.get match {
- case Some(robot) => new tileentity.RobotProxy(robot)
- case _ => new tileentity.RobotProxy()
+ case Some(robot) => new tileentity.RobotProxy(tileentity.TileEntityTypes.ROBOT, robot)
+ case _ => new tileentity.RobotProxy(tileentity.TileEntityTypes.ROBOT)
}
}
// ----------------------------------------------------------------------- //
- override def getExplosionResistance(entity: Entity) = 10f
-
- override def getDrops(world: IBlockAccess, pos: BlockPos, state: IBlockState, fortune: Int): util.ArrayList[ItemStack] = {
- val list = new java.util.ArrayList[ItemStack]()
-
+ override def getDrops(state: BlockState, ctx: LootContext.Builder): util.List[ItemStack] = {
// Superspecial hack... usually this will not work, because Minecraft calls
// this method *after* the block has already been destroyed. Meaning we
// won't have access to the tile entity.
@@ -153,24 +146,26 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
// mod calls this before the block is broken *and* calls removedByPlayer
// this will lead to dupes, but in some initial testing this wasn't the
// case anywhere (TE autonomous activator, CC turtles).
- world.getTileEntity(pos) match {
- case proxy: tileentity.RobotProxy =>
- val robot = proxy.robot
- if (robot.node != null) {
- // Update: even more special hack! As discussed here http://git.io/IcNAyg
- // some mods call this even when they're not about to actually break the
- // block... soooo we need a whitelist to know when to generate a *proper*
- // drop (i.e. with file systems closed / open handles not saved, e.g.).
- if (gettingDropsForActualDrop) {
- robot.node.remove()
- robot.saveComponents()
+ val newCtx = ctx.withDynamicDrop(LootFunctions.DYN_ITEM_DATA, (c, f) => {
+ c.getParamOrNull(LootParameters.BLOCK_ENTITY) match {
+ case proxy: tileentity.RobotProxy =>
+ val robot = proxy.robot
+ if (robot.node != null) {
+ // Update: even more special hack! As discussed here http://git.io/IcNAyg
+ // some mods call this even when they're not about to actually break the
+ // block... soooo we need a whitelist to know when to generate a *proper*
+ // drop (i.e. with file systems closed / open handles not saved, e.g.).
+ if (gettingDropsForActualDrop) {
+ robot.node.remove()
+ robot.saveComponents()
+ }
+ f.accept(robot.info.createItemStack())
}
- list.add(robot.info.createItemStack())
- }
- case _ =>
- }
+ case _ =>
+ }
+ })
- list
+ super.getDrops(state, newCtx)
}
private val getDropForRealDropCallers = Set(
@@ -179,35 +174,29 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
private def gettingDropsForActualDrop = new Exception().getStackTrace.exists(element => getDropForRealDropCallers.contains(element.getClassName + "." + element.getMethodName))
- override def collisionRayTrace(state: IBlockState, world: World, pos: BlockPos, start: Vec3d, end: Vec3d): RayTraceResult = {
- val bounds = getCollisionBoundingBox(state, world, pos)
- world.getTileEntity(pos) match {
- case proxy: tileentity.RobotProxy if proxy.robot.animationTicksLeft <= 0 && bounds.contains(start) => null
- case _ => super.collisionRayTrace(state, world, pos, start, end)
- }
- }
-
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- if (!player.isSneaking) {
- if (!world.isRemote) {
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ if (!player.isCrouching) {
+ if (!world.isClientSide) {
// We only send slot changes to nearby players, so if there was no slot
// change since this player got into range he might have the wrong one,
// so we send him the current one just in case.
- world.getTileEntity(pos) match {
- case proxy: tileentity.RobotProxy if proxy.robot.node.network != null =>
+ (player, world.getBlockEntity(pos)) match {
+ case (srvPlr: ServerPlayerEntity, proxy: tileentity.RobotProxy) if proxy.robot.node.network != null =>
PacketSender.sendRobotSelectedSlotChange(proxy.robot)
- player.openGui(OpenComputers, GuiType.Robot.id, world, pos.getX, pos.getY, pos.getZ)
+ if (proxy.stillValid(player)) {
+ ContainerTypes.openRobotGui(srvPlr, proxy.robot)
+ }
case _ =>
}
}
true
}
else if (heldItem.isEmpty) {
- if (!world.isRemote) {
- world.getTileEntity(pos) match {
- case proxy: tileentity.RobotProxy if !proxy.machine.isRunning && proxy.isUsableByPlayer(player) => proxy.machine.start()
+ if (!world.isClientSide) {
+ world.getBlockEntity(pos) match {
+ case proxy: tileentity.RobotProxy if !proxy.machine.isRunning && proxy.stillValid(player) => proxy.machine.start()
case _ =>
}
}
@@ -216,49 +205,45 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
else false
}
- override def onBlockPlacedBy(world: World, pos: BlockPos, state: IBlockState, entity: EntityLivingBase, stack: ItemStack) {
- super.onBlockPlacedBy(world, pos, state, entity, stack)
- if (!world.isRemote) ((entity, world.getTileEntity(pos)) match {
+ override def setPlacedBy(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity, stack: ItemStack) {
+ super.setPlacedBy(world, pos, state, entity, stack)
+ if (!world.isClientSide) ((entity, world.getBlockEntity(pos)) match {
case (player: agent.Player, proxy: tileentity.RobotProxy) =>
Some((proxy.robot, player.agent.ownerName, player.agent.ownerUUID))
- case (player: EntityPlayer, proxy: tileentity.RobotProxy) =>
- Some((proxy.robot, player.getName, player.getGameProfile.getId))
+ case (player: PlayerEntity, proxy: tileentity.RobotProxy) =>
+ Some((proxy.robot, player.getName.getString, player.getGameProfile.getId))
case _ => None
}) match {
case Some((robot, owner, uuid)) =>
robot.ownerName = owner
robot.ownerUUID = agent.Player.determineUUID(Option(uuid))
- robot.info.load(stack)
+ robot.info.loadData(stack)
robot.bot.node.changeBuffer(robot.info.robotEnergy - robot.bot.node.localBuffer)
robot.updateInventorySize()
case _ =>
}
}
- override def removedByPlayer(state: IBlockState, world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean): Boolean = {
- world.getTileEntity(pos) match {
+ override def removedByPlayer(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, willHarvest: Boolean, fluid: FluidState): Boolean = {
+ world.getBlockEntity(pos) match {
case proxy: tileentity.RobotProxy =>
val robot = proxy.robot
// Only allow breaking creative tier robots by allowed users.
// Unlike normal robots, griefing isn't really a valid concern
// here, because to get a creative robot you need creative
// mode in the first place.
- if (robot.isCreative && (!player.capabilities.isCreativeMode || !robot.canInteract(player.getName))) return false
- if (!world.isRemote) {
+ if (robot.isCreative && (!player.isCreative || !robot.canInteract(player.getName.getString))) return false
+ if (!world.isClientSide) {
if (robot.player == player) return false
robot.node.remove()
robot.saveComponents()
- InventoryUtils.spawnStackInWorld(BlockPosition(pos, world), robot.info.createItemStack())
+ if (player.isCreative) InventoryUtils.spawnStackInWorld(BlockPosition(pos, world), robot.info.createItemStack())
}
robot.moveFrom.foreach(fromPos => if (world.getBlockState(fromPos).getBlock == api.Items.get(Constants.BlockName.RobotAfterimage).block) {
- world.setBlockState(fromPos, net.minecraft.init.Blocks.AIR.getDefaultState, 1)
+ world.setBlock(fromPos, net.minecraft.block.Blocks.AIR.defaultBlockState, 1)
})
case _ =>
}
- super.removedByPlayer(state, world, pos, player, willHarvest)
+ super.removedByPlayer(state, world, pos, player, willHarvest, fluid)
}
-
- override def breakBlock(world: World, pos: BlockPos, state: IBlockState): Unit =
- if (moving.get.isEmpty)
- super.breakBlock(world, pos, state)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Screen.scala b/src/main/scala/li/cil/oc/common/block/Screen.scala
index 83b29c46f1..b2fde6fb1d 100644
--- a/src/main/scala/li/cil/oc/common/block/Screen.scala
+++ b/src/main/scala/li/cil/oc/common/block/Screen.scala
@@ -2,94 +2,81 @@ package li.cil.oc.common.block
import java.util
-import _root_.net.minecraft.entity.Entity
-import _root_.net.minecraft.entity.EntityLivingBase
-import _root_.net.minecraft.entity.player.EntityPlayer
-import _root_.net.minecraft.entity.projectile.EntityArrow
-import _root_.net.minecraft.item.ItemStack
-import _root_.net.minecraft.util.EnumFacing
-import _root_.net.minecraft.util.EnumHand
-import _root_.net.minecraft.world.{IBlockAccess, World}
-import _root_.net.minecraftforge.common.property.ExtendedBlockState
-import _root_.net.minecraftforge.common.property.IExtendedBlockState
import li.cil.oc.Constants
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
-import li.cil.oc.common.GuiType
+import li.cil.oc.client.gui
import li.cil.oc.common.block.property.PropertyRotatable
-import li.cil.oc.common.block.property.PropertyTile
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.PackedColor
-import li.cil.oc.util.Rarity
+import li.cil.oc.util.RotationHelper
import li.cil.oc.util.Tooltip
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.util.math.{AxisAlignedBB, BlockPos}
-import net.minecraftforge.fml.relauncher.{Side, SideOnly}
-
-class Screen(val tier: Int) extends RedstoneAware {
- override def createBlockState() = new ExtendedBlockState(this, Array(PropertyRotatable.Pitch, PropertyRotatable.Yaw), Array(PropertyTile.Tile))
-
- override def getMetaFromState(state: IBlockState): Int = (state.getValue(PropertyRotatable.Pitch).ordinal() << 2) | state.getValue(PropertyRotatable.Yaw).getHorizontalIndex
-
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Pitch, EnumFacing.getFront(meta >> 2)).withProperty(PropertyRotatable.Yaw, EnumFacing.getHorizontal(meta & 0x3))
-
- override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos): IBlockState =
- (state, world.getTileEntity(pos)) match {
- case (extendedState: IExtendedBlockState, tile: tileentity.Screen) =>
- extendedState.
- withProperty(property.PropertyTile.Tile, tile).
- withProperty(PropertyRotatable.Pitch, tile.pitch).
- withProperty(PropertyRotatable.Yaw, tile.yaw)
- case _ => state
- }
-
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing) = toLocal(world, pos, side) != EnumFacing.SOUTH
+import net.minecraft.entity.Entity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.projectile.ArrowEntity
+import net.minecraft.item.ItemStack
+import net.minecraft.state.StateContainer
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
+import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.{IBlockReader, World}
+import net.minecraftforge.api.distmarker.{Dist, OnlyIn}
+
+import scala.collection.convert.ImplicitConversionsToScala._
+
+class Screen(props: Properties, val tier: Int) extends RedstoneAware(props) {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Pitch, PropertyRotatable.Yaw)
// ----------------------------------------------------------------------- //
- override def rarity(stack: ItemStack) = Rarity.byTier(tier)
-
- override protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
+ override protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
val (w, h) = Settings.screenResolutionsByTier(tier)
val depth = PackedColor.Depth.bits(Settings.screenDepthsByTier(tier))
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase, w, h, depth))
+ for (curr <- Tooltip.get(getClass.getSimpleName.toLowerCase, w, h, depth)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Screen(tier)
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Screen(tileentity.TileEntityTypes.SCREEN, tier)
// ----------------------------------------------------------------------- //
- override def onBlockPlacedBy(world: World, pos: BlockPos, state: IBlockState, placer: EntityLivingBase, stack: ItemStack) {
- super.onBlockPlacedBy(world, pos, state, placer, stack)
- world.getTileEntity(pos) match {
+ override def setPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity, stack: ItemStack) {
+ super.setPlacedBy(world, pos, state, placer, stack)
+ world.getBlockEntity(pos) match {
case screen: tileentity.Screen => screen.delayUntilCheckForMultiBlock = 0
case _ =>
}
}
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = rightClick(world, pos, player, hand, heldItem, side, hitX, hitY, hitZ, force = false)
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = rightClick(world, pos, player, hand, heldItem, side, hitX, hitY, hitZ, force = false)
- def rightClick(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack,
- side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, force: Boolean) = {
+ def rightClick(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack,
+ side: Direction, hitX: Float, hitY: Float, hitZ: Float, force: Boolean) = {
if (Wrench.holdsApplicableWrench(player, pos) && getValidRotations(world, pos).contains(side) && !force) false
else if (api.Items.get(heldItem) == api.Items.get(Constants.ItemName.Analyzer)) false
- else world.getTileEntity(pos) match {
- case screen: tileentity.Screen if screen.hasKeyboard && (force || player.isSneaking == screen.origin.invertTouchMode) =>
- // Yep, this GUI is actually purely client side. We could skip this
- // if, but it is clearer this way (to trigger it from the server we
- // would have to give screens a "container", which we do not want).
- if (world.isRemote) {
- player.openGui(OpenComputers, GuiType.Screen.id, world, pos.getX, pos.getY, pos.getZ)
- }
+ else world.getBlockEntity(pos) match {
+ case screen: tileentity.Screen if screen.hasKeyboard && (force || player.isCrouching == screen.origin.invertTouchMode) =>
+ // Yep, this GUI is actually purely client side (to trigger it from
+ // the server we would have to give screens a "container", which we
+ // do not want).
+ if (world.isClientSide) showGui(screen)
true
case screen: tileentity.Screen if screen.tier > 0 && side == screen.facing =>
- if (world.isRemote && player == Minecraft.getMinecraft.player) {
+ if (world.isClientSide && player == Minecraft.getInstance.player) {
screen.click(hitX, hitY, hitZ)
}
else true
@@ -97,32 +84,37 @@ class Screen(val tier: Int) extends RedstoneAware {
}
}
- override def onEntityWalk(world: World, pos: BlockPos, entity: Entity): Unit =
- if (!world.isRemote) world.getTileEntity(pos) match {
- case screen: tileentity.Screen if screen.tier > 0 && screen.facing == EnumFacing.UP => screen.walk(entity)
- case _ => super.onEntityWalk(world, pos, entity)
+ @OnlyIn(Dist.CLIENT)
+ private def showGui(screen: tileentity.Screen) {
+ Minecraft.getInstance.pushGuiLayer(new gui.Screen(screen.origin.buffer, screen.tier > 0, () => screen.origin.hasKeyboard, () => screen.origin.buffer.isRenderingEnabled))
+ }
+
+ override def stepOn(world: World, pos: BlockPos, entity: Entity): Unit =
+ if (!world.isClientSide) world.getBlockEntity(pos) match {
+ case screen: tileentity.Screen if screen.tier > 0 && screen.facing == Direction.UP => screen.walk(entity)
+ case _ => super.stepOn(world, pos, entity)
}
- override def onEntityCollidedWithBlock(world: World, pos: BlockPos, state: IBlockState, entity: Entity): Unit =
- if (world.isRemote) (entity, world.getTileEntity(pos)) match {
- case (arrow: EntityArrow, screen: tileentity.Screen) if screen.tier > 0 =>
- val hitX = math.max(0, math.min(1, arrow.posX - pos.getX))
- val hitY = math.max(0, math.min(1, arrow.posY - pos.getY))
- val hitZ = math.max(0, math.min(1, arrow.posZ - pos.getZ))
+ override def entityInside(state: BlockState, world: World, pos: BlockPos, entity: Entity): Unit =
+ if (world.isClientSide) (entity, world.getBlockEntity(pos)) match {
+ case (arrow: ArrowEntity, screen: tileentity.Screen) if screen.tier > 0 =>
+ val hitX = math.max(0, math.min(1, arrow.getX - pos.getX))
+ val hitY = math.max(0, math.min(1, arrow.getY - pos.getY))
+ val hitZ = math.max(0, math.min(1, arrow.getZ - pos.getZ))
val absX = math.abs(hitX - 0.5)
val absY = math.abs(hitY - 0.5)
val absZ = math.abs(hitZ - 0.5)
val side = if (absX > absY && absX > absZ) {
- if (hitX < 0.5) EnumFacing.WEST
- else EnumFacing.EAST
+ if (hitX < 0.5) Direction.WEST
+ else Direction.EAST
}
else if (absY > absZ) {
- if (hitY < 0.5) EnumFacing.DOWN
- else EnumFacing.UP
+ if (hitY < 0.5) Direction.DOWN
+ else Direction.UP
}
else {
- if (hitZ < 0.5) EnumFacing.NORTH
- else EnumFacing.SOUTH
+ if (hitZ < 0.5) Direction.NORTH
+ else Direction.SOUTH
}
if (side == screen.facing) {
screen.shot(arrow)
@@ -133,21 +125,12 @@ class Screen(val tier: Int) extends RedstoneAware {
// ----------------------------------------------------------------------- //
override def getValidRotations(world: World, pos: BlockPos) =
- world.getTileEntity(pos) match {
+ world.getBlockEntity(pos) match {
case screen: tileentity.Screen =>
- if (screen.facing == EnumFacing.UP || screen.facing == EnumFacing.DOWN) EnumFacing.values
- else EnumFacing.values.filter {
+ if (screen.facing == Direction.UP || screen.facing == Direction.DOWN) Direction.values
+ else Direction.values.filter {
d => d != screen.facing && d != screen.facing.getOpposite
}
case _ => super.getValidRotations(world, pos)
}
-
- val emptyBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0)
-
- @SideOnly(Side.CLIENT)
- override def getSelectedBoundingBox(state: IBlockState, worldIn: World, pos: BlockPos): AxisAlignedBB =
- if (!Minecraft.getMinecraft.player.isSneaking)
- emptyBB
- else
- super.getSelectedBoundingBox(state, worldIn, pos)
}
diff --git a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala
index d187e662a7..21578aa098 100644
--- a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala
+++ b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala
@@ -7,108 +7,106 @@ import li.cil.oc.common.tileentity
import li.cil.oc.common.tileentity.traits.Colored
import li.cil.oc.common.tileentity.traits.Inventory
import li.cil.oc.common.tileentity.traits.Rotatable
+import li.cil.oc.server.loot.LootFunctions
import li.cil.oc.util.Color
+import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.Tooltip
-import net.minecraft.block.BlockContainer
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
+import net.minecraft.block.BlockRenderType
+import net.minecraft.block.ContainerBlock
import net.minecraft.block.material.Material
-import net.minecraft.block.state.BlockFaceShape
-import net.minecraft.block.state.IBlockState
import net.minecraft.client.util.ITooltipFlag
import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLiving.SpawnPlacementType
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumDyeColor
-import net.minecraft.item.EnumRarity
+import net.minecraft.entity.EntityType
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.DyeColor
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
+import net.minecraft.loot.LootContext
+import net.minecraft.loot.LootParameters
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util._
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.math.BlockRayTraceResult
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
+import net.minecraft.world.IWorldReader
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.common.ToolType
-abstract class SimpleBlock(material: Material = Material.IRON) extends BlockContainer(material) {
- setHardness(2f)
- setResistance(5)
- setCreativeTab(CreativeTab)
+import scala.collection.convert.ImplicitConversionsToScala._
- var showInItemList = true
+abstract class SimpleBlock(props: Properties) extends ContainerBlock(props) {
+ @Deprecated
+ private var unlocalizedName = super.getDescriptionId()
- protected val validRotations_ = Array(EnumFacing.UP, EnumFacing.DOWN)
+ @Deprecated
+ private[oc] def setUnlocalizedName(name: String): Unit = unlocalizedName = "tile." + name
- def createItemStack(amount: Int = 1) = new ItemStack(this, amount)
+ @Deprecated
+ override def getDescriptionId = unlocalizedName
- override def createNewTileEntity(world: World, meta: Int): TileEntity = null
-
- @SideOnly(Side.CLIENT)
- override def shouldSideBeRendered(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = {
- val bounds = getBoundingBox(state, world, pos)
- (side == EnumFacing.DOWN && bounds.minY > 0) ||
- (side == EnumFacing.UP && bounds.maxY < 1) ||
- (side == EnumFacing.NORTH && bounds.minZ > 0) ||
- (side == EnumFacing.SOUTH && bounds.maxZ < 1) ||
- (side == EnumFacing.WEST && bounds.minX > 0) ||
- (side == EnumFacing.EAST && bounds.maxX < 1) ||
- isOpaqueCube(state)
- }
+ protected val validRotations_ = Array(Direction.UP, Direction.DOWN)
- // ----------------------------------------------------------------------- //
- // Rendering
- // ----------------------------------------------------------------------- //
+ def createItemStack(amount: Int = 1) = new ItemStack(this, amount)
- override def getRenderType(state: IBlockState): EnumBlockRenderType = EnumBlockRenderType.MODEL
+ override def newBlockEntity(world: IBlockReader): TileEntity = null
- @SideOnly(Side.CLIENT)
- def preItemRender(metadata: Int) {}
+ override def getRenderShape(state: BlockState): BlockRenderType = BlockRenderType.MODEL
// ----------------------------------------------------------------------- //
- // ItemBlock
+ // BlockItem
// ----------------------------------------------------------------------- //
- def rarity(stack: ItemStack) = EnumRarity.COMMON
-
- @SideOnly(Side.CLIENT)
- def addInformation(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- tooltipHead(metadata, stack, world, tooltip, flag)
- tooltipBody(metadata, stack, world, tooltip, flag)
- tooltipTail(metadata, stack, world, tooltip, flag)
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ tooltipHead(stack, world, tooltip, flag)
+ tooltipBody(stack, world, tooltip, flag)
+ tooltipTail(stack, world, tooltip, flag)
}
- protected def tooltipHead(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
+ protected def tooltipHead(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
}
- protected def tooltipBody(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase))
+ protected def tooltipBody(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ for (curr <- Tooltip.get(getClass.getSimpleName.toLowerCase)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
- protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
+ protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
}
// ----------------------------------------------------------------------- //
// Rotation
// ----------------------------------------------------------------------- //
- def getFacing(world: IBlockAccess, pos: BlockPos): EnumFacing =
- world.getTileEntity(pos) match {
+ def getFacing(world: IBlockReader, pos: BlockPos): Direction =
+ world.getBlockEntity(pos) match {
case tileEntity: Rotatable => tileEntity.facing
- case _ => EnumFacing.SOUTH
+ case _ => Direction.SOUTH
}
- def setFacing(world: World, pos: BlockPos, value: EnumFacing): Boolean =
- world.getTileEntity(pos) match {
+ def setFacing(world: World, pos: BlockPos, value: Direction): Boolean =
+ world.getBlockEntity(pos) match {
case rotatable: Rotatable => rotatable.setFromFacing(value); true
case _ => false
}
def setRotationFromEntityPitchAndYaw(world: World, pos: BlockPos, value: Entity): Boolean =
- world.getTileEntity(pos) match {
+ world.getBlockEntity(pos) match {
case rotatable: Rotatable => rotatable.setFromEntityPitchAndYaw(value); true
case _ => false
}
- def toLocal(world: IBlockAccess, pos: BlockPos, value: EnumFacing): EnumFacing =
- world.getTileEntity(pos) match {
+ def toLocal(world: IBlockReader, pos: BlockPos, value: Direction): Direction =
+ world.getBlockEntity(pos) match {
case rotatable: Rotatable => rotatable.toLocal(value)
case _ => value
}
@@ -117,64 +115,69 @@ abstract class SimpleBlock(material: Material = Material.IRON) extends BlockCont
// Block
// ----------------------------------------------------------------------- //
- override def getBlockFaceShape(world: IBlockAccess, state: IBlockState, pos: BlockPos, side: EnumFacing): BlockFaceShape = if(isBlockSolid(world, pos, side)) BlockFaceShape.SOLID else BlockFaceShape.UNDEFINED
-
- def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = world.getBlockState(pos).getMaterial.isSolid
+ override def canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: PlayerEntity) = true
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = true
+ override def getHarvestTool(state: BlockState): ToolType = null
- override def canHarvestBlock(world: IBlockAccess, pos: BlockPos, player: EntityPlayer) = true
+ override def canBeReplacedByLeaves(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean = false
- override def getHarvestTool(state: IBlockState): String = null
+ def getValidRotations(world: World, pos: BlockPos): Array[Direction] = validRotations_
- override def canBeReplacedByLeaves(state: IBlockState, world: IBlockAccess, pos: BlockPos): Boolean = false
-
- override def canCreatureSpawn(state: IBlockState, world: IBlockAccess, pos: BlockPos, `type`: SpawnPlacementType): Boolean = false
-
- override def getValidRotations(world: World, pos: BlockPos): Array[EnumFacing] = validRotations_
+ override def getDrops(state: BlockState, ctx: LootContext.Builder): util.List[ItemStack] = {
+ val newCtx = ctx.getOptionalParameter(LootParameters.BLOCK_ENTITY) match {
+ case _: Inventory => ctx.withDynamicDrop(LootFunctions.DYN_VOLATILE_CONTENTS, (c, f) => {
+ c.getParamOrNull(LootParameters.BLOCK_ENTITY) match {
+ case inventory: Inventory => inventory.forAllLoot(f)
+ case _ =>
+ }
+ })
+ case _ => ctx
+ }
+ super.getDrops(state, newCtx)
+ }
- override def breakBlock(world: World, pos: BlockPos, state: IBlockState): Unit = {
- if (!world.isRemote) world.getTileEntity(pos) match {
+ override def playerWillDestroy(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
+ if (!world.isClientSide && player.isCreative) world.getBlockEntity(pos) match {
case inventory: Inventory => inventory.dropAllSlots()
case _ => // Ignore.
}
- super.breakBlock(world, pos, state)
+ super.playerWillDestroy(world, pos, state, player)
}
// ----------------------------------------------------------------------- //
- override def rotateBlock(world: World, pos: BlockPos, axis: EnumFacing): Boolean =
- world.getTileEntity(pos) match {
+ @Deprecated
+ def rotateBlock(world: World, pos: BlockPos, axis: Direction): Boolean =
+ world.getBlockEntity(pos) match {
case rotatable: tileentity.traits.Rotatable if rotatable.rotate(axis) =>
- world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3)
+ world.sendBlockUpdated(pos, world.getBlockState(pos), world.getBlockState(pos), 3)
true
case _ => false
}
- override def recolorBlock(world: World, pos: BlockPos, side: EnumFacing, color: EnumDyeColor): Boolean =
- world.getTileEntity(pos) match {
- case colored: Colored if colored.getColor != Color.rgbValues(color) =>
- colored.setColor(Color.rgbValues(color))
- world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3)
- true // Blame Vexatos.
- case _ => super.recolorBlock(world, pos, side, color)
- }
-
// ----------------------------------------------------------------------- //
- override def onBlockActivated(world: World, pos: BlockPos, state: IBlockState, player: EntityPlayer, hand: EnumHand, facing: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- val heldItem = player.getHeldItem(hand)
- world.getTileEntity(pos) match {
+ override def use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, trace: BlockRayTraceResult): ActionResultType = {
+ val heldItem = player.getItemInHand(hand)
+ world.getBlockEntity(pos) match {
case colored: Colored if Color.isDye(heldItem) =>
colored.setColor(Color.rgbValues(Color.dyeColor(heldItem)))
- world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3)
- if (!player.capabilities.isCreativeMode && colored.consumesDye) {
- heldItem.splitStack(1)
+ world.sendBlockUpdated(pos, world.getBlockState(pos), world.getBlockState(pos), 3)
+ if (!player.isCreative && colored.consumesDye) {
+ heldItem.split(1)
}
- true
- case _ => localOnBlockActivated(world, pos, player, hand, heldItem, facing, hitX, hitY, hitZ)
+ ActionResultType.sidedSuccess(world.isClientSide)
+ case _ => {
+ val loc = trace.getLocation
+ val pos = trace.getBlockPos
+ val x = loc.x.toFloat - pos.getX
+ val y = loc.y.toFloat - pos.getY
+ val z = loc.z.toFloat - pos.getZ
+ if (localOnBlockActivated(world, pos, player, hand, heldItem, trace.getDirection, x, y, z))
+ ActionResultType.sidedSuccess(world.isClientSide) else ActionResultType.PASS
+ }
}
}
- def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = false
+ def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = false
}
diff --git a/src/main/scala/li/cil/oc/common/block/Transposer.scala b/src/main/scala/li/cil/oc/common/block/Transposer.scala
index 78f01d35e3..a54d894fb6 100644
--- a/src/main/scala/li/cil/oc/common/block/Transposer.scala
+++ b/src/main/scala/li/cil/oc/common/block/Transposer.scala
@@ -1,16 +1,13 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.IBlockState
-import net.minecraft.util.EnumFacing
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.BlockState
+import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.world.IBlockReader
import net.minecraft.world.World
-class Transposer extends SimpleBlock {
- override def isSideSolid(state: IBlockState, world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = false
-
- // ----------------------------------------------------------------------- //
-
- override def createNewTileEntity(world: World, meta: Int) = new tileentity.Transposer()
+class Transposer(props: Properties) extends SimpleBlock(props) {
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Transposer(tileentity.TileEntityTypes.TRANSPOSER)
}
diff --git a/src/main/scala/li/cil/oc/common/block/Waypoint.scala b/src/main/scala/li/cil/oc/common/block/Waypoint.scala
index 8f6cbc5bab..294d2b0232 100644
--- a/src/main/scala/li/cil/oc/common/block/Waypoint.scala
+++ b/src/main/scala/li/cil/oc/common/block/Waypoint.scala
@@ -1,56 +1,54 @@
package li.cil.oc.common.block
import li.cil.oc.OpenComputers
-import li.cil.oc.common.GuiType
-import li.cil.oc.common.block.property.{PropertyRotatable, PropertyTile}
+import li.cil.oc.client.gui
+import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.common.tileentity
-import net.minecraft.block.state.BlockStateContainer
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import li.cil.oc.util.RotationHelper
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.Block
+import net.minecraft.block.BlockState
+import net.minecraft.client.Minecraft
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.state.StateContainer
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.{IBlockAccess, World}
-import net.minecraftforge.common.property.{ExtendedBlockState, IExtendedBlockState}
+import net.minecraft.util.math.BlockRayTraceResult
+import net.minecraft.world.{IBlockReader, World}
+import net.minecraftforge.api.distmarker.{Dist, OnlyIn}
-class Waypoint extends RedstoneAware {
- override def createBlockState() = new ExtendedBlockState(this, Array(PropertyRotatable.Pitch, PropertyRotatable.Yaw), Array(PropertyTile.Tile))
-
- override def getMetaFromState(state: IBlockState): Int = (state.getValue(PropertyRotatable.Pitch).ordinal() << 2) | state.getValue(PropertyRotatable.Yaw).getHorizontalIndex
-
- override def getStateFromMeta(meta: Int): IBlockState = getDefaultState.withProperty(PropertyRotatable.Pitch, EnumFacing.getFront(meta >> 2)).withProperty(PropertyRotatable.Yaw, EnumFacing.getHorizontal(meta & 0x3))
-
- override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos): IBlockState =
- (state, world.getTileEntity(pos)) match {
- case (extendedState: IExtendedBlockState, tile: tileentity.Screen) =>
- extendedState.
- withProperty(property.PropertyTile.Tile, tile).
- withProperty(PropertyRotatable.Pitch, tile.pitch).
- withProperty(PropertyRotatable.Yaw, tile.yaw)
- case _ => state
- }
+class Waypoint(props: Properties) extends RedstoneAware(props) {
+ protected override def createBlockStateDefinition(builder: StateContainer.Builder[Block, BlockState]) =
+ builder.add(PropertyRotatable.Pitch, PropertyRotatable.Yaw)
// ----------------------------------------------------------------------- //
- override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Waypoint()
+ override def newBlockEntity(world: IBlockReader) = new tileentity.Waypoint(tileentity.TileEntityTypes.WAYPOINT)
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- if (!player.isSneaking) {
- if (world.isRemote) {
- player.openGui(OpenComputers, GuiType.Waypoint.id, world, pos.getX, pos.getY, pos.getZ)
+ override def use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, trace: BlockRayTraceResult): ActionResultType = {
+ if (!player.isCrouching) {
+ if (world.isClientSide) world.getBlockEntity(pos) match {
+ case t: tileentity.Waypoint => showGui(t)
+ case _ =>
}
- true
+ ActionResultType.sidedSuccess(world.isClientSide)
}
- else super.localOnBlockActivated(world, pos, player, hand, heldItem, side, hitX, hitY, hitZ)
+ else super.use(state, world, pos, player, hand, trace)
+ }
+
+ @OnlyIn(Dist.CLIENT)
+ private def showGui(t: tileentity.Waypoint) {
+ Minecraft.getInstance.pushGuiLayer(new gui.Waypoint(t))
}
- override def getValidRotations(world: World, pos: BlockPos): Array[EnumFacing] =
- world.getTileEntity(pos) match {
+ override def getValidRotations(world: World, pos: BlockPos): Array[Direction] =
+ world.getBlockEntity(pos) match {
case waypoint: tileentity.Waypoint =>
- EnumFacing.values.filter {
+ Direction.values.filter {
d => d != waypoint.facing && d != waypoint.facing.getOpposite
}
case _ => super.getValidRotations(world, pos)
diff --git a/src/main/scala/li/cil/oc/common/block/property/PropertyCableConnection.java b/src/main/scala/li/cil/oc/common/block/property/PropertyCableConnection.java
new file mode 100644
index 0000000000..ce5917c306
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/block/property/PropertyCableConnection.java
@@ -0,0 +1,54 @@
+package li.cil.oc.common.block.property;
+
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
+
+import net.minecraft.state.EnumProperty;
+import net.minecraft.util.Direction;
+import net.minecraft.util.IStringSerializable;
+
+public final class PropertyCableConnection {
+ public static enum Shape implements IStringSerializable {
+ NONE("none"),
+ CABLE("cable"),
+ DEVICE("device");
+
+ private final String name;
+
+ private Shape(String name) {
+ this.name = name;
+ }
+
+ public String getSerializedName() {
+ return name;
+ }
+
+ public String toString() {
+ return name;
+ }
+ }
+
+ public static final EnumProperty DOWN = EnumProperty.create("conn_down", Shape.class);
+ public static final EnumProperty UP = EnumProperty.create("conn_up", Shape.class);
+ public static final EnumProperty NORTH = EnumProperty.create("conn_north", Shape.class);
+ public static final EnumProperty SOUTH = EnumProperty.create("conn_south", Shape.class);
+ public static final EnumProperty WEST = EnumProperty.create("conn_west", Shape.class);
+ public static final EnumProperty EAST = EnumProperty.create("conn_east", Shape.class);
+ public static Map> BY_DIRECTION;
+
+ static
+ {
+ EnumMap> byDir = new EnumMap<>(Direction.class);
+ byDir.put(Direction.DOWN, DOWN);
+ byDir.put(Direction.UP, UP);
+ byDir.put(Direction.NORTH, NORTH);
+ byDir.put(Direction.SOUTH, SOUTH);
+ byDir.put(Direction.WEST, WEST);
+ byDir.put(Direction.EAST, EAST);
+ BY_DIRECTION = Collections.unmodifiableMap(byDir);
+ }
+
+ private PropertyCableConnection() {
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/block/property/PropertyRotatable.scala b/src/main/scala/li/cil/oc/common/block/property/PropertyRotatable.scala
index 930e337e46..569ee9c44d 100644
--- a/src/main/scala/li/cil/oc/common/block/property/PropertyRotatable.scala
+++ b/src/main/scala/li/cil/oc/common/block/property/PropertyRotatable.scala
@@ -1,14 +1,14 @@
package li.cil.oc.common.block.property
-import com.google.common.base.Predicate
-import com.google.common.base.Predicates
-import net.minecraft.block.properties.PropertyDirection
-import net.minecraft.util.EnumFacing
+import java.util.function.Predicate
-import scala.collection.convert.WrapAsJava._
+import net.minecraft.state.DirectionProperty
+import net.minecraft.util.Direction
+
+import scala.collection.convert.ImplicitConversionsToJava._
object PropertyRotatable {
- final val Facing = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL.asInstanceOf[Predicate[EnumFacing]])
- final val Pitch = PropertyDirection.create("pitch", Predicates.in(Set(EnumFacing.DOWN, EnumFacing.UP, EnumFacing.NORTH)))
- final val Yaw = PropertyDirection.create("yaw", EnumFacing.Plane.HORIZONTAL.asInstanceOf[Predicate[EnumFacing]])
+ final val Facing = DirectionProperty.create("facing", Direction.Plane.HORIZONTAL)
+ final val Pitch = DirectionProperty.create("pitch", d => d.getAxis == Direction.Axis.Y || d == Direction.NORTH)
+ final val Yaw = DirectionProperty.create("yaw", Direction.Plane.HORIZONTAL)
}
diff --git a/src/main/scala/li/cil/oc/common/block/property/PropertyRunning.scala b/src/main/scala/li/cil/oc/common/block/property/PropertyRunning.scala
index f9ad0a7d2e..7aa3d7622f 100644
--- a/src/main/scala/li/cil/oc/common/block/property/PropertyRunning.scala
+++ b/src/main/scala/li/cil/oc/common/block/property/PropertyRunning.scala
@@ -1,7 +1,7 @@
package li.cil.oc.common.block.property
-import net.minecraft.block.properties.PropertyBool
+import net.minecraft.state.BooleanProperty
object PropertyRunning {
- final val Running = PropertyBool.create("running")
+ final val Running = BooleanProperty.create("running")
}
diff --git a/src/main/scala/li/cil/oc/common/block/property/PropertyTile.scala b/src/main/scala/li/cil/oc/common/block/property/PropertyTile.scala
deleted file mode 100644
index c28a8cd095..0000000000
--- a/src/main/scala/li/cil/oc/common/block/property/PropertyTile.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package li.cil.oc.common.block.property
-
-import net.minecraft.tileentity.TileEntity
-import net.minecraftforge.common.property.IUnlistedProperty
-
-object PropertyTile {
- final val Tile = new PropertyTile()
-}
-
-// Custom unlisted property used to pass a long tile entities to a block's renderer.
-class PropertyTile extends IUnlistedProperty[TileEntity] {
- override def getName = "tile"
-
- override def isValid(value: TileEntity) = true
-
- override def getType = classOf[TileEntity]
-
- override def valueToString(value: TileEntity) = value.toString
-}
diff --git a/src/main/scala/li/cil/oc/common/block/property/UnlistedInteger.scala b/src/main/scala/li/cil/oc/common/block/property/UnlistedInteger.scala
deleted file mode 100644
index ed833c2ce4..0000000000
--- a/src/main/scala/li/cil/oc/common/block/property/UnlistedInteger.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package li.cil.oc.common.block.property
-
-import net.minecraftforge.common.property.IUnlistedProperty
-
-class UnlistedInteger(val name:String) extends IUnlistedProperty[Integer]{
- override def getName: String = name
-
- override def isValid(value: Integer): Boolean = value != null
-
- override def getType: Class[Integer] = classOf[Integer]
-
- override def valueToString(value: Integer): String = value.toString
-}
diff --git a/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala
deleted file mode 100644
index f201ba1931..0000000000
--- a/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package li.cil.oc.common.block.traits
-
-import java.util
-
-import li.cil.oc.common.block.SimpleBlock
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.ItemStack
-import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
-import net.minecraft.world.World
-
-import scala.reflect.ClassTag
-
-trait CustomDrops[Tile <: TileEntity] extends SimpleBlock {
- protected def tileTag: ClassTag[Tile]
-
- override def getDrops(world: IBlockAccess, pos: BlockPos, state: IBlockState, fortune: Int): util.List[ItemStack] = new java.util.ArrayList[ItemStack]()
-
- override def breakBlock(world: World, pos: BlockPos, state: IBlockState): Unit = {}
-
- override def removedByPlayer(state: IBlockState, world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean): Boolean = {
- if (!world.isRemote) {
- val matcher = tileTag
- world.getTileEntity(pos) match {
- case matcher(tileEntity) => doCustomDrops(tileEntity, player, willHarvest)
- case _ =>
- }
- }
- super.removedByPlayer(state, world, pos, player, willHarvest)
- }
-
- override def onBlockPlacedBy(world: World, pos: BlockPos, state: IBlockState, placer: EntityLivingBase, stack: ItemStack): Unit = {
- super.onBlockPlacedBy(world, pos, state, placer, stack)
- val matcher = tileTag
- world.getTileEntity(pos) match {
- case matcher(tileEntity) => doCustomInit(tileEntity, placer, stack)
- case _ =>
- }
- }
-
- protected def doCustomInit(tileEntity: Tile, player: EntityLivingBase, stack: ItemStack): Unit = {}
-
- protected def doCustomDrops(tileEntity: Tile, player: EntityPlayer, willHarvest: Boolean): Unit = {}
-}
diff --git a/src/main/scala/li/cil/oc/common/block/traits/GUI.scala b/src/main/scala/li/cil/oc/common/block/traits/GUI.scala
index ac895350ab..e50324764e 100644
--- a/src/main/scala/li/cil/oc/common/block/traits/GUI.scala
+++ b/src/main/scala/li/cil/oc/common/block/traits/GUI.scala
@@ -1,22 +1,28 @@
package li.cil.oc.common.block.traits
import li.cil.oc.OpenComputers
-import li.cil.oc.common.GuiType
import li.cil.oc.common.block.SimpleBlock
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
trait GUI extends SimpleBlock {
- def guiType: GuiType.EnumVal
+ def openGui(player: ServerPlayerEntity, world: World, pos: BlockPos)
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, guiType.id, world, pos.getX, pos.getY, pos.getZ)
+ // This gets forwarded to the vanilla PlayerEntity.openMenu call which doesn't support extra data.
+ override def getMenuProvider(state: BlockState, world: World, pos: BlockPos): INamedContainerProvider = null
+
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, heldItem: ItemStack, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ if (!player.isCrouching) {
+ player match {
+ case srvPlr: ServerPlayerEntity if !world.isClientSide => openGui(srvPlr, world, pos)
+ case _ =>
}
true
}
diff --git a/src/main/scala/li/cil/oc/common/block/traits/PowerAcceptor.scala b/src/main/scala/li/cil/oc/common/block/traits/PowerAcceptor.scala
index a2ba010bf5..94180143d1 100644
--- a/src/main/scala/li/cil/oc/common/block/traits/PowerAcceptor.scala
+++ b/src/main/scala/li/cil/oc/common/block/traits/PowerAcceptor.scala
@@ -5,17 +5,23 @@ import java.util
import li.cil.oc.common.block.SimpleBlock
import li.cil.oc.util.Tooltip
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.world.World
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IBlockReader
+
+import scala.collection.convert.ImplicitConversionsToScala._
trait PowerAcceptor extends SimpleBlock {
def energyThroughput: Double
// ----------------------------------------------------------------------- //
- override protected def tooltipTail(metadata: Int, stack: ItemStack, world: World, tooltip: util.List[String], advanced: ITooltipFlag) {
- super.tooltipTail(metadata, stack, world, tooltip, advanced)
- tooltip.addAll(Tooltip.extended("PowerAcceptor", energyThroughput.toInt))
+ override protected def tooltipTail(stack: ItemStack, world: IBlockReader, tooltip: util.List[ITextComponent], advanced: ITooltipFlag) {
+ super.tooltipTail(stack, world, tooltip, advanced)
+ for (curr <- Tooltip.extended("poweracceptor", energyThroughput.toInt)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/traits/StateAware.scala b/src/main/scala/li/cil/oc/common/block/traits/StateAware.scala
index a406f8760e..3ad68b5148 100644
--- a/src/main/scala/li/cil/oc/common/block/traits/StateAware.scala
+++ b/src/main/scala/li/cil/oc/common/block/traits/StateAware.scala
@@ -2,15 +2,15 @@ package li.cil.oc.common.block.traits
import li.cil.oc.api
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
trait StateAware extends Block {
- override def hasComparatorInputOverride(state: IBlockState): Boolean = true
+ override def hasAnalogOutputSignal(state: BlockState): Boolean = true
- override def getComparatorInputOverride(state: IBlockState, world: World, pos: BlockPos): Int =
- world.getTileEntity(pos) match {
+ override def getAnalogOutputSignal(state: BlockState, world: World, pos: BlockPos): Int =
+ world.getBlockEntity(pos) match {
case stateful: api.util.StateAware =>
if (stateful.getCurrentState.contains(api.util.StateAware.State.IsWorking)) 15
else if (stateful.getCurrentState.contains(api.util.StateAware.State.CanWork)) 10
diff --git a/src/main/scala/li/cil/oc/common/capabilities/CapabilityColored.scala b/src/main/scala/li/cil/oc/common/capabilities/CapabilityColored.scala
index b186caa6c3..f133a1a781 100644
--- a/src/main/scala/li/cil/oc/common/capabilities/CapabilityColored.scala
+++ b/src/main/scala/li/cil/oc/common/capabilities/CapabilityColored.scala
@@ -2,25 +2,29 @@ package li.cil.oc.common.capabilities
import li.cil.oc.api.internal.Colored
import li.cil.oc.integration.Mods
-import net.minecraft.nbt.NBTBase
-import net.minecraft.nbt.NBTTagInt
+import net.minecraft.nbt.INBT
+import net.minecraft.nbt.IntNBT
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
object CapabilityColored {
final val ProviderColored = new ResourceLocation(Mods.IDs.OpenComputers, "colored")
- class Provider(val tileEntity: TileEntity with Colored) extends ICapabilityProvider with Colored {
- override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
- capability == Capabilities.ColoredCapability
- }
+ class Provider(val tileEntity: TileEntity with Colored) extends ICapabilityProvider with NonNullSupplier[Provider] with Colored {
+ private val wrapper = LazyOptional.of(this)
+
+ def get = this
+
+ def invalidate() = wrapper.invalidate
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
- if (hasCapability(capability, facing)) this.asInstanceOf[T]
- else null.asInstanceOf[T]
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
+ if (capability == Capabilities.ColoredCapability) wrapper.cast[T]
+ else LazyOptional.empty[T]
}
override def getColor = tileEntity.getColor
@@ -41,15 +45,15 @@ object CapabilityColored {
}
class DefaultStorage extends Capability.IStorage[Colored] {
- override def writeNBT(capability: Capability[Colored], t: Colored, enumFacing: EnumFacing): NBTBase = {
+ override def writeNBT(capability: Capability[Colored], t: Colored, Direction: Direction): INBT = {
val color = t.getColor
- new NBTTagInt(color)
+ IntNBT.valueOf(color)
}
- override def readNBT(capability: Capability[Colored], t: Colored, enumFacing: EnumFacing, nbtBase: NBTBase): Unit = {
+ override def readNBT(capability: Capability[Colored], t: Colored, Direction: Direction, nbtBase: INBT): Unit = {
nbtBase match {
- case nbt: NBTTagInt =>
- t.setColor(nbt.getInt)
+ case nbt: IntNBT =>
+ t.setColor(nbt.getAsInt)
case _ =>
}
}
diff --git a/src/main/scala/li/cil/oc/common/capabilities/CapabilityEnvironment.scala b/src/main/scala/li/cil/oc/common/capabilities/CapabilityEnvironment.scala
index fe5ee5992b..19b321ef0f 100644
--- a/src/main/scala/li/cil/oc/common/capabilities/CapabilityEnvironment.scala
+++ b/src/main/scala/li/cil/oc/common/capabilities/CapabilityEnvironment.scala
@@ -6,25 +6,29 @@ import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.integration.Mods
-import net.minecraft.nbt.NBTBase
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.INBT
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
object CapabilityEnvironment {
final val ProviderEnvironment = new ResourceLocation(Mods.IDs.OpenComputers, "environment")
- class Provider(val tileEntity: TileEntity with Environment) extends ICapabilityProvider with Environment {
- override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
- capability == Capabilities.EnvironmentCapability
- }
+ class Provider(val tileEntity: TileEntity with Environment) extends ICapabilityProvider with NonNullSupplier[Provider] with Environment {
+ private val wrapper = LazyOptional.of(this)
+
+ def get = this
+
+ def invalidate() = wrapper.invalidate
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
- if (hasCapability(capability, facing)) this.asInstanceOf[T]
- else null.asInstanceOf[T]
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
+ if (capability == Capabilities.EnvironmentCapability) wrapper.cast[T]
+ else LazyOptional.empty[T]
}
override def node = tileEntity.node
@@ -47,21 +51,21 @@ object CapabilityEnvironment {
}
class DefaultStorage extends Capability.IStorage[Environment] {
- override def writeNBT(capability: Capability[Environment], t: Environment, facing: EnumFacing): NBTBase = {
+ override def writeNBT(capability: Capability[Environment], t: Environment, facing: Direction): INBT = {
val node = t.node
if (node != null) {
- val nbt = new NBTTagCompound()
- node.save(nbt)
+ val nbt = new CompoundNBT()
+ node.saveData(nbt)
nbt
}
else null
}
- override def readNBT(capability: Capability[Environment], t: Environment, facing: EnumFacing, nbtBase: NBTBase): Unit = {
+ override def readNBT(capability: Capability[Environment], t: Environment, facing: Direction, nbtBase: INBT): Unit = {
nbtBase match {
- case nbt: NBTTagCompound =>
+ case nbt: CompoundNBT =>
val node = t.node
- if (node != null) node.load(nbt)
+ if (node != null) node.loadData(nbt)
case _ =>
}
}
diff --git a/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedComponent.scala b/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedComponent.scala
index aecb4b2e39..c0fafb4485 100644
--- a/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedComponent.scala
+++ b/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedComponent.scala
@@ -5,27 +5,31 @@ import li.cil.oc.api.network.SidedComponent
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.integration.Mods
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
object CapabilitySidedComponent {
final val SidedComponent = new ResourceLocation(Mods.IDs.OpenComputers, "sided_component")
- class Provider(val tileEntity: TileEntity with Environment with SidedComponent) extends ICapabilityProvider with SidedEnvironment {
- override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
- capability == Capabilities.SidedEnvironmentCapability
- }
+ class Provider(val tileEntity: TileEntity with Environment with SidedComponent) extends ICapabilityProvider with NonNullSupplier[Provider] with SidedEnvironment {
+ private val wrapper = LazyOptional.of(this)
+
+ def get = this
+
+ def invalidate() = wrapper.invalidate
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
- if (hasCapability(capability, facing)) this.asInstanceOf[T]
- else null.asInstanceOf[T]
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
+ if (capability == Capabilities.SidedEnvironmentCapability) wrapper.cast[T]
+ else LazyOptional.empty[T]
}
- override def sidedNode(side: EnumFacing) = if (tileEntity.canConnectNode(side)) tileEntity.node else null
+ override def sidedNode(side: Direction) = if (tileEntity.canConnectNode(side)) tileEntity.node else null
- override def canConnect(side: EnumFacing) = tileEntity.canConnectNode(side)
+ override def canConnect(side: Direction) = tileEntity.canConnectNode(side)
}
}
diff --git a/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedEnvironment.scala b/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedEnvironment.scala
index f2e619135c..4f42147374 100644
--- a/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedEnvironment.scala
+++ b/src/main/scala/li/cil/oc/common/capabilities/CapabilitySidedEnvironment.scala
@@ -3,41 +3,45 @@ package li.cil.oc.common.capabilities
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.integration.Mods
-import net.minecraft.nbt.NBTBase
+import net.minecraft.nbt.INBT
import net.minecraft.tileentity.TileEntity
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
object CapabilitySidedEnvironment {
final val ProviderSidedEnvironment = new ResourceLocation(Mods.IDs.OpenComputers, "sided_environment")
- class Provider(val tileEntity: TileEntity with SidedEnvironment) extends ICapabilityProvider with SidedEnvironment {
- override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
- capability == Capabilities.SidedEnvironmentCapability
- }
+ class Provider(val tileEntity: TileEntity with SidedEnvironment) extends ICapabilityProvider with NonNullSupplier[Provider] with SidedEnvironment {
+ private val wrapper = LazyOptional.of(this)
+
+ def get = this
+
+ def invalidate() = wrapper.invalidate
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
- if (hasCapability(capability, facing)) this.asInstanceOf[T]
- else null.asInstanceOf[T]
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
+ if (capability == Capabilities.SidedEnvironmentCapability) wrapper.cast[T]
+ else LazyOptional.empty[T]
}
- override def sidedNode(side: EnumFacing) = tileEntity.sidedNode(side)
+ override def sidedNode(side: Direction) = tileEntity.sidedNode(side)
- override def canConnect(side: EnumFacing) = tileEntity.canConnect(side)
+ override def canConnect(side: Direction) = tileEntity.canConnect(side)
}
class DefaultImpl extends SidedEnvironment {
- override def sidedNode(side: EnumFacing): Node = null
+ override def sidedNode(side: Direction): Node = null
- override def canConnect(side: EnumFacing): Boolean = false
+ override def canConnect(side: Direction): Boolean = false
}
class DefaultStorage extends Capability.IStorage[SidedEnvironment] {
- override def writeNBT(capability: Capability[SidedEnvironment], t: SidedEnvironment, enumFacing: EnumFacing): NBTBase = null
+ override def writeNBT(capability: Capability[SidedEnvironment], t: SidedEnvironment, Direction: Direction): INBT = null
- override def readNBT(capability: Capability[SidedEnvironment], t: SidedEnvironment, enumFacing: EnumFacing, nbtBase: NBTBase): Unit = {}
+ override def readNBT(capability: Capability[SidedEnvironment], t: SidedEnvironment, Direction: Direction, nbtBase: INBT): Unit = {}
}
}
diff --git a/src/main/scala/li/cil/oc/common/command/SimpleCommand.scala b/src/main/scala/li/cil/oc/common/command/SimpleCommand.scala
deleted file mode 100644
index f36204e0de..0000000000
--- a/src/main/scala/li/cil/oc/common/command/SimpleCommand.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package li.cil.oc.common.command
-
-import java.util
-
-import net.minecraft.command.CommandBase
-import net.minecraft.command.ICommandSender
-import net.minecraft.server.MinecraftServer
-import net.minecraftforge.fml.common.FMLCommonHandler
-
-import scala.collection.convert.WrapAsJava._
-import scala.collection.mutable
-
-abstract class SimpleCommand(val name: String) extends CommandBase {
- protected var aliases = mutable.ListBuffer.empty[String]
-
- override def getName = name
-
- override def getAliases: util.List[String] = aliases
-
- override def checkPermission(server: MinecraftServer, sender: ICommandSender): Boolean = super.checkPermission(server, sender)|| (FMLCommonHandler.instance().getMinecraftServerInstance != null && FMLCommonHandler.instance().getMinecraftServerInstance.isSinglePlayer)
-
- override def isUsernameIndex(command: Array[String], i: Int) = false
-}
diff --git a/src/main/scala/li/cil/oc/common/component/GpuTextBuffer.scala b/src/main/scala/li/cil/oc/common/component/GpuTextBuffer.scala
index 2d9f8f4dfe..570686029e 100644
--- a/src/main/scala/li/cil/oc/common/component/GpuTextBuffer.scala
+++ b/src/main/scala/li/cil/oc/common/component/GpuTextBuffer.scala
@@ -3,12 +3,15 @@ package li.cil.oc.common.component
import java.io.InvalidObjectException
import java.security.InvalidParameterException
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.api.network.{Environment, Message, Node}
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
import li.cil.oc.api.internal.TextBuffer.ColorDepth
import li.cil.oc.api
import li.cil.oc.common.component.traits.{TextBufferProxy, VideoRamDevice, VideoRamRasterizer}
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
class GpuTextBuffer(val owner: String, val id: Int, val data: li.cil.oc.util.TextBuffer) extends traits.TextBufferProxy {
@@ -30,14 +33,14 @@ class GpuTextBuffer(val owner: String, val id: Int, val data: li.cil.oc.util.Tex
override def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int): Unit = dirty = true
override def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char): Unit = dirty = true
- override def load(nbt: NBTTagCompound): Unit = {
+ override def loadData(nbt: CompoundNBT): Unit = {
// the data is initially dirty because other devices don't know about it yet
- data.load(nbt)
+ data.loadData(nbt)
dirty = true
}
- override def save(nbt: NBTTagCompound): Unit = {
- data.save(nbt)
+ override def saveData(nbt: CompoundNBT): Unit = {
+ data.saveData(nbt)
dirty = false
}
@@ -52,18 +55,20 @@ class GpuTextBuffer(val owner: String, val id: Int, val data: li.cil.oc.util.Tex
override def setViewport(width: Int, height: Int): Boolean = false
override def setMaximumColorDepth(depth: ColorDepth): Unit = {}
override def getMaximumColorDepth: ColorDepth = data.format.depth
- override def renderText: Boolean = false
+ @OnlyIn(Dist.CLIENT)
+ override def renderText(stack: MatrixStack): Boolean = false
override def renderWidth: Int = 0
override def renderHeight: Int = 0
override def setRenderingEnabled(enabled: Boolean): Unit = {}
override def isRenderingEnabled: Boolean = false
- override def keyDown(character: Char, code: Int, player: EntityPlayer): Unit = {}
- override def keyUp(character: Char, code: Int, player: EntityPlayer): Unit = {}
- override def clipboard(value: String, player: EntityPlayer): Unit = {}
- override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer): Unit = {}
- override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer): Unit = {}
- override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer): Unit = {}
- override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer): Unit = {}
+ override def keyDown(character: Char, code: Int, player: PlayerEntity): Unit = {}
+ override def keyUp(character: Char, code: Int, player: PlayerEntity): Unit = {}
+ override def textInput(codePt: Int, player: PlayerEntity): Unit = {}
+ override def clipboard(value: String, player: PlayerEntity): Unit = {}
+ override def mouseDown(x: Double, y: Double, button: Int, player: PlayerEntity): Unit = {}
+ override def mouseDrag(x: Double, y: Double, button: Int, player: PlayerEntity): Unit = {}
+ override def mouseUp(x: Double, y: Double, button: Int, player: PlayerEntity): Unit = {}
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: PlayerEntity): Unit = {}
override def canUpdate: Boolean = false
override def update(): Unit = {}
override def onConnect(node: Node): Unit = {}
@@ -91,7 +96,7 @@ object ClientGpuTextBufferHandler {
}
}
- def loadBuffer(buffer: api.internal.TextBuffer, owner: String, id: Int, nbt: NBTTagCompound): Boolean = {
+ def loadBuffer(buffer: api.internal.TextBuffer, owner: String, id: Int, nbt: CompoundNBT): Boolean = {
buffer match {
case screen: VideoRamRasterizer => screen.loadBuffer(owner, id, nbt)
case _ => false // ignore, not compatible with bitblts
diff --git a/src/main/scala/li/cil/oc/common/component/TerminalServer.scala b/src/main/scala/li/cil/oc/common/component/TerminalServer.scala
index 4832c5d136..61d1db1923 100644
--- a/src/main/scala/li/cil/oc/common/component/TerminalServer.scala
+++ b/src/main/scala/li/cil/oc/common/component/TerminalServer.scala
@@ -23,18 +23,17 @@ import li.cil.oc.api.util.StateAware
import li.cil.oc.api.util.StateAware.State
import li.cil.oc.common.Tier
import li.cil.oc.common.item
-import li.cil.oc.common.item.Delegator
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.nbt.NBTTagString
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.StringNBT
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraftforge.common.util.Constants.NBT
-import scala.collection.convert.WrapAsScala._
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToScala._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environment with EnvironmentHost with Analyzable with RackMountable with Lifecycle with DeviceInfo {
@@ -53,10 +52,10 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
val keyboardItem = api.Items.get(Constants.BlockName.Keyboard).createItemStack(1)
val keyboard = api.Driver.driverFor(keyboardItem, getClass).createEnvironment(keyboardItem, this).asInstanceOf[api.internal.Keyboard]
keyboard.setUsableOverride(new UsabilityChecker {
- override def isUsableByPlayer(keyboard: api.internal.Keyboard, player: EntityPlayer) = {
- val stack = player.getHeldItemMainhand
- Delegator.subItem(stack) match {
- case Some(t: item.Terminal) if stack.hasTagCompound => sidedKeys.contains(stack.getTagCompound.getString(Settings.namespace + "key"))
+ override def isUsableByPlayer(keyboard: api.internal.Keyboard, player: PlayerEntity) = {
+ val stack = player.getItemInHand(Hand.MAIN_HAND)
+ stack.getItem match {
+ case t: item.Terminal if stack.hasTag => sidedKeys.contains(stack.getTag.getString(Settings.namespace + "key"))
case _ => false
}
}
@@ -71,7 +70,7 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
if (rack != null) {
val data = rack.getMountableData(slot)
if (data != null) {
- return data.hasKey("terminalAddress")
+ return data.contains("terminalAddress")
}
}
false
@@ -80,8 +79,8 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
def address: String = rack.getMountableData(slot).getString("terminalAddress")
def sidedKeys = {
- if (!rack.world.isRemote) keys
- else rack.getMountableData(slot).getTagList("keys", NBT.TAG_STRING).map((tag: NBTTagString) => tag.getString)
+ if (!rack.world.isClientSide) keys
+ else rack.getMountableData(slot).getList("keys", NBT.TAG_STRING).map((tag: StringNBT) => tag.getAsString)
}
// ----------------------------------------------------------------------- //
@@ -133,12 +132,12 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
// ----------------------------------------------------------------------- //
// RackMountable
- override def getData: NBTTagCompound = {
+ override def getData: CompoundNBT = {
if (node.address == null) api.Network.joinNewNetwork(node)
- val nbt = new NBTTagCompound()
+ val nbt = new CompoundNBT()
nbt.setNewTagList("keys", keys)
- nbt.setString("terminalAddress", node.address)
+ nbt.putString("terminalAddress", node.address)
nbt
}
@@ -146,25 +145,20 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
override def getConnectableAt(index: Int): RackBusConnectable = null
- override def onActivate(player: EntityPlayer, hand: EnumHand, heldItem: ItemStack, hitX: Float, hitY: Float): Boolean = {
+ override def onActivate(player: PlayerEntity, hand: Hand, heldItem: ItemStack, hitX: Float, hitY: Float): Boolean = {
if (api.Items.get(heldItem) == api.Items.get(Constants.ItemName.Terminal)) {
- if (!world.isRemote) {
+ if (!world.isClientSide) {
val key = UUID.randomUUID().toString
- if (!heldItem.hasTagCompound) {
- heldItem.setTagCompound(new NBTTagCompound())
- }
- else {
- keys -= heldItem.getTagCompound.getString(Settings.namespace + "key")
- }
+ keys -= heldItem.getOrCreateTag.getString(Settings.namespace + "key")
val maxSize = Settings.get.terminalsPerServer
while (keys.length >= maxSize) {
keys.remove(0)
}
keys += key
- heldItem.getTagCompound.setString(Settings.namespace + "key", key)
- heldItem.getTagCompound.setString(Settings.namespace + "server", node.address)
+ heldItem.getTag.putString(Settings.namespace + "key", key)
+ heldItem.getTag.putString(Settings.namespace + "server", node.address)
rack.markChanged(slot)
- player.inventory.markDirty()
+ player.inventory.setChanged()
}
true
}
@@ -178,20 +172,20 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
private final val KeyboardTag = Settings.namespace + "keyboard"
private final val KeysTag = Settings.namespace + "keys"
- override def load(nbt: NBTTagCompound): Unit = {
- if (!rack.world.isRemote) {
- node.load(nbt)
+ override def loadData(nbt: CompoundNBT): Unit = {
+ if (!rack.world.isClientSide) {
+ node.loadData(nbt)
}
- buffer.load(nbt.getCompoundTag(BufferTag))
- keyboard.load(nbt.getCompoundTag(KeyboardTag))
+ buffer.loadData(nbt.getCompound(BufferTag))
+ keyboard.loadData(nbt.getCompound(KeyboardTag))
keys.clear()
- nbt.getTagList(KeysTag, NBT.TAG_STRING).foreach((tag: NBTTagString) => keys += tag.getString)
+ nbt.getList(KeysTag, NBT.TAG_STRING).foreach((tag: StringNBT) => keys += tag.getAsString)
}
- override def save(nbt: NBTTagCompound): Unit = {
- node.save(nbt)
- nbt.setNewCompoundTag(BufferTag, buffer.save)
- nbt.setNewCompoundTag(KeyboardTag, keyboard.save)
+ override def saveData(nbt: CompoundNBT): Unit = {
+ node.saveData(nbt)
+ nbt.setNewCompoundTag(BufferTag, buffer.saveData)
+ nbt.setNewCompoundTag(KeyboardTag, keyboard.saveData)
nbt.setNewTagList(KeysTag, keys)
}
@@ -201,7 +195,7 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
override def canUpdate: Boolean = true
override def update(): Unit = {
- if (world.isRemote || (node.address != null && node.network != null)) {
+ if (world.isClientSide || (node.address != null && node.network != null)) {
buffer.update()
}
}
@@ -216,12 +210,12 @@ class TerminalServer(val rack: api.internal.Rack, val slot: Int) extends Environ
// ----------------------------------------------------------------------- //
// Analyzable
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(buffer.node, keyboard.node)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(buffer.node, keyboard.node)
// ----------------------------------------------------------------------- //
// LifeCycle
- override def onLifecycleStateChange(state: Lifecycle.LifecycleState): Unit = if (rack.world.isRemote) state match {
+ override def onLifecycleStateChange(state: Lifecycle.LifecycleState): Unit = if (rack.world.isClientSide) state match {
case Lifecycle.LifecycleState.Initialized =>
TerminalServer.loaded.add(this)
case Lifecycle.LifecycleState.Disposed =>
diff --git a/src/main/scala/li/cil/oc/common/component/TextBuffer.scala b/src/main/scala/li/cil/oc/common/component/TextBuffer.scala
index 51cb8c83d8..c780521b17 100644
--- a/src/main/scala/li/cil/oc/common/component/TextBuffer.scala
+++ b/src/main/scala/li/cil/oc/common/component/TextBuffer.scala
@@ -1,6 +1,7 @@
package li.cil.oc.common.component
import com.google.common.base.Strings
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.Constants
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
import li.cil.oc.api.driver.DeviceInfo.DeviceClass
@@ -31,17 +32,17 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.PackedColor
import li.cil.oc.util.SideTracker
import net.minecraft.client.Minecraft
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumHand
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Hand
import net.minecraftforge.event.world.ChunkEvent
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment with traits.TextBufferProxy with VideoRamRasterizer with DeviceInfo {
@@ -125,7 +126,7 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
override def update() {
super.update()
- if (isDisplaying && host.world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (isDisplaying && host.world.getGameTime % Settings.get.tickFrequency == 0) {
if (relativeLitArea < 0) {
// The relative lit area is the number of pixels that are not blank
// versus the number of pixels in the *current* resolution. This is
@@ -220,7 +221,7 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
precisionMode = args.checkBoolean(0)
result(oldValue)
}
- else result(Unit, "unsupported operation")
+ else result((), "unsupported operation")
}
// ----------------------------------------------------------------------- //
@@ -257,7 +258,7 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
override def getMaximumHeight: Int = maxResolution._2
- override def setAspectRatio(width: Double, height: Double): Unit = this.synchronized(aspectRatio = (width, height))
+ override def setAspectRatio(width: Double, height: Double): Unit = this.synchronized(this.aspectRatio = (width, height))
override def getAspectRatio: Double = aspectRatio._1 / aspectRatio._2
@@ -361,43 +362,46 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
proxy.onBufferRawSetForeground(col, row, color)
}
- @SideOnly(Side.CLIENT)
- override def renderText: Boolean = relativeLitArea != 0 && proxy.render()
+ @OnlyIn(Dist.CLIENT)
+ override def renderText(stack: MatrixStack): Boolean = relativeLitArea != 0 && proxy.render(stack)
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def renderWidth: Int = TextBufferRenderCache.renderer.charRenderWidth * getViewportWidth
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def renderHeight: Int = TextBufferRenderCache.renderer.charRenderHeight * getViewportHeight
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def setRenderingEnabled(enabled: Boolean): Unit = isRendering = enabled
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def isRenderingEnabled: Boolean = isRendering
- override def keyDown(character: Char, code: Int, player: EntityPlayer): Unit =
+ override def keyDown(character: Char, code: Int, player: PlayerEntity): Unit =
proxy.keyDown(character, code, player)
- override def keyUp(character: Char, code: Int, player: EntityPlayer): Unit =
+ override def keyUp(character: Char, code: Int, player: PlayerEntity): Unit =
proxy.keyUp(character, code, player)
- override def clipboard(value: String, player: EntityPlayer): Unit =
+ override def textInput(codePt: Int, player: PlayerEntity): Unit =
+ proxy.textInput(codePt, player)
+
+ override def clipboard(value: String, player: PlayerEntity): Unit =
proxy.clipboard(value, player)
- override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer): Unit =
+ override def mouseDown(x: Double, y: Double, button: Int, player: PlayerEntity): Unit =
proxy.mouseDown(x, y, button, player)
- override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer): Unit =
+ override def mouseDrag(x: Double, y: Double, button: Int, player: PlayerEntity): Unit =
proxy.mouseDrag(x, y, button, player)
- override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer): Unit =
+ override def mouseUp(x: Double, y: Double, button: Int, player: PlayerEntity): Unit =
proxy.mouseUp(x, y, button, player)
- override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer): Unit =
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: PlayerEntity): Unit =
proxy.mouseScroll(x, y, delta, player)
- def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
+ def copyToAnalyzer(line: Int, player: PlayerEntity): Unit = {
proxy.copyToAnalyzer(line, player)
}
@@ -428,38 +432,38 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
private final val ViewportWidthTag = Settings.namespace + "viewportWidth"
private final val ViewportHeightTag = Settings.namespace + "viewportHeight"
- override def load(nbt: NBTTagCompound) {
- super.load(nbt)
+ override def loadData(nbt: CompoundNBT) {
+ super.loadData(nbt)
if (SideTracker.isClient) {
if (!Strings.isNullOrEmpty(proxy.nodeAddress)) return // Only load once.
- proxy.nodeAddress = nbt.getCompoundTag(NodeData.NodeTag).getString(NodeData.AddressTag)
+ proxy.nodeAddress = nbt.getCompound(NodeData.NodeTag).getString(NodeData.AddressTag)
TextBuffer.registerClientBuffer(this)
}
else {
- if (nbt.hasKey(NodeData.BufferTag)) {
- data.load(nbt.getCompoundTag(NodeData.BufferTag))
+ if (nbt.contains(NodeData.BufferTag)) {
+ data.loadData(nbt.getCompound(NodeData.BufferTag))
}
else if (!Strings.isNullOrEmpty(node.address)) {
- data.load(SaveHandler.loadNBT(nbt, bufferPath))
+ data.loadData(SaveHandler.loadNBT(nbt, bufferPath))
}
}
- if (nbt.hasKey(IsOnTag)) {
+ if (nbt.contains(IsOnTag)) {
isDisplaying = nbt.getBoolean(IsOnTag)
}
- if (nbt.hasKey(HasPowerTag)) {
+ if (nbt.contains(HasPowerTag)) {
hasPower = nbt.getBoolean(HasPowerTag)
}
- if (nbt.hasKey(MaxWidthTag) && nbt.hasKey(MaxHeightTag)) {
- val maxWidth = nbt.getInteger(MaxWidthTag)
- val maxHeight = nbt.getInteger(MaxHeightTag)
+ if (nbt.contains(MaxWidthTag) && nbt.contains(MaxHeightTag)) {
+ val maxWidth = nbt.getInt(MaxWidthTag)
+ val maxHeight = nbt.getInt(MaxHeightTag)
maxResolution = (maxWidth, maxHeight)
}
precisionMode = nbt.getBoolean(PreciseTag)
- if (nbt.hasKey(ViewportWidthTag)) {
- val vpw = nbt.getInteger(ViewportWidthTag)
- val vph = nbt.getInteger(ViewportHeightTag)
+ if (nbt.contains(ViewportWidthTag)) {
+ val vpw = nbt.getInt(ViewportWidthTag)
+ val vph = nbt.getInt(ViewportHeightTag)
viewport = (vpw min data.width max 1, vph min data.height max 1)
} else {
viewport = data.size
@@ -467,8 +471,8 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
}
// Null check for Waila (and other mods that may call this client side).
- override def save(nbt: NBTTagCompound): Unit = if (node != null) {
- super.save(nbt)
+ override def saveData(nbt: CompoundNBT): Unit = if (node != null) {
+ super.saveData(nbt)
// Happy thread synchronization hack! Here's the problem: GPUs allow direct
// calls for modifying screens to give a more responsive experience. This
// causes the following problem: when saving, if the screen is saved first,
@@ -486,14 +490,14 @@ class TextBuffer(val host: EnvironmentHost) extends AbstractManagedEnvironment w
}
}
- SaveHandler.scheduleSave(host, nbt, bufferPath, data.save _)
- nbt.setBoolean(IsOnTag, isDisplaying)
- nbt.setBoolean(HasPowerTag, hasPower)
- nbt.setInteger(MaxWidthTag, maxResolution._1)
- nbt.setInteger(MaxHeightTag, maxResolution._2)
- nbt.setBoolean(PreciseTag, precisionMode)
- nbt.setInteger(ViewportWidthTag, viewport._1)
- nbt.setInteger(ViewportHeightTag, viewport._2)
+ SaveHandler.scheduleSave(host, nbt, bufferPath, data.saveData _)
+ nbt.putBoolean(IsOnTag, isDisplaying)
+ nbt.putBoolean(HasPowerTag, hasPower)
+ nbt.putInt(MaxWidthTag, maxResolution._1)
+ nbt.putInt(MaxHeightTag, maxResolution._2)
+ nbt.putBoolean(PreciseTag, precisionMode)
+ nbt.putInt(ViewportWidthTag, viewport._1)
+ nbt.putInt(ViewportHeightTag, viewport._2)
}
}
@@ -501,11 +505,12 @@ object TextBuffer {
var clientBuffers = mutable.ListBuffer.empty[TextBuffer]
@SubscribeEvent
- def onChunkUnload(e: ChunkEvent.Unload) {
+ def onChunkUnloaded(e: ChunkEvent.Unload) {
val chunk = e.getChunk
clientBuffers = clientBuffers.filter(t => {
val blockPos = BlockPosition(t.host)
- val keep = t.host.world != e.getWorld || !chunk.isAtLocation(blockPos.x >> 4, blockPos.z >> 4)
+ val chunkPos = chunk.getPos
+ val keep = t.host.world != e.getWorld || ((blockPos.x >> 4) != chunkPos.x || (blockPos.z >> 4) != chunkPos.z)
if (!keep) {
ClientComponentTracker.remove(t.host.world, t)
}
@@ -537,11 +542,12 @@ object TextBuffer {
var nodeAddress = ""
- def markDirty() {
+ def setChanged() {
dirty = true
}
- def render() = false
+ @OnlyIn(Dist.CLIENT)
+ def render(stack: MatrixStack) = false
def onBufferColorChange(): Unit
@@ -596,21 +602,23 @@ object TextBuffer {
owner.relativeLitArea = -1
}
- def keyDown(character: Char, code: Int, player: EntityPlayer): Unit
+ def keyDown(character: Char, code: Int, player: PlayerEntity): Unit
+
+ def keyUp(character: Char, code: Int, player: PlayerEntity): Unit
- def keyUp(character: Char, code: Int, player: EntityPlayer): Unit
+ def textInput(codePt: Int, player: PlayerEntity): Unit
- def clipboard(value: String, player: EntityPlayer): Unit
+ def clipboard(value: String, player: PlayerEntity): Unit
- def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
+ def mouseDown(x: Double, y: Double, button: Int, player: PlayerEntity): Unit
- def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
+ def mouseDrag(x: Double, y: Double, button: Int, player: PlayerEntity): Unit
- def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
+ def mouseUp(x: Double, y: Double, button: Int, player: PlayerEntity): Unit
- def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer): Unit
+ def mouseScroll(x: Double, y: Double, delta: Int, player: PlayerEntity): Unit
- def copyToAnalyzer(line: Int, player: EntityPlayer): Unit
+ def copyToAnalyzer(line: Int, player: PlayerEntity): Unit
}
class ClientProxy(val owner: TextBuffer) extends Proxy {
@@ -624,52 +632,53 @@ object TextBuffer {
override def viewport: (Int, Int) = owner.viewport
}
- override def render() = {
+ @OnlyIn(Dist.CLIENT)
+ override def render(stack: MatrixStack) = {
val wasDirty = dirty
- TextBufferRenderCache.render(renderer)
+ TextBufferRenderCache.render(stack, renderer)
wasDirty
}
override def onBufferColorChange() {
- markDirty()
+ setChanged()
}
override def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
super.onBufferCopy(col, row, w, h, tx, ty)
- markDirty()
+ setChanged()
}
override def onBufferDepthChange(depth: api.internal.TextBuffer.ColorDepth) {
- markDirty()
+ setChanged()
}
override def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
super.onBufferFill(col, row, w, h, c)
- markDirty()
+ setChanged()
}
override def onBufferPaletteChange(index: Int) {
- markDirty()
+ setChanged()
}
override def onBufferResolutionChange(w: Int, h: Int) {
super.onBufferResolutionChange(w, h)
- markDirty()
+ setChanged()
}
override def onBufferViewportResolutionChange(w: Int, h: Int) {
super.onBufferViewportResolutionChange(w, h)
- markDirty()
+ setChanged()
}
override def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
super.onBufferSet(col, row, s, vertical)
- markDirty()
+ setChanged()
}
override def onBufferBitBlt(col: Int, row: Int, w: Int, h: Int, ram: component.GpuTextBuffer, fromCol: Int, fromRow: Int): Unit = {
super.onBufferBitBlt(col, row, w, h, ram, fromCol, fromRow)
- markDirty()
+ setChanged()
}
override def onBufferRamInit(ram: component.GpuTextBuffer): Unit = {
@@ -680,49 +689,54 @@ object TextBuffer {
super.onBufferRamDestroy(ram)
}
- override def keyDown(character: Char, code: Int, player: EntityPlayer) {
+ override def keyDown(character: Char, code: Int, player: PlayerEntity) {
debug(s"{type = keyDown, char = $character, code = $code}")
ClientPacketSender.sendKeyDown(nodeAddress, character, code)
}
- override def keyUp(character: Char, code: Int, player: EntityPlayer) {
+ override def keyUp(character: Char, code: Int, player: PlayerEntity) {
debug(s"{type = keyUp, char = $character, code = $code}")
ClientPacketSender.sendKeyUp(nodeAddress, character, code)
}
- override def clipboard(value: String, player: EntityPlayer) {
+ override def textInput(codePt: Int, player: PlayerEntity) {
+ debug(s"{type = textInput, codePt = $codePt}")
+ ClientPacketSender.sendTextInput(nodeAddress, codePt)
+ }
+
+ override def clipboard(value: String, player: PlayerEntity) {
debug(s"{type = clipboard}")
ClientPacketSender.sendClipboard(nodeAddress, value)
}
- override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ override def mouseDown(x: Double, y: Double, button: Int, player: PlayerEntity) {
debug(s"{type = mouseDown, x = $x, y = $y, button = $button}")
ClientPacketSender.sendMouseClick(nodeAddress, x, y, drag = false, button)
}
- override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ override def mouseDrag(x: Double, y: Double, button: Int, player: PlayerEntity) {
debug(s"{type = mouseDrag, x = $x, y = $y, button = $button}")
ClientPacketSender.sendMouseClick(nodeAddress, x, y, drag = true, button)
}
- override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ override def mouseUp(x: Double, y: Double, button: Int, player: PlayerEntity) {
debug(s"{type = mouseUp, x = $x, y = $y, button = $button}")
ClientPacketSender.sendMouseUp(nodeAddress, x, y, button)
}
- override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer) {
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: PlayerEntity) {
debug(s"{type = mouseScroll, x = $x, y = $y, delta = $delta}")
ClientPacketSender.sendMouseScroll(nodeAddress, x, y, delta)
}
- override def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
+ override def copyToAnalyzer(line: Int, player: PlayerEntity): Unit = {
ClientPacketSender.sendCopyToAnalyzer(nodeAddress, line)
}
private lazy val Debugger = api.Items.get(Constants.ItemName.Debugger)
private def debug(message: String) {
- if (Minecraft.getMinecraft != null && Minecraft.getMinecraft.player != null && api.Items.get(Minecraft.getMinecraft.player.getHeldItemMainhand) == Debugger) {
+ if (Minecraft.getInstance != null && Minecraft.getInstance.player != null && api.Items.get(Minecraft.getInstance.player.getItemInHand(Hand.MAIN_HAND)) == Debugger) {
OpenComputers.log.info(s"[NETWORK DEBUGGER] Sending packet to node $nodeAddress: " + message)
}
}
@@ -791,8 +805,8 @@ object TextBuffer {
override def onBufferRamInit(ram: component.GpuTextBuffer): Unit = {
super.onBufferRamInit(ram)
owner.host.markChanged()
- val nbt = new NBTTagCompound()
- ram.save(nbt)
+ val nbt = new CompoundNBT()
+ ram.saveData(nbt)
owner.synchronized(ServerPacketSender.appendTextBufferRamInit(owner.pendingCommands, ram.owner, ram.id, nbt))
}
@@ -820,56 +834,53 @@ object TextBuffer {
owner.synchronized(ServerPacketSender.appendTextBufferRawSetForeground(owner.pendingCommands, col, row, color))
}
- override def keyDown(character: Char, code: Int, player: EntityPlayer) {
+ override def keyDown(character: Char, code: Int, player: PlayerEntity) {
sendToKeyboards("keyboard.keyDown", player, Char.box(character), Int.box(code))
}
- override def keyUp(character: Char, code: Int, player: EntityPlayer) {
+ override def keyUp(character: Char, code: Int, player: PlayerEntity) {
sendToKeyboards("keyboard.keyUp", player, Char.box(character), Int.box(code))
}
- override def clipboard(value: String, player: EntityPlayer) {
+ override def textInput(codePt: Int, player: PlayerEntity) {
+ sendToKeyboards("keyboard.textInput", player, Int.box(codePt))
+ }
+
+ override def clipboard(value: String, player: PlayerEntity) {
sendToKeyboards("keyboard.clipboard", player, value)
}
- override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ override def mouseDown(x: Double, y: Double, button: Int, player: PlayerEntity) {
sendMouseEvent(player, "touch", x, y, button)
}
- override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ override def mouseDrag(x: Double, y: Double, button: Int, player: PlayerEntity) {
sendMouseEvent(player, "drag", x, y, button)
}
- override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ override def mouseUp(x: Double, y: Double, button: Int, player: PlayerEntity) {
sendMouseEvent(player, "drop", x, y, button)
}
- override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer) {
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: PlayerEntity) {
sendMouseEvent(player, "scroll", x, y, delta)
}
- override def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
- val stack = player.getHeldItem(EnumHand.MAIN_HAND)
+ override def copyToAnalyzer(line: Int, player: PlayerEntity): Unit = {
+ val stack = player.getItemInHand(Hand.MAIN_HAND)
if (!stack.isEmpty) {
- if (!stack.hasTagCompound) {
- stack.setTagCompound(new NBTTagCompound())
- }
- stack.getTagCompound.removeTag(Settings.namespace + "clipboard")
+ stack.removeTagKey(Settings.namespace + "clipboard")
if (line >= 0 && line < owner.getViewportHeight) {
val text = new String(owner.data.buffer(line)).trim
if (!Strings.isNullOrEmpty(text)) {
- stack.getTagCompound.setString(Settings.namespace + "clipboard", text)
+ stack.getOrCreateTag.putString(Settings.namespace + "clipboard", text)
}
}
-
- if (stack.getTagCompound.hasNoTags) {
- stack.setTagCompound(null)
- }
}
}
- private def sendMouseEvent(player: EntityPlayer, name: String, x: Double, y: Double, data: Int) = {
+ private def sendMouseEvent(player: PlayerEntity, name: String, x: Double, y: Double, data: Int) = {
val args = mutable.ArrayBuffer.empty[AnyRef]
args += player
@@ -884,10 +895,10 @@ object TextBuffer {
}
args += Int.box(data)
if (Settings.get.inputUsername) {
- args += player.getName
+ args += player.getName.getString
}
- owner.node.sendToReachable("computer.checked_signal", args: _*)
+ owner.node.sendToReachable("computer.checked_signal", args.toSeq: _*)
}
private def sendToKeyboards(name: String, values: AnyRef*) {
diff --git a/src/main/scala/li/cil/oc/common/component/traits/VideoRamDevice.scala b/src/main/scala/li/cil/oc/common/component/traits/VideoRamDevice.scala
index 7bd2b41151..4d75c0b2bd 100644
--- a/src/main/scala/li/cil/oc/common/component/traits/VideoRamDevice.scala
+++ b/src/main/scala/li/cil/oc/common/component/traits/VideoRamDevice.scala
@@ -1,7 +1,7 @@
package li.cil.oc.common.component.traits
import li.cil.oc.common.component
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import scala.collection.mutable
trait VideoRamDevice {
@@ -37,9 +37,9 @@ trait VideoRamDevice {
def removeAllBuffers(): Int = removeBuffers(bufferIndexes())
- def loadBuffer(address: String, id: Int, nbt: NBTTagCompound): Unit = {
+ def loadBuffer(address: String, id: Int, nbt: CompoundNBT): Unit = {
val src = new li.cil.oc.util.TextBuffer(width = 1, height = 1, li.cil.oc.util.PackedColor.SingleBitFormat)
- src.load(nbt)
+ src.loadData(nbt)
addBuffer(component.GpuTextBuffer.wrap(address, id, src))
}
diff --git a/src/main/scala/li/cil/oc/common/component/traits/VideoRamRasterizer.scala b/src/main/scala/li/cil/oc/common/component/traits/VideoRamRasterizer.scala
index 1aa3910cce..452182a6b8 100644
--- a/src/main/scala/li/cil/oc/common/component/traits/VideoRamRasterizer.scala
+++ b/src/main/scala/li/cil/oc/common/component/traits/VideoRamRasterizer.scala
@@ -2,8 +2,7 @@ package li.cil.oc.common.component.traits
import li.cil.oc.common.component
import li.cil.oc.common.component.GpuTextBuffer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.village.VillageDoorInfo
+import net.minecraft.nbt.CompoundNBT
import scala.collection.mutable
@@ -54,7 +53,7 @@ trait VideoRamRasterizer {
}
}
}
- case _ => Unit
+ case _ =>
}
count
}
@@ -67,9 +66,9 @@ trait VideoRamRasterizer {
count
}
- def loadBuffer(owner: String, id: Int, nbt: NBTTagCompound): Boolean = {
+ def loadBuffer(owner: String, id: Int, nbt: CompoundNBT): Boolean = {
val src = new li.cil.oc.util.TextBuffer(width = 1, height = 1, li.cil.oc.util.PackedColor.SingleBitFormat)
- src.load(nbt)
+ src.loadData(nbt)
addBuffer(component.GpuTextBuffer.wrap(owner, id, src))
}
diff --git a/src/main/scala/li/cil/oc/common/container/Adapter.scala b/src/main/scala/li/cil/oc/common/container/Adapter.scala
index c3d93ddf68..153fe27569 100644
--- a/src/main/scala/li/cil/oc/common/container/Adapter.scala
+++ b/src/main/scala/li/cil/oc/common/container/Adapter.scala
@@ -1,10 +1,19 @@
package li.cil.oc.common.container
+import li.cil.oc.api.Driver
import li.cil.oc.common.Slot
+import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.item.ItemStack
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+
+class Adapter(selfType: ContainerType[_ <: Adapter], id: Int, playerInventory: PlayerInventory, adapter: IInventory)
+ extends Player(selfType, id, playerInventory, adapter) {
+
+ override protected def getHostClass = classOf[tileentity.Adapter]
-class Adapter(playerInventory: InventoryPlayer, adapter: tileentity.Adapter) extends Player(playerInventory, adapter) {
addSlotToContainer(80, 35, Slot.Upgrade)
addPlayerInventorySlots(8, 84)
}
diff --git a/src/main/scala/li/cil/oc/common/container/Assembler.scala b/src/main/scala/li/cil/oc/common/container/Assembler.scala
index 8f843acb59..236cd33284 100644
--- a/src/main/scala/li/cil/oc/common/container/Assembler.scala
+++ b/src/main/scala/li/cil/oc/common/container/Assembler.scala
@@ -5,25 +5,39 @@ import li.cil.oc.common
import li.cil.oc.common.InventorySlots.InventorySlot
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.item.ItemStack
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.nbt.CompoundNBT
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class Assembler(selfType: ContainerType[_ <: Assembler], id: Int, playerInventory: PlayerInventory, val assembler: IInventory)
+ extends Player(selfType, id, playerInventory, assembler) {
+
+ override protected def getHostClass = classOf[tileentity.Assembler]
-class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Assembler) extends Player(playerInventory, assembler) {
// Computer case.
{
- val index = inventorySlots.size
- addSlotToContainer(new StaticComponentSlot(this, otherInventory, index, 12, 12, "template", common.Tier.Any) {
- @SideOnly(Side.CLIENT) override
- def isEnabled = !isAssembling && super.isEnabled
+ val index = slots.size
+ addSlot(new StaticComponentSlot(this, otherInventory, index, 12, 12, getHostClass, "template", common.Tier.Any) {
+ @OnlyIn(Dist.CLIENT) override
+ def isActive = !isAssembling && super.isActive
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!container.canPlaceItem(getSlotIndex, stack)) return false
+ if (isAssembling) return false
+ AssemblerTemplates.select(stack).isDefined
+ }
+
+ @OnlyIn(Dist.CLIENT)
override def getBackgroundLocation = if (isAssembling) Textures.Icons.get(common.Tier.None) else super.getBackgroundLocation
})
}
private def slotInfo(slot: DynamicComponentSlot) = {
- AssemblerTemplates.select(getSlot(0).getStack) match {
+ AssemblerTemplates.select(getSlot(0).getItem) match {
case Some(template) =>
val index = slot.getSlotIndex
val tplSlot =
@@ -36,6 +50,26 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
}
}
+ override def addSlotToContainer(x: Int, y: Int, info: DynamicComponentSlot => InventorySlot) {
+ val index = slots.size
+ addSlot(new DynamicComponentSlot(this, otherInventory, index, x, y, getHostClass, info, () => common.Tier.One) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!super.mayPlace(stack)) return false
+ AssemblerTemplates.select(getSlot(0).getItem) match {
+ case Some(template) =>
+ val index = getSlotIndex
+ val tplSlot =
+ if ((1 until 4) contains index) template.containerSlots(index - 1)
+ else if ((4 until 13) contains index) template.upgradeSlots(index - 4)
+ else if ((13 until 21) contains index) template.componentSlots(index - 13)
+ else AssemblerTemplates.NoSlot
+ tplSlot.validate(assembler, getSlotIndex, stack)
+ case _ => false
+ }
+ }
+ })
+ }
+
// Component containers.
for (i <- 0 until 3) {
addSlotToContainer(34 + i * slotSize, 70, slotInfo _)
@@ -71,12 +105,17 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
def assemblyProgress = synchronizedData.getDouble("assemblyProgress")
- def assemblyRemainingTime = synchronizedData.getInteger("assemblyRemainingTime")
+ def assemblyRemainingTime = synchronizedData.getInt("assemblyRemainingTime")
- override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
- synchronizedData.setBoolean("isAssembling", assembler.isAssembling)
- synchronizedData.setDouble("assemblyProgress", assembler.progress)
- synchronizedData.setInteger("assemblyRemainingTime", assembler.timeRemaining)
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
+ assembler match {
+ case te: tileentity.Assembler => {
+ synchronizedData.putBoolean("isAssembling", te.isAssembling)
+ synchronizedData.putDouble("assemblyProgress", te.progress)
+ synchronizedData.putInt("assemblyRemainingTime", te.timeRemaining)
+ }
+ case _ =>
+ }
super.detectCustomDataChanges(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Case.scala b/src/main/scala/li/cil/oc/common/container/Case.scala
index 021324c215..e6b91eda97 100644
--- a/src/main/scala/li/cil/oc/common/container/Case.scala
+++ b/src/main/scala/li/cil/oc/common/container/Case.scala
@@ -3,48 +3,71 @@ package li.cil.oc.common.container
import li.cil.oc.common.InventorySlots
import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.util.IntReferenceHolder
+import net.minecraft.util.text.ITextComponent
-class Case(playerInventory: InventoryPlayer, computer: tileentity.Case) extends Player(playerInventory, computer) {
- for (i <- 0 to (if (computer.tier >= Tier.Three) 2 else 1)) {
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+class Case(selfType: ContainerType[_ <: Case], id: Int, playerInventory: PlayerInventory, computer: IInventory, tier: Int)
+ extends Player(selfType, id, playerInventory, computer) {
+
+ override protected def getHostClass = classOf[tileentity.Case]
+
+ for (i <- 0 to (if (tier >= Tier.Three) 2 else 1)) {
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(98, 16 + i * slotSize, slot.slot, slot.tier)
}
- for (i <- 0 to (if (computer.tier == Tier.One) 0 else 1)) {
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+ for (i <- 0 to (if (tier == Tier.One) 0 else 1)) {
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(120, 16 + (i + 1) * slotSize, slot.slot, slot.tier)
}
- for (i <- 0 to (if (computer.tier == Tier.One) 0 else 1)) {
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+ for (i <- 0 to (if (tier == Tier.One) 0 else 1)) {
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(142, 16 + i * slotSize, slot.slot, slot.tier)
}
- if (computer.tier >= Tier.Three) {
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+ if (tier >= Tier.Three) {
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(142, 16 + 2 * slotSize, slot.slot, slot.tier)
}
{
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(120, 16, slot.slot, slot.tier)
}
- if (computer.tier == Tier.One) {
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+ if (tier == Tier.One) {
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(120, 16 + 2 * slotSize, slot.slot, slot.tier)
}
{
- val slot = InventorySlots.computer(computer.tier)(getInventory.size)
+ val slot = InventorySlots.computer(tier)(getItems.size)
addSlotToContainer(48, 34, slot.slot, slot.tier)
}
// Show the player's inventory.
addPlayerInventorySlots(8, 84)
- override def canInteractWith(player: EntityPlayer) =
- super.canInteractWith(player) && computer.canInteract(player.getName)
+ private val runningData = computer match {
+ case te: tileentity.Case => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = if (te.isRunning) 1 else 0
+
+ override def set(value: Int): Unit = te.setRunning(value != 0)
+ })
+ }
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def isRunning = runningData.get != 0
+
+ override def stillValid(player: PlayerEntity) =
+ super.stillValid(player) && (computer match {
+ case te: tileentity.Case => te.canInteract(player.getName.getString)
+ case _ => true
+ })
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/container/Charger.scala b/src/main/scala/li/cil/oc/common/container/Charger.scala
index 0448e3ee40..f4830be052 100644
--- a/src/main/scala/li/cil/oc/common/container/Charger.scala
+++ b/src/main/scala/li/cil/oc/common/container/Charger.scala
@@ -1,9 +1,23 @@
package li.cil.oc.common.container
+import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
+import li.cil.oc.integration.util.ItemCharge
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.item.ItemStack
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
-class Charger(playerInventory: InventoryPlayer, charger: tileentity.Charger) extends Player(playerInventory, charger) {
- addSlotToContainer(80, 35, "tablet")
+class Charger(selfType: ContainerType[_ <: Charger], id: Int, playerInventory: PlayerInventory, charger: IInventory)
+ extends Player(selfType, id, playerInventory, charger) {
+
+ override protected def getHostClass = classOf[tileentity.Charger]
+
+ addSlot(new StaticComponentSlot(this, otherInventory, slots.size, 80, 35, getHostClass, "tablet", Tier.Any) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!container.canPlaceItem(getSlotIndex, stack)) return false
+ ItemCharge.canCharge(stack)
+ }
+ })
addPlayerInventorySlots(8, 84)
}
diff --git a/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala
index 67de747f07..80350cecc2 100644
--- a/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala
+++ b/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala
@@ -1,61 +1,82 @@
package li.cil.oc.common.container
+import li.cil.oc.api.Driver
+import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.common
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.IInventory
-import net.minecraft.inventory.Slot
+import net.minecraft.inventory.container.Slot
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
-abstract class ComponentSlot(inventory: IInventory, index: Int, x: Int, y: Int) extends Slot(inventory, index, x, y) {
- def container: Player
+abstract class ComponentSlot(inventory: IInventory, index: Int, x: Int, y: Int, host: Class[_ <: EnvironmentHost]) extends Slot(inventory, index, x, y) {
+ def agentContainer: Player
def slot: String
def tier: Int
+ @OnlyIn(Dist.CLIENT)
def tierIcon: ResourceLocation
var changeListener: Option[Slot => Unit] = None
// ----------------------------------------------------------------------- //
- def hasBackground = backgroundLocation != null
+ @OnlyIn(Dist.CLIENT)
+ def hasBackground = getBackgroundLocation != null
- @SideOnly(Side.CLIENT)
- override def isEnabled = slot != common.Slot.None && tier != common.Tier.None && super.isEnabled
+ @OnlyIn(Dist.CLIENT)
+ def getBackgroundLocation: ResourceLocation = null
- override def isItemValid(stack: ItemStack) = inventory.isItemValidForSlot(getSlotIndex, stack)
+ @OnlyIn(Dist.CLIENT)
+ override def isActive = slot != common.Slot.None && tier != common.Tier.None && super.isActive
- override def onTake(player: EntityPlayer, stack: ItemStack) = {
- for (slot <- container.inventorySlots) slot match {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!inventory.canPlaceItem(getSlotIndex, stack)) return false
+ if (slot == common.Slot.None || tier == common.Tier.None) return false
+ if (slot == common.Slot.Any && tier == common.Tier.Any) return true
+ // Special case: tool slots fit everything.
+ if (slot == common.Slot.Tool) return true
+ Option(Driver.driverFor(stack, host)) match {
+ case Some(driver) => {
+ val slotOk = (slot == common.Slot.Any || driver.slot(stack) == slot)
+ val tierOk = (tier == common.Tier.Any || driver.tier(stack) <= tier)
+ slotOk && tierOk
+ }
+ case _ => false
+ }
+ }
+
+ override def onTake(player: PlayerEntity, stack: ItemStack) = {
+ for (slot <- agentContainer.slots) slot match {
case dynamic: ComponentSlot => dynamic.clearIfInvalid(player)
case _ =>
}
super.onTake(player, stack)
}
- override def putStack(stack: ItemStack): Unit = {
- super.putStack(stack)
+ override def set(stack: ItemStack): Unit = {
+ super.set(stack)
inventory match {
case playerAware: common.tileentity.traits.PlayerInputAware =>
- playerAware.onSetInventorySlotContents(container.playerInventory.player, getSlotIndex, stack)
+ playerAware.onSetInventorySlotContents(agentContainer.playerInventory.player, getSlotIndex, stack)
case _ =>
}
}
- override def onSlotChanged() {
- super.onSlotChanged()
- for (slot <- container.inventorySlots) slot match {
- case dynamic: ComponentSlot => dynamic.clearIfInvalid(container.playerInventory.player)
+ override def setChanged() {
+ super.setChanged()
+ for (slot <- agentContainer.slots) slot match {
+ case dynamic: ComponentSlot => dynamic.clearIfInvalid(agentContainer.playerInventory.player)
case _ =>
}
changeListener.foreach(_(this))
}
- protected def clearIfInvalid(player: EntityPlayer) {}
+ protected def clearIfInvalid(player: PlayerEntity) {}
}
diff --git a/src/main/scala/li/cil/oc/common/container/ContainerTypes.java b/src/main/scala/li/cil/oc/common/container/ContainerTypes.java
new file mode 100644
index 0000000000..c6af141266
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/container/ContainerTypes.java
@@ -0,0 +1,179 @@
+package li.cil.oc.common.container;
+
+import li.cil.oc.OpenComputers;
+import net.minecraft.item.ItemStack;
+import net.minecraft.inventory.Inventory;
+import net.minecraft.inventory.container.ContainerType;
+import net.minecraft.entity.player.ServerPlayerEntity;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.common.extensions.IForgeContainerType;
+import net.minecraftforge.event.RegistryEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.network.IContainerFactory;
+import net.minecraftforge.fml.network.NetworkHooks;
+import net.minecraftforge.registries.IForgeRegistry;
+import net.minecraftforge.registries.ObjectHolder;
+
+@ObjectHolder("opencomputers")
+public final class ContainerTypes {
+ public static final ContainerType ADAPTER = null;
+ public static final ContainerType ASSEMBLER = null;
+ public static final ContainerType CASE = null;
+ public static final ContainerType CHARGER = null;
+ public static final ContainerType DATABASE = null;
+ public static final ContainerType DISASSEMBLER = null;
+ public static final ContainerType DISK_DRIVE = null;
+ public static final ContainerType DRONE = null;
+ public static final ContainerType PRINTER = null;
+ public static final ContainerType RACK = null;
+ public static final ContainerType RAID = null;
+ public static final ContainerType RELAY = null;
+ public static final ContainerType ROBOT = null;
+ public static final ContainerType SERVER = null;
+ public static final ContainerType TABLET = null;
+
+ @SubscribeEvent
+ public static void registerContainers(RegistryEvent.Register> e) {
+ register(e.getRegistry(), "adapter", (id, plr, buff) -> new Adapter(ADAPTER, id, plr, new Inventory(1)));
+ register(e.getRegistry(), "assembler", (id, plr, buff) -> new Assembler(ASSEMBLER, id, plr, new Inventory(22)));
+ register(e.getRegistry(), "case", (id, plr, buff) -> {
+ int invSize = buff.readVarInt();
+ int tier = buff.readVarInt();
+ return new Case(CASE, id, plr, new Inventory(invSize), tier);
+ });
+ register(e.getRegistry(), "charger", (id, plr, buff) -> new Charger(CHARGER, id, plr, new Inventory(1)));
+ register(e.getRegistry(), "database", (id, plr, buff) -> {
+ ItemStack containerStack = buff.readItem();
+ int invSize = buff.readVarInt();
+ int tier = buff.readVarInt();
+ return new Database(DATABASE, id, plr, containerStack, new Inventory(invSize), tier);
+ });
+ register(e.getRegistry(), "disassembler", (id, plr, buff) -> new Disassembler(DISASSEMBLER, id, plr, new Inventory(1)));
+ register(e.getRegistry(), "disk_drive", (id, plr, buff) -> new DiskDrive(DISK_DRIVE, id, plr, new Inventory(1)));
+ register(e.getRegistry(), "drone", (id, plr, buff) -> {
+ int invSize = buff.readVarInt();
+ return new Drone(DRONE, id, plr, new Inventory(8), invSize);
+ });
+ register(e.getRegistry(), "printer", (id, plr, buff) -> new Printer(PRINTER, id, plr, new Inventory(3)));
+ register(e.getRegistry(), "rack", (id, plr, buff) -> new Rack(RACK, id, plr, new Inventory(4)));
+ register(e.getRegistry(), "raid", (id, plr, buff) -> new Raid(RAID, id, plr, new Inventory(3)));
+ register(e.getRegistry(), "relay", (id, plr, buff) -> new Relay(RELAY, id, plr, new Inventory(4)));
+ register(e.getRegistry(), "robot", (id, plr, buff) -> {
+ RobotInfo info = RobotInfo$.MODULE$.readRobotInfo(buff);
+ return new Robot(ROBOT, id, plr, new Inventory(100), info);
+ });
+ register(e.getRegistry(), "server", (id, plr, buff) -> {
+ ItemStack containerStack = buff.readItem();
+ int invSize = buff.readVarInt();
+ int tier = buff.readVarInt();
+ int rackSlot = buff.readVarInt() - 1;
+ return new Server(SERVER, id, plr, containerStack, new Inventory(invSize), tier, rackSlot);
+ });
+ register(e.getRegistry(), "tablet", (id, plr, buff) -> {
+ ItemStack containerStack = buff.readItem();
+ int invSize = buff.readVarInt();
+ String slot1 = buff.readUtf(32);
+ int tier1 = buff.readVarInt();
+ return new Tablet(TABLET, id, plr, containerStack, new Inventory(invSize), slot1, tier1);
+ });
+ }
+
+ private static void register(IForgeRegistry> registry, String name, IContainerFactory> factory) {
+ ContainerType> type = IForgeContainerType.create(factory);
+ type.setRegistryName(new ResourceLocation(OpenComputers.ID(), name));
+ registry.register(type);
+ }
+
+ public static void openAdapterGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Adapter adapter) {
+ NetworkHooks.openGui(player, adapter);
+ }
+
+ public static void openAssemblerGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Assembler assembler) {
+ NetworkHooks.openGui(player, assembler);
+ }
+
+ public static void openCaseGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Case computer) {
+ NetworkHooks.openGui(player, computer, buff -> {
+ buff.writeVarInt(computer.getContainerSize());
+ buff.writeVarInt(computer.tier());
+ });
+ }
+
+ public static void openChargerGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Charger charger) {
+ NetworkHooks.openGui(player, charger);
+ }
+
+ public static void openDatabaseGui(ServerPlayerEntity player, li.cil.oc.common.inventory.DatabaseInventory database) {
+ NetworkHooks.openGui(player, database, buff -> {
+ buff.writeItem(database.container());
+ buff.writeVarInt(database.getContainerSize());
+ buff.writeVarInt(database.tier());
+ });
+ }
+
+ public static void openDisassemblerGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Disassembler disassembler) {
+ NetworkHooks.openGui(player, disassembler);
+ }
+
+ public static void openDiskDriveGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.DiskDrive diskDrive) {
+ NetworkHooks.openGui(player, diskDrive);
+ }
+
+ public static void openDiskDriveGui(ServerPlayerEntity player, li.cil.oc.server.component.DiskDriveMountable diskDrive) {
+ NetworkHooks.openGui(player, diskDrive);
+ }
+
+ public static void openDiskDriveGui(ServerPlayerEntity player, li.cil.oc.common.inventory.DiskDriveMountableInventory diskDrive) {
+ NetworkHooks.openGui(player, diskDrive);
+ }
+
+ public static void openDroneGui(ServerPlayerEntity player, li.cil.oc.common.entity.Drone drone) {
+ NetworkHooks.openGui(player, drone.containerProvider(), buff -> {
+ buff.writeVarInt(drone.mainInventory().getContainerSize());
+ });
+ }
+
+ public static void openPrinterGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Printer printer) {
+ NetworkHooks.openGui(player, printer);
+ }
+
+ public static void openRackGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Rack rack) {
+ NetworkHooks.openGui(player, rack);
+ }
+
+ public static void openRaidGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Raid raid) {
+ NetworkHooks.openGui(player, raid);
+ }
+
+ public static void openRelayGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Relay relay) {
+ NetworkHooks.openGui(player, relay);
+ }
+
+ public static void openRobotGui(ServerPlayerEntity player, li.cil.oc.common.tileentity.Robot robot) {
+ NetworkHooks.openGui(player, robot, buff -> {
+ RobotInfo$.MODULE$.writeRobotInfo(buff, new RobotInfo(robot));
+ });
+ }
+
+ public static void openServerGui(ServerPlayerEntity player, li.cil.oc.common.inventory.ServerInventory server, int rackSlot) {
+ NetworkHooks.openGui(player, server, buff -> {
+ buff.writeItem(server.container());
+ buff.writeVarInt(server.getContainerSize());
+ buff.writeVarInt(server.tier());
+ buff.writeVarInt(rackSlot + 1);
+ });
+ }
+
+ public static void openTabletGui(ServerPlayerEntity player, li.cil.oc.common.item.TabletWrapper tablet) {
+ NetworkHooks.openGui(player, tablet, buff -> {
+ buff.writeItem(tablet.stack());
+ buff.writeVarInt(tablet.getContainerSize());
+ buff.writeUtf(tablet.containerSlotType(), 32);
+ buff.writeVarInt(tablet.containerSlotTier());
+ });
+ }
+
+ private ContainerTypes() {
+ throw new Error();
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/container/Database.scala b/src/main/scala/li/cil/oc/common/container/Database.scala
index b3201ec444..1c115fc0cc 100644
--- a/src/main/scala/li/cil/oc/common/container/Database.scala
+++ b/src/main/scala/li/cil/oc/common/container/Database.scala
@@ -1,14 +1,21 @@
package li.cil.oc.common.container
import li.cil.oc.common.inventory.DatabaseInventory
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.inventory._
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ClickType
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.inventory.container.Slot
import net.minecraft.item.ItemStack
-class Database(playerInventory: InventoryPlayer, databaseInventory: DatabaseInventory) extends Player(playerInventory, databaseInventory) {
- val rows = math.sqrt(databaseInventory.getSizeInventory).ceil.toInt
- val offset = 8 + Array(3, 2, 0)(databaseInventory.tier) * slotSize
+class Database(selfType: ContainerType[_ <: Database], id: Int, playerInventory: PlayerInventory, val container: ItemStack, databaseInventory: IInventory, val tier: Int)
+ extends Player(selfType, id, playerInventory, databaseInventory) {
+
+ override protected def getHostClass = null
+
+ val rows = math.sqrt(databaseInventory.getContainerSize).ceil.toInt
+ val offset = 8 + Array(3, 2, 0)(tier) * slotSize
for (row <- 0 until rows; col <- 0 until rows) {
addSlotToContainer(offset + col * slotSize, offset + row * slotSize)
@@ -17,49 +24,49 @@ class Database(playerInventory: InventoryPlayer, databaseInventory: DatabaseInve
// Show the player's inventory.
addPlayerInventorySlots(8, 174)
- override def canInteractWith(player: EntityPlayer) = player == playerInventory.player
+ override def stillValid(player: PlayerEntity) = player == playerInventory.player
- override def slotClick(slot: Int, dragType: Int, clickType: ClickType, player: EntityPlayer): ItemStack = {
- if (slot >= databaseInventory.getSizeInventory() || slot < 0) {
+ override def clicked(slot: Int, dragType: Int, clickType: ClickType, player: PlayerEntity): ItemStack = {
+ if (slot >= databaseInventory.getContainerSize() || slot < 0) {
// if the slot interaction is with the user inventory use
// default behavior
- return super.slotClick(slot, dragType, clickType, player)
+ return super.clicked(slot, dragType, clickType, player)
}
// remove the ghost item
- val ghostSlot = this.inventorySlots.get(slot);
+ val ghostSlot = this.slots.get(slot);
if (ghostSlot != null) {
val inventoryPlayer = player.inventory
- val hand = inventoryPlayer.getItemStack()
+ val hand = inventoryPlayer.getCarried()
var itemToAdd = ItemStack.EMPTY
// if the player is holding an item, place a copy
if (!hand.isEmpty()) {
itemToAdd = hand.copy()
}
- ghostSlot.putStack(itemToAdd)
+ ghostSlot.set(itemToAdd)
}
ItemStack.EMPTY
}
override protected def tryTransferStackInSlot(from: Slot, intoPlayerInventory: Boolean) {
if (intoPlayerInventory) {
- from.onSlotChanged()
+ from.setChanged()
return
}
- val fromStack = from.getStack().copy()
+ val fromStack = from.getItem().copy()
if (fromStack.isEmpty) {
return
}
fromStack.setCount(1)
- val (begin, end) = (0, inventorySlots.size - 1)
+ val (begin, end) = (0, slots.size - 1)
for (i <- begin to end) {
- val intoSlot = inventorySlots.get(i)
- if (intoSlot.inventory != from.inventory) {
- if (!intoSlot.getHasStack && intoSlot.isItemValid(fromStack)) {
- if (intoSlot.getSlotStackLimit > 0) {
- intoSlot.putStack(fromStack)
+ val intoSlot = slots.get(i)
+ if (intoSlot.container != from.container) {
+ if (!intoSlot.hasItem && intoSlot.mayPlace(fromStack)) {
+ if (intoSlot.getMaxStackSize > 0) {
+ intoSlot.set(fromStack)
return
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Disassembler.scala b/src/main/scala/li/cil/oc/common/container/Disassembler.scala
index 248e137b8d..3aa743908a 100644
--- a/src/main/scala/li/cil/oc/common/container/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/common/container/Disassembler.scala
@@ -1,17 +1,43 @@
package li.cil.oc.common.container
+import li.cil.oc.Settings
+import li.cil.oc.api
+import li.cil.oc.common.Slot
+import li.cil.oc.common.Tier
+import li.cil.oc.common.template.DisassemblerTemplates
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.nbt.NBTTagCompound
+import li.cil.oc.util.ItemUtils
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.item.ItemStack
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.nbt.CompoundNBT
-class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentity.Disassembler) extends Player(playerInventory, disassembler) {
- addSlotToContainer(80, 35, "ocitem")
+class Disassembler(selfType: ContainerType[_ <: Disassembler], id: Int, playerInventory: PlayerInventory, val disassembler: IInventory)
+ extends Player(selfType, id, playerInventory, disassembler) {
+
+ private def allowDisassembling(stack: ItemStack) = !stack.isEmpty && (!stack.hasTag || !stack.getTag.getBoolean(Settings.namespace + "undisassemblable"))
+
+ override protected def getHostClass = classOf[tileentity.Disassembler]
+
+ addSlot(new StaticComponentSlot(this, otherInventory, slots.size, 80, 35, getHostClass, "ocitem", Tier.Any) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!container.canPlaceItem(getSlotIndex, stack)) return false
+ allowDisassembling(stack) &&
+ (((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) &&
+ ItemUtils.getIngredients(playerInventory.player.level.getRecipeManager, stack).nonEmpty) ||
+ DisassemblerTemplates.select(stack).isDefined)
+ }
+ })
addPlayerInventorySlots(8, 84)
def disassemblyProgress = synchronizedData.getDouble("disassemblyProgress")
- override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
- synchronizedData.setDouble("disassemblyProgress", disassembler.progress)
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
+ disassembler match {
+ case te: tileentity.Disassembler => synchronizedData.putDouble("disassemblyProgress", te.progress)
+ case _ =>
+ }
super.detectCustomDataChanges(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/DiskDrive.scala b/src/main/scala/li/cil/oc/common/container/DiskDrive.scala
index 8a2c4b3fbf..9dedf16e12 100644
--- a/src/main/scala/li/cil/oc/common/container/DiskDrive.scala
+++ b/src/main/scala/li/cil/oc/common/container/DiskDrive.scala
@@ -1,10 +1,16 @@
package li.cil.oc.common.container
import li.cil.oc.common.Slot
-import net.minecraft.entity.player.InventoryPlayer
+import li.cil.oc.common.tileentity
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+
+class DiskDrive(selfType: ContainerType[_ <: DiskDrive], id: Int, playerInventory: PlayerInventory, drive: IInventory)
+ extends Player(selfType, id, playerInventory, drive) {
+
+ override protected def getHostClass = classOf[tileentity.DiskDrive]
-class DiskDrive(playerInventory: InventoryPlayer, drive: IInventory) extends Player(playerInventory, drive) {
addSlotToContainer(80, 35, Slot.Floppy)
addPlayerInventorySlots(8, 84)
}
diff --git a/src/main/scala/li/cil/oc/common/container/Drone.scala b/src/main/scala/li/cil/oc/common/container/Drone.scala
index fb978f074c..34326a219d 100644
--- a/src/main/scala/li/cil/oc/common/container/Drone.scala
+++ b/src/main/scala/li/cil/oc/common/container/Drone.scala
@@ -3,37 +3,110 @@ package li.cil.oc.common.container
import li.cil.oc.client.Textures
import li.cil.oc.common
import li.cil.oc.common.entity
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
import net.minecraft.item.ItemStack
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.IntReferenceHolder
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class Drone(selfType: ContainerType[_ <: Drone], id: Int, playerInventory: PlayerInventory, droneInv: IInventory, val mainInvSize: Int)
+ extends Player(selfType, id, playerInventory, droneInv) {
-class Drone(playerInventory: InventoryPlayer, drone: entity.Drone) extends Player(playerInventory, drone.mainInventory) {
val deltaY = 0
+ override protected def getHostClass = classOf[entity.Drone]
+
for (i <- 0 to 1) {
val y = 8 + i * slotSize - deltaY
for (j <- 0 to 3) {
val x = 98 + j * slotSize
- addSlotToContainer(new InventorySlot(this, otherInventory, inventorySlots.size, x, y))
+ addSlot(new InventorySlot(this, otherInventory, slots.size, x, y))
}
}
addPlayerInventorySlots(8, 66)
- class InventorySlot(container: Player, inventory: IInventory, index: Int, x: Int, y: Int) extends StaticComponentSlot(container, inventory, index, x, y, common.Slot.Any, common.Tier.Any) {
- def isValid = (0 until drone.mainInventory.getSizeInventory).contains(getSlotIndex)
+ // This factor is used to make the energy values transferable using
+ // MCs 'progress bar' stuff, even though those internally send the
+ // values as shorts over the net (for whatever reason).
+ private val factor = 100
+
+ private val globalBufferData = droneInv match {
+ case droneInv: entity.DroneInventory => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = droneInv.drone.globalBuffer / factor
+
+ override def set(value: Int): Unit = droneInv.drone.globalBuffer = value * factor
+ })
+ }
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def globalBuffer = globalBufferData.get * factor
+
+ private val globalBufferSizeData = droneInv match {
+ case droneInv: entity.DroneInventory => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = droneInv.drone.globalBufferSize / factor
+
+ override def set(value: Int): Unit = droneInv.drone.globalBufferSize = value * factor
+ })
+ }
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def globalBufferSize = globalBufferSizeData.get * factor
+
+ private val runningData = droneInv match {
+ case droneInv: entity.DroneInventory => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = if (droneInv.drone.isRunning) 1 else 0
+
+ override def set(value: Int): Unit = droneInv.drone.setRunning(value != 0)
+ })
+ }
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def isRunning = runningData.get != 0
+
+ private val selectedSlotData = droneInv match {
+ case droneInv: entity.DroneInventory => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = droneInv.drone.selectedSlot
+
+ override def set(value: Int): Unit = droneInv.drone.setSelectedSlot(value)
+ })
+ }
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def selectedSlot = selectedSlotData.get
+
+ def statusText = synchronizedData.getString("statusText")
+
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
+ droneInv match {
+ case droneInv: entity.DroneInventory => synchronizedData.putString("statusText", droneInv.drone.statusText)
+ case _ =>
+ }
+ super.detectCustomDataChanges(nbt)
+ }
+
+ class InventorySlot(container: Player, inventory: IInventory, index: Int, x: Int, y: Int)
+ extends StaticComponentSlot(container, inventory, index, x, y, getHostClass, common.Slot.Any, common.Tier.Any) {
+
+ def isValid = (0 until mainInvSize).contains(getSlotIndex)
- @SideOnly(Side.CLIENT) override
- def isEnabled = isValid && super.isEnabled
+ @OnlyIn(Dist.CLIENT) override
+ def isActive = isValid && super.isActive
+ @OnlyIn(Dist.CLIENT)
override def getBackgroundLocation =
if (isValid) super.getBackgroundLocation
else Textures.Icons.get(common.Tier.None)
- override def getStack = {
- if (isValid) super.getStack
+ override def getItem = {
+ if (isValid) super.getItem
else ItemStack.EMPTY
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala
index 612a0e5a7f..9738fda3ad 100644
--- a/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala
+++ b/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala
@@ -1,22 +1,29 @@
package li.cil.oc.common.container
+import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.client.Textures
import li.cil.oc.common
import li.cil.oc.common.InventorySlots.InventorySlot
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.SideTracker
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class DynamicComponentSlot(val agentContainer: Player, inventory: IInventory, index: Int, x: Int, y: Int, host: Class[_ <: EnvironmentHost],
+ val info: DynamicComponentSlot => InventorySlot, val containerTierGetter: () => Int)
+ extends ComponentSlot(inventory, index, x, y, host) {
-class DynamicComponentSlot(val container: Player, inventory: IInventory, index: Int, x: Int, y: Int, val info: DynamicComponentSlot => InventorySlot, val containerTierGetter: () => Int) extends ComponentSlot(inventory, index, x, y) {
override def tier: Int = {
val mainTier = containerTierGetter()
if (mainTier >= 0) info(this).tier
else mainTier
}
+ @OnlyIn(Dist.CLIENT)
def tierIcon: ResourceLocation = Textures.Icons.get(tier)
def slot: String = {
@@ -25,21 +32,23 @@ class DynamicComponentSlot(val container: Player, inventory: IInventory, index:
else common.Slot.None
}
+ @OnlyIn(Dist.CLIENT)
override def hasBackground: Boolean = Textures.Icons.get(slot) != null
+ @OnlyIn(Dist.CLIENT)
override def getBackgroundLocation: ResourceLocation = Option(Textures.Icons.get(slot)).getOrElse(super.getBackgroundLocation)
- override def getSlotStackLimit: Int =
+ override def getMaxStackSize: Int =
slot match {
- case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getSlotStackLimit
+ case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getMaxStackSize
case common.Slot.None => 0
case _ => 1
}
- override protected def clearIfInvalid(player: EntityPlayer) {
- if (SideTracker.isServer && getHasStack && !isItemValid(getStack)) {
- val stack = getStack
- putStack(ItemStack.EMPTY)
+ override protected def clearIfInvalid(player: PlayerEntity) {
+ if (SideTracker.isServer && hasItem && !mayPlace(getItem)) {
+ val stack = getItem
+ set(ItemStack.EMPTY)
InventoryUtils.addToPlayerInventory(stack, player)
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/InternalSlot.scala b/src/main/scala/li/cil/oc/common/container/InternalSlot.scala
deleted file mode 100644
index 43156ecdcf..0000000000
--- a/src/main/scala/li/cil/oc/common/container/InternalSlot.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package li.cil.oc.common.container
-
-object InternalSlot extends Enumeration {
- val Server = Value
-}
diff --git a/src/main/scala/li/cil/oc/common/container/Player.scala b/src/main/scala/li/cil/oc/common/container/Player.scala
index 64f20eae05..1aeeebc872 100644
--- a/src/main/scala/li/cil/oc/common/container/Player.scala
+++ b/src/main/scala/li/cil/oc/common/container/Player.scala
@@ -1,51 +1,65 @@
package li.cil.oc.common.container
+import java.util.Arrays
+
+import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.common
import li.cil.oc.common.InventorySlots.InventorySlot
import li.cil.oc.common.Tier
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.SideTracker
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory._
+import net.minecraft.inventory.container.ClickType
+import net.minecraft.inventory.container.Container
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.inventory.container.IContainerListener
+import net.minecraft.inventory.container.Slot
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTBase
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.ByteArrayNBT
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.INBT
+import net.minecraft.nbt.IntArrayNBT
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import net.minecraftforge.common.util.FakePlayer
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
+import scala.collection.mutable
-abstract class Player(val playerInventory: InventoryPlayer, val otherInventory: IInventory) extends Container {
+abstract class Player(selfType: ContainerType[_ <: Player], id: Int, val playerInventory: PlayerInventory, val otherInventory: IInventory) extends Container(selfType, id) {
/** Number of player inventory slots to display horizontally. */
- protected val playerInventorySizeX = math.min(9, InventoryPlayer.getHotbarSize)
+ protected val playerInventorySizeX = math.min(9, PlayerInventory.getSelectionSize)
- /** Subtract four for armor slots. */
- protected val playerInventorySizeY = math.min(4, (playerInventory.getSizeInventory - 4) / playerInventorySizeX)
+ protected val playerInventorySizeY = math.min(4, playerInventory.items.size / playerInventorySizeX)
/** Render size of slots (width and height). */
protected val slotSize = 18
private var lastSync = System.currentTimeMillis()
- override def canInteractWith(player: EntityPlayer) = otherInventory.isUsableByPlayer(player)
+ protected val playerListeners = mutable.ArrayBuffer.empty[ServerPlayerEntity]
+
+ override def stillValid(player: PlayerEntity) = otherInventory.stillValid(player)
- override def slotClick(slot: Int, dragType: Int, clickType: ClickType, player: EntityPlayer): ItemStack = {
- val result = super.slotClick(slot, dragType, clickType, player)
+ override def clicked(slot: Int, dragType: Int, clickType: ClickType, player: PlayerEntity): ItemStack = {
+ val result = super.clicked(slot, dragType, clickType, player)
if (SideTracker.isServer) {
- detectAndSendChanges() // We have to enforce this more than MC does itself
+ broadcastChanges() // We have to enforce this more than MC does itself
// because stacks can change their... "character" just by being inserted in
// certain containers - by being assigned an address.
}
result
}
- override def transferStackInSlot(player: EntityPlayer, index: Int): ItemStack = {
- val slot = Option(inventorySlots.get(index)).orNull
- if (slot != null && slot.getHasStack) {
- tryTransferStackInSlot(slot, slot.inventory == otherInventory)
+ override def quickMoveStack(player: PlayerEntity, index: Int): ItemStack = {
+ val slot = Option(slots.get(index)).orNull
+ if (slot != null && slot.hasItem) {
+ tryTransferStackInSlot(slot, slot.container == otherInventory)
if (SideTracker.isServer) {
- detectAndSendChanges()
+ broadcastChanges()
}
}
ItemStack.EMPTY
@@ -57,30 +71,30 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
return false // nowhere to move it
if (from == null ||
- !from.getHasStack ||
- from.getStack.isEmpty)
+ !from.hasItem ||
+ from.getItem.isEmpty)
return true // all moved because nothing to move
- if (to.inventory == from.inventory)
+ if (to.container == from.container)
return false // not intended for moving in the same inventory
// for ghost slots we don't care about stack size
- val fromStack = from.getStack
- val toStack = if (to.getHasStack) to.getStack else ItemStack.EMPTY
+ val fromStack = from.getItem
+ val toStack = if (to.hasItem) to.getItem else ItemStack.EMPTY
val toStackSize = if (!toStack.isEmpty) toStack.getCount else 0
- val maxStackSize = math.min(fromStack.getMaxStackSize, to.getSlotStackLimit)
+ val maxStackSize = math.min(fromStack.getMaxStackSize, to.getMaxStackSize)
val itemsMoved = math.min(maxStackSize - toStackSize, fromStack.getCount)
if (!toStack.isEmpty) {
if (toStackSize < maxStackSize &&
- fromStack.isItemEqual(toStack) &&
- ItemStack.areItemStackTagsEqual(fromStack, toStack) &&
+ fromStack.sameItem(toStack) &&
+ ItemStack.tagMatches(fromStack, toStack) &&
itemsMoved > 0) {
- toStack.grow(from.decrStackSize(itemsMoved).getCount)
+ toStack.grow(from.remove(itemsMoved).getCount)
} else return false
- } else if (to.isItemValid(fromStack)) {
- to.putStack(from.decrStackSize(itemsMoved))
+ } else if (to.mayPlace(fromStack)) {
+ to.set(from.remove(itemsMoved))
if (maxStackSize == 0) {
// Special case: we have an inventory with "phantom/ghost stacks", i.e.
// zero size stacks, usually used for configuring machinery. In that
@@ -92,14 +106,14 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
}
} else return false
- to.onSlotChanged()
- from.onSlotChanged()
+ to.setChanged()
+ from.setChanged()
false
}
protected def fillOrder(backFill: Boolean): Seq[Int] = {
- (if (backFill) inventorySlots.indices.reverse else inventorySlots.indices).sortBy(i => inventorySlots(i) match {
- case s: Slot if s.getHasStack => -1
+ (if (backFill) slots.indices.reverse else slots.indices).sortBy(i => slots(i) match {
+ case s: Slot if s.hasItem => -1
case s: ComponentSlot => s.tier
case _ => 99
})
@@ -107,24 +121,27 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
protected def tryTransferStackInSlot(from: Slot, intoPlayerInventory: Boolean) {
for (i <- fillOrder(intoPlayerInventory)) {
- if (inventorySlots.get(i) match { case slot: Slot => tryMoveAllSlotToSlot(from, slot) case _ => false })
+ if (slots.get(i) match { case slot: Slot => tryMoveAllSlotToSlot(from, slot) case _ => false })
return
}
}
+ // Used by the ComponentSlots to make host-aware item placement decisions.
+ protected def getHostClass: Class[_ <: EnvironmentHost]
+
def addSlotToContainer(x: Int, y: Int, slot: String = common.Slot.Any, tier: Int = common.Tier.Any) {
- val index = inventorySlots.size
- addSlotToContainer(new StaticComponentSlot(this, otherInventory, index, x, y, slot, tier))
+ val index = slots.size
+ addSlot(new StaticComponentSlot(this, otherInventory, index, x, y, getHostClass, slot, tier))
}
def addSlotToContainer(x: Int, y: Int, info: Array[Array[InventorySlot]], containerTierGetter: () => Int) {
- val index = inventorySlots.size
- addSlotToContainer(new DynamicComponentSlot(this, otherInventory, index, x, y, slot => info(slot.containerTierGetter())(slot.getSlotIndex), containerTierGetter))
+ val index = slots.size
+ addSlot(new DynamicComponentSlot(this, otherInventory, index, x, y, getHostClass, slot => info(slot.containerTierGetter())(slot.getSlotIndex), containerTierGetter))
}
def addSlotToContainer(x: Int, y: Int, info: DynamicComponentSlot => InventorySlot) {
- val index = inventorySlots.size
- addSlotToContainer(new DynamicComponentSlot(this, otherInventory, index, x, y, info, () => Tier.One))
+ val index = slots.size
+ addSlot(new DynamicComponentSlot(this, otherInventory, index, x, y, getHostClass, info, () => Tier.One))
}
/** Render player inventory at the specified coordinates. */
@@ -136,7 +153,7 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
val x = left + slotX * slotSize
// Compensate for hot bar offset.
val y = top + (slotY - 1) * slotSize
- addSlotToContainer(new Slot(playerInventory, index, x, y))
+ addSlot(new Slot(playerInventory, index, x, y))
}
}
@@ -145,113 +162,126 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
for (index <- 0 until playerInventorySizeX) {
val x = left + index * slotSize
val y = top + slotSize * (playerInventorySizeY - 1) + quickBarSpacing
- addSlotToContainer(new Slot(playerInventory, index, x, y))
+ addSlot(new Slot(playerInventory, index, x, y))
+ }
+ }
+
+ override def addSlotListener(listener: IContainerListener): Unit = {
+ listener match {
+ case _: FakePlayer => // Nope
+ case player: ServerPlayerEntity => playerListeners += player
+ case _ =>
}
+ super.addSlotListener(listener)
}
- protected def sendWindowProperty(id: Int, value: Int) {
- listeners.foreach(_.sendWindowProperty(this, id, value))
+ @OnlyIn(Dist.CLIENT)
+ override def removeSlotListener(listener: IContainerListener): Unit = {
+ if (listener.isInstanceOf[ServerPlayerEntity]) playerListeners -= listener.asInstanceOf[ServerPlayerEntity]
+ super.removeSlotListener(listener)
}
- override def detectAndSendChanges(): Unit = {
- super.detectAndSendChanges()
+ override def broadcastChanges(): Unit = {
+ super.broadcastChanges()
if (SideTracker.isServer) {
- val nbt = new NBTTagCompound()
+ val nbt = new CompoundNBT()
detectCustomDataChanges(nbt)
- for (entry <- listeners) entry match {
- case _: FakePlayer => // Nope
- case player: EntityPlayerMP => ServerPacketSender.sendContainerUpdate(this, nbt, player)
- case _ =>
- }
+ for (player <- playerListeners) ServerPacketSender.sendContainerUpdate(this, nbt, player)
}
}
// Used for custom value synchronization, because shorts simply don't cut it most of the time.
- protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
+ protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
val delta = synchronizedData.getDelta
- if (delta != null && !delta.hasNoTags) {
- nbt.setTag("delta", delta)
+ if (delta != null && !delta.isEmpty) {
+ nbt.put("delta", delta)
}
else if (System.currentTimeMillis() - lastSync > 250) {
- nbt.setTag("delta", synchronizedData)
+ nbt.put("delta", synchronizedData)
lastSync = Long.MaxValue
}
}
- def updateCustomData(nbt: NBTTagCompound): Unit = {
- if (nbt.hasKey("delta")) {
- val delta = nbt.getCompoundTag("delta")
- delta.getKeySet.foreach {
- case key: String => synchronizedData.setTag(key, delta.getTag(key))
+ def updateCustomData(nbt: CompoundNBT): Unit = {
+ if (nbt.contains("delta")) {
+ val delta = nbt.getCompound("delta")
+ delta.getAllKeys.foreach {
+ case key: String => synchronizedData.put(key, delta.get(key))
}
}
}
- protected class SynchronizedData extends NBTTagCompound {
- private var delta = new NBTTagCompound()
+ protected class SynchronizedData extends CompoundNBT {
+ private var delta = new CompoundNBT()
- def getDelta: NBTTagCompound = this.synchronized {
- if (delta.hasNoTags) null
+ def getDelta: CompoundNBT = this.synchronized {
+ if (delta.isEmpty) null
else {
val result = delta
- delta = new NBTTagCompound()
+ delta = new CompoundNBT()
result
}
}
- override def setTag(key: String, value: NBTBase): Unit = this.synchronized {
- if (!value.equals(getTag(key))) delta.setTag(key, value)
- super.setTag(key, value)
+ override def put(key: String, value: INBT): INBT = this.synchronized {
+ if (!value.equals(get(key))) delta.put(key, value)
+ super.put(key, value)
}
- override def setByte(key: String, value: Byte): Unit = this.synchronized {
- if (value != getByte(key)) delta.setByte(key, value)
- super.setByte(key, value)
+ override def putByte(key: String, value: Byte): Unit = this.synchronized {
+ if (value != getByte(key)) delta.putByte(key, value)
+ super.putByte(key, value)
}
- override def setShort(key: String, value: Short): Unit = this.synchronized {
- if (value != getShort(key)) delta.setShort(key, value)
- super.setShort(key, value)
+ override def putShort(key: String, value: Short): Unit = this.synchronized {
+ if (value != getShort(key)) delta.putShort(key, value)
+ super.putShort(key, value)
}
- override def setInteger(key: String, value: Int): Unit = this.synchronized {
- if (value != getInteger(key)) delta.setInteger(key, value)
- super.setInteger(key, value)
+ override def putInt(key: String, value: Int): Unit = this.synchronized {
+ if (value != getInt(key)) delta.putInt(key, value)
+ super.putInt(key, value)
}
- override def setLong(key: String, value: Long): Unit = this.synchronized {
- if (value != getLong(key)) delta.setLong(key, value)
- super.setLong(key, value)
+ override def putLong(key: String, value: Long): Unit = this.synchronized {
+ if (value != getLong(key)) delta.putLong(key, value)
+ super.putLong(key, value)
}
- override def setFloat(key: String, value: Float): Unit = this.synchronized {
- if (value != getFloat(key)) delta.setFloat(key, value)
- super.setFloat(key, value)
+ override def putFloat(key: String, value: Float): Unit = this.synchronized {
+ if (value != getFloat(key)) delta.putFloat(key, value)
+ super.putFloat(key, value)
}
- override def setDouble(key: String, value: Double): Unit = this.synchronized {
- if (value != getDouble(key)) delta.setDouble(key, value)
- super.setDouble(key, value)
+ override def putDouble(key: String, value: Double): Unit = this.synchronized {
+ if (value != getDouble(key)) delta.putDouble(key, value)
+ super.putDouble(key, value)
}
- override def setString(key: String, value: String): Unit = this.synchronized {
- if (value != getString(key)) delta.setString(key, value)
- super.setString(key, value)
+ override def putString(key: String, value: String): Unit = this.synchronized {
+ if (value != getString(key)) delta.putString(key, value)
+ super.putString(key, value)
}
- override def setByteArray(key: String, value: Array[Byte]): Unit = this.synchronized {
- if (value.deep != getByteArray(key).deep) delta.setByteArray(key, value)
- super.setByteArray(key, value)
+ override def putByteArray(key: String, value: Array[Byte]): Unit = this.synchronized {
+ get(key) match {
+ case arr: ByteArrayNBT if !Arrays.equals(value, arr.getAsByteArray) => delta.putByteArray(key, value)
+ case _ =>
+ }
+ super.putByteArray(key, value)
}
- override def setIntArray(key: String, value: Array[Int]): Unit = this.synchronized {
- if (value.deep != getIntArray(key).deep) delta.setIntArray(key, value)
- super.setIntArray(key, value)
+ override def putIntArray(key: String, value: Array[Int]): Unit = this.synchronized {
+ get(key) match {
+ case arr: IntArrayNBT if !Arrays.equals(value, arr.getAsIntArray) => delta.putIntArray(key, value)
+ case _ =>
+ }
+ super.putIntArray(key, value)
}
- override def setBoolean(key: String, value: Boolean): Unit = this.synchronized {
- if (value != getBoolean(key)) delta.setBoolean(key, value)
- super.setBoolean(key, value)
+ override def putBoolean(key: String, value: Boolean): Unit = this.synchronized {
+ if (value != getBoolean(key)) delta.putBoolean(key, value)
+ super.putBoolean(key, value)
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Printer.scala b/src/main/scala/li/cil/oc/common/container/Printer.scala
index 8dbe78c5b8..3be5e425aa 100644
--- a/src/main/scala/li/cil/oc/common/container/Printer.scala
+++ b/src/main/scala/li/cil/oc/common/container/Printer.scala
@@ -1,13 +1,32 @@
package li.cil.oc.common.container
import li.cil.oc.common.Slot
+import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.item.ItemStack
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.nbt.CompoundNBT
-class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends Player(playerInventory, printer) {
- addSlotToContainer(18, 19, Slot.Filtered)
- addSlotToContainer(18, 51, Slot.Filtered)
+class Printer(selfType: ContainerType[_ <: Printer], id: Int, playerInventory: PlayerInventory, val printer: IInventory)
+ extends Player(selfType, id, playerInventory, printer) {
+
+ override protected def getHostClass = classOf[tileentity.Printer]
+
+ addSlot(new StaticComponentSlot(this, otherInventory, slots.size, 18, 19, getHostClass, Slot.Filtered, Tier.Any) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!container.canPlaceItem(getSlotIndex, stack)) return false
+ PrintData.materialValue(stack) > 0
+ }
+ })
+ addSlot(new StaticComponentSlot(this, otherInventory, slots.size, 18, 51, getHostClass, Slot.Filtered, Tier.Any) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (!container.canPlaceItem(getSlotIndex, stack)) return false
+ PrintData.inkValue(stack) > 0
+ }
+ })
addSlotToContainer(152, 35)
// Show the player's inventory.
@@ -15,14 +34,25 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer)
def progress = synchronizedData.getDouble("progress")
- def amountMaterial = synchronizedData.getInteger("amountMaterial")
+ def maxAmountMaterial = synchronizedData.getInt("maxAmountMaterial")
+
+ def amountMaterial = synchronizedData.getInt("amountMaterial")
+
+ def maxAmountInk = synchronizedData.getInt("maxAmountInk")
- def amountInk = synchronizedData.getInteger("amountInk")
+ def amountInk = synchronizedData.getInt("amountInk")
- override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
- synchronizedData.setDouble("progress", if (printer.isPrinting) printer.progress / 100.0 else 0)
- synchronizedData.setInteger("amountMaterial", printer.amountMaterial)
- synchronizedData.setInteger("amountInk", printer.amountInk)
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
+ printer match {
+ case te: tileentity.Printer => {
+ synchronizedData.putDouble("progress", if (te.isPrinting) te.progress / 100.0 else 0)
+ synchronizedData.putInt("maxAmountMaterial", te.maxAmountMaterial)
+ synchronizedData.putInt("amountMaterial", te.amountMaterial)
+ synchronizedData.putInt("maxAmountInk", te.maxAmountInk)
+ synchronizedData.putInt("amountInk", te.amountInk)
+ }
+ case _ =>
+ }
super.detectCustomDataChanges(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Rack.scala b/src/main/scala/li/cil/oc/common/container/Rack.scala
index 7c3fe1900f..a8c470d03d 100644
--- a/src/main/scala/li/cil/oc/common/container/Rack.scala
+++ b/src/main/scala/li/cil/oc/common/container/Rack.scala
@@ -4,13 +4,20 @@ import li.cil.oc.api.component.RackMountable
import li.cil.oc.common.Slot
import li.cil.oc.common.tileentity
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.nbt.NBTTagIntArray
-import net.minecraft.util.EnumFacing
+import li.cil.oc.util.RotationHelper
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.IntArrayNBT
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends Player(playerInventory, rack) {
+class Rack(selfType: ContainerType[_ <: Rack], id: Int, playerInventory: PlayerInventory, val rack: IInventory)
+ extends Player(selfType, id, playerInventory, rack) {
+
+ override protected def getHostClass = classOf[tileentity.Rack]
+
addSlotToContainer(20, 23, Slot.RackMountable)
addSlotToContainer(20, 43, Slot.RackMountable)
addSlotToContainer(20, 63, Slot.RackMountable)
@@ -19,26 +26,33 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
final val MaxConnections = 4
val nodePresence: Array[Array[Boolean]] = Array.fill(4)(Array.fill(4)(false))
+ val nodeMapping: Array[Array[Option[Direction]]] = Array.fill(rack.getContainerSize)(Array.fill[Option[Direction]](4)(None))
+ var isRelayEnabled = false
- override def updateCustomData(nbt: NBTTagCompound): Unit = {
+ override def updateCustomData(nbt: CompoundNBT): Unit = {
super.updateCustomData(nbt)
- nbt.getTagList("nodeMapping", NBT.TAG_INT_ARRAY).map((sides: NBTTagIntArray) => {
- sides.getIntArray.map(side => if (side >= 0) Option(EnumFacing.getFront(side)) else None)
- }).copyToArray(rack.nodeMapping)
+ nbt.getList("nodeMapping", NBT.TAG_INT_ARRAY).map((sides: IntArrayNBT) => {
+ sides.getAsIntArray.map(side => if (side >= 0) Option(Direction.from3DDataValue(side)) else None)
+ }).copyToArray(nodeMapping)
nbt.getBooleanArray("nodePresence").grouped(MaxConnections).copyToArray(nodePresence)
- rack.isRelayEnabled = nbt.getBoolean("isRelayEnabled")
+ isRelayEnabled = nbt.getBoolean("isRelayEnabled")
}
- override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
super.detectCustomDataChanges(nbt)
- nbt.setNewTagList("nodeMapping", rack.nodeMapping.map(sides => toNbt(sides.map {
- case Some(side) => side.ordinal()
- case _ => -1
- })))
- nbt.setBooleanArray("nodePresence", (0 until rack.getSizeInventory).flatMap(slot => rack.getMountable(slot) match {
- case mountable: RackMountable => (Seq(true) ++ (0 until math.min(MaxConnections - 1, mountable.getConnectableCount)).map(index => mountable.getConnectableAt(index) != null)).padTo(MaxConnections, false)
- case _ => Array.fill(MaxConnections)(false)
- }).toArray)
- nbt.setBoolean("isRelayEnabled", rack.isRelayEnabled)
+ rack match {
+ case te: tileentity.Rack => {
+ nbt.setNewTagList("nodeMapping", te.nodeMapping.map(sides => toNbt(sides.map {
+ case Some(side) => side.ordinal()
+ case _ => -1
+ })))
+ nbt.setBooleanArray("nodePresence", (0 until te.getContainerSize).flatMap(slot => te.getMountable(slot) match {
+ case mountable: RackMountable => (Seq(true) ++ (0 until math.min(MaxConnections - 1, mountable.getConnectableCount)).map(index => mountable.getConnectableAt(index) != null)).padTo(MaxConnections, false)
+ case _ => Array.fill(MaxConnections)(false)
+ }).toArray)
+ nbt.putBoolean("isRelayEnabled", te.isRelayEnabled)
+ }
+ case _ =>
+ }
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Raid.scala b/src/main/scala/li/cil/oc/common/container/Raid.scala
index 6774008d7e..06e356f71d 100644
--- a/src/main/scala/li/cil/oc/common/container/Raid.scala
+++ b/src/main/scala/li/cil/oc/common/container/Raid.scala
@@ -3,9 +3,15 @@ package li.cil.oc.common.container
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+
+class Raid(selfType: ContainerType[_ <: Raid], id: Int, playerInventory: PlayerInventory, raid: IInventory)
+ extends Player(selfType, id, playerInventory, raid) {
+
+ override protected def getHostClass = classOf[tileentity.Raid]
-class Raid(playerInventory: InventoryPlayer, raid: tileentity.Raid) extends Player(playerInventory, raid) {
addSlotToContainer(60, 23, Slot.HDD, Tier.Three)
addSlotToContainer(80, 23, Slot.HDD, Tier.Three)
addSlotToContainer(100, 23, Slot.HDD, Tier.Three)
diff --git a/src/main/scala/li/cil/oc/common/container/Relay.scala b/src/main/scala/li/cil/oc/common/container/Relay.scala
index d9ee4a54f9..277718d2dd 100644
--- a/src/main/scala/li/cil/oc/common/container/Relay.scala
+++ b/src/main/scala/li/cil/oc/common/container/Relay.scala
@@ -1,33 +1,59 @@
package li.cil.oc.common.container
+import li.cil.oc.Constants
+import li.cil.oc.api
+import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.common.Slot
+import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.item.ItemStack
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.nbt.CompoundNBT
+
+class Relay(selfType: ContainerType[_ <: Relay], id: Int, playerInventory: PlayerInventory, relay: IInventory)
+ extends Player(selfType, id, playerInventory, relay) {
+
+ lazy final val WirelessNetworkCardTier1: ItemInfo = api.Items.get(Constants.ItemName.WirelessNetworkCardTier1)
+ lazy final val WirelessNetworkCardTier2: ItemInfo = api.Items.get(Constants.ItemName.WirelessNetworkCardTier2)
+ lazy final val LinkedCard: ItemInfo = api.Items.get(Constants.ItemName.LinkedCard)
+
+ override protected def getHostClass = classOf[tileentity.Relay]
-class Relay(playerInventory: InventoryPlayer, relay: tileentity.Relay) extends Player(playerInventory, relay) {
addSlotToContainer(151, 15, Slot.CPU)
addSlotToContainer(151, 34, Slot.Memory)
addSlotToContainer(151, 53, Slot.HDD)
- addSlotToContainer(178, 15, Slot.Card)
+ addSlot(new StaticComponentSlot(this, otherInventory, slots.size, 178, 15, getHostClass, Slot.Card, Tier.Any) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (api.Items.get(stack) != WirelessNetworkCardTier1 && api.Items.get(stack) != WirelessNetworkCardTier2 &&
+ api.Items.get(stack) != LinkedCard) return false
+ super.mayPlace(stack)
+ }
+ })
addPlayerInventorySlots(8, 84)
- def relayDelay = synchronizedData.getInteger("relayDelay")
+ def relayDelay = synchronizedData.getInt("relayDelay")
- def relayAmount = synchronizedData.getInteger("relayAmount")
+ def relayAmount = synchronizedData.getInt("relayAmount")
- def maxQueueSize = synchronizedData.getInteger("maxQueueSize")
+ def maxQueueSize = synchronizedData.getInt("maxQueueSize")
- def packetsPerCycleAvg = synchronizedData.getInteger("packetsPerCycleAvg")
+ def packetsPerCycleAvg = synchronizedData.getInt("packetsPerCycleAvg")
- def queueSize = synchronizedData.getInteger("queueSize")
+ def queueSize = synchronizedData.getInt("queueSize")
- override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
- synchronizedData.setInteger("relayDelay", relay.relayDelay)
- synchronizedData.setInteger("relayAmount", relay.relayAmount)
- synchronizedData.setInteger("maxQueueSize", relay.maxQueueSize)
- synchronizedData.setInteger("packetsPerCycleAvg", relay.packetsPerCycleAvg())
- synchronizedData.setInteger("queueSize", relay.queue.size)
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
+ relay match {
+ case te: tileentity.Relay => {
+ synchronizedData.putInt("relayDelay", te.relayDelay)
+ synchronizedData.putInt("relayAmount", te.relayAmount)
+ synchronizedData.putInt("maxQueueSize", te.maxQueueSize)
+ synchronizedData.putInt("packetsPerCycleAvg", te.packetsPerCycleAvg())
+ synchronizedData.putInt("queueSize", te.queue.size)
+ }
+ case _ =>
+ }
super.detectCustomDataChanges(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Robot.scala b/src/main/scala/li/cil/oc/common/container/Robot.scala
index 4d73cb09a7..7bab9f8c50 100644
--- a/src/main/scala/li/cil/oc/common/container/Robot.scala
+++ b/src/main/scala/li/cil/oc/common/container/Robot.scala
@@ -3,39 +3,115 @@ package li.cil.oc.common.container
import li.cil.oc.api
import li.cil.oc.client.Textures
import li.cil.oc.common
+import li.cil.oc.common.ComponentTracker
import li.cil.oc.common.tileentity
+import li.cil.oc.integration.opencomputers.DriverKeyboard
+import li.cil.oc.integration.opencomputers.DriverScreen
import li.cil.oc.util.SideTracker
-import net.minecraft.entity.player.InventoryPlayer
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
import net.minecraft.item.ItemStack
+import net.minecraft.network.PacketBuffer
+import net.minecraft.world.World
+import net.minecraft.util.IntReferenceHolder
import net.minecraft.util.ResourceLocation
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends Player(playerInventory, robot) {
- val hasScreen: Boolean = robot.components.exists {
- case Some(buffer: api.internal.TextBuffer) => true
- case _ => false
+object RobotInfo {
+ def getScreenBuffer(robot: tileentity.Robot): Option[String] = robot.components.collectFirst {
+ case Some(buffer: api.internal.TextBuffer) if buffer.node != null => buffer.node.address
}
+
+ def hasKeyboard(robot: tileentity.Robot) = robot.info.components.map(api.Driver.driverFor(_, robot.getClass)).contains(DriverKeyboard)
+
+ def readRobotInfo(buff: PacketBuffer): RobotInfo = {
+ val mainInvSize = buff.readVarInt()
+ val slot1 = buff.readUtf(32)
+ val tier1 = buff.readVarInt()
+ val slot2 = buff.readUtf(32)
+ val tier2 = buff.readVarInt()
+ val slot3 = buff.readUtf(32)
+ val tier3 = buff.readVarInt()
+ val screenBuffer = buff.readBoolean() match {
+ case true => Some(buff.readUtf())
+ case false => None
+ }
+ val hasKeyboard = buff.readBoolean()
+ new RobotInfo(mainInvSize, slot1, tier1, slot2, tier2, slot3, tier3, screenBuffer, hasKeyboard)
+ }
+
+ def writeRobotInfo(buff: PacketBuffer, info: RobotInfo) {
+ buff.writeVarInt(info.mainInvSize)
+ buff.writeUtf(info.slot1, 32)
+ buff.writeVarInt(info.tier1)
+ buff.writeUtf(info.slot2, 32)
+ buff.writeVarInt(info.tier2)
+ buff.writeUtf(info.slot3, 32)
+ buff.writeVarInt(info.tier3)
+ info.screenBuffer match {
+ case Some(addr) => {
+ buff.writeBoolean(true)
+ buff.writeUtf(addr)
+ }
+ case _ => buff.writeBoolean(false)
+ }
+ buff.writeBoolean(info.hasKeyboard)
+ }
+}
+
+class RobotInfo(val mainInvSize: Int, val slot1: String, val tier1: Int,
+ val slot2: String, val tier2: Int, val slot3: String, val tier3: Int,
+ val screenBuffer: Option[String], val hasKeyboard: Boolean) {
+
+ def this(robot: tileentity.Robot) = this(robot.mainInventory.getContainerSize, robot.containerSlotType(1), robot.containerSlotTier(1),
+ robot.containerSlotType(2), robot.containerSlotTier(2), robot.containerSlotType(3), robot.containerSlotTier(3),
+ RobotInfo.getScreenBuffer(robot), RobotInfo.hasKeyboard(robot))
+}
+
+class Robot(selfType: ContainerType[_ <: Robot], id: Int, playerInventory: PlayerInventory, robot: IInventory, val info: RobotInfo)
+ extends Player(selfType, id, playerInventory, robot) {
+
private val withScreenHeight = 256
private val noScreenHeight = 108
- val deltaY: Int = if (hasScreen) 0 else withScreenHeight - noScreenHeight
+ val deltaY: Int = if (info.screenBuffer.isDefined) 0 else withScreenHeight - noScreenHeight
+
+ override protected def getHostClass = classOf[tileentity.Robot]
addSlotToContainer(170 + 0 * slotSize, 232 - deltaY, common.Slot.Tool)
- addSlotToContainer(170 + 1 * slotSize, 232 - deltaY, robot.containerSlotType(1), robot.containerSlotTier(1))
- addSlotToContainer(170 + 2 * slotSize, 232 - deltaY, robot.containerSlotType(2), robot.containerSlotTier(2))
- addSlotToContainer(170 + 3 * slotSize, 232 - deltaY, robot.containerSlotType(3), robot.containerSlotTier(3))
-
- for (i <- 0 to 3) {
- val y = 156 + i * slotSize - deltaY
- for (j <- 0 to 3) {
- val x = 170 + j * slotSize
- addSlotToContainer(new InventorySlot(this, otherInventory, inventorySlots.size, x, y))
- }
+ addSpecialSlot(170 + 1 * slotSize, 232 - deltaY, info.slot1, info.tier1)
+ addSpecialSlot(170 + 2 * slotSize, 232 - deltaY, info.slot2, info.tier2)
+ addSpecialSlot(170 + 3 * slotSize, 232 - deltaY, info.slot3, info.tier3)
+
+ // Like addSlotToContainer, but handles the very special, much edge case with screen & keyboard.
+ def addSpecialSlot(x: Int, y: Int, slot: String, tier: Int) {
+ val index = slots.size
+ addSlot(new StaticComponentSlot(this, otherInventory, index, x, y, getHostClass, slot, tier) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (DriverScreen.worksWith(stack, getHostClass)) return false
+ if (DriverKeyboard.worksWith(stack, getHostClass)) return false
+ super.mayPlace(stack)
+ }
+ })
}
- for (i <- 16 until 64) {
- addSlotToContainer(new InventorySlot(this, otherInventory, inventorySlots.size, -10000, -10000))
+
+ // Slot.x and Slot.y are final, so have to rebuild when scrolling
+ def generateSlotsFor(scroll: Int) {
+ val maxRows = math.max(info.mainInvSize / 4, 4)
+ for (i <- 0 until maxRows) {
+ val y = 156 + (i - scroll) * slotSize - deltaY
+ for (j <- 0 to 3) {
+ val x = 170 + j * slotSize
+ val idx = 4 + j + 4 * i
+ val slot = new InventorySlot(this, otherInventory, idx, x, y, i >= scroll && i < scroll + 4)
+ slot.index = idx
+ if (slots.size() <= idx) addSlot(slot)
+ else slots.set(idx, slot)
+ }
+ }
}
+ generateSlotsFor(0)
addPlayerInventorySlots(6, 174 - deltaY)
@@ -44,51 +120,69 @@ class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends P
// values as shorts over the net (for whatever reason).
private val factor = 100
- private var lastSentBuffer = -1
+ private val globalBufferData = robot match {
+ case te: tileentity.Robot => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = te.globalBuffer.toInt / factor
- private var lastSentBufferSize = -1
+ override def set(value: Int): Unit = te.globalBuffer = value * factor
+ })
+ }
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def globalBuffer = globalBufferData.get * factor
- @SideOnly(Side.CLIENT)
- override def updateProgressBar(id: Int, value: Int) {
- super.updateProgressBar(id, value)
- if (id == 0) {
- robot.globalBuffer = value * factor
+ private val globalBufferSizeData = robot match {
+ case te: tileentity.Robot => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = te.globalBufferSize.toInt / factor
+
+ override def set(value: Int): Unit = te.globalBufferSize = value * factor
+ })
}
+ case _ => addDataSlot(IntReferenceHolder.standalone)
+ }
+ def globalBufferSize = globalBufferSizeData.get * factor
+
+ private val runningData = robot match {
+ case te: tileentity.Robot => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = if (te.isRunning) 1 else 0
- if (id == 1) {
- robot.globalBufferSize = value * factor
+ override def set(value: Int): Unit = te.setRunning(value != 0)
+ })
}
+ case _ => addDataSlot(IntReferenceHolder.standalone)
}
+ def isRunning = runningData.get != 0
- override def detectAndSendChanges() {
- super.detectAndSendChanges()
- if (SideTracker.isServer) {
- val currentBuffer = robot.globalBuffer.toInt / factor
- if (currentBuffer != lastSentBuffer) {
- lastSentBuffer = currentBuffer
- sendWindowProperty(0, lastSentBuffer)
- }
+ private val selectedSlotData = robot match {
+ case te: tileentity.Robot => {
+ addDataSlot(new IntReferenceHolder {
+ override def get(): Int = te.selectedSlot
- val currentBufferSize = robot.globalBufferSize.toInt / factor
- if (currentBufferSize != lastSentBufferSize) {
- lastSentBufferSize = currentBufferSize
- sendWindowProperty(1, lastSentBufferSize)
- }
+ override def set(value: Int): Unit = te.setSelectedSlot(value)
+ })
}
+ case _ => addDataSlot(IntReferenceHolder.standalone)
}
+ def selectedSlot = selectedSlotData.get
+
+ class InventorySlot(container: Player, inventory: IInventory, index: Int, x: Int, y: Int, enabled: Boolean)
+ extends StaticComponentSlot(container, inventory, index, x, y, getHostClass, common.Slot.Any, common.Tier.Any) {
- class InventorySlot(container: Player, inventory: IInventory, index: Int, x: Int, y: Int) extends StaticComponentSlot(container, inventory, index, x, y, common.Slot.Any, common.Tier.Any) {
- def isValid: Boolean = robot.isInventorySlot(getSlotIndex)
+ def isValid: Boolean = getSlotIndex >= 4 && getSlotIndex < 4 + info.mainInvSize
- @SideOnly(Side.CLIENT) override
- def isEnabled: Boolean = isValid && super.isEnabled
+ @OnlyIn(Dist.CLIENT) override
+ def isActive: Boolean = enabled && isValid && super.isActive
+ @OnlyIn(Dist.CLIENT)
override def getBackgroundLocation: ResourceLocation =
if (isValid) super.getBackgroundLocation
else Textures.Icons.get(common.Tier.None)
- override def getStack: ItemStack = {
- if (isValid) super.getStack
+ override def getItem: ItemStack = {
+ if (isValid) super.getItem
else ItemStack.EMPTY
}
}
diff --git a/src/main/scala/li/cil/oc/common/container/Server.scala b/src/main/scala/li/cil/oc/common/container/Server.scala
index 19700b379f..27d2826e35 100644
--- a/src/main/scala/li/cil/oc/common/container/Server.scala
+++ b/src/main/scala/li/cil/oc/common/container/Server.scala
@@ -3,64 +3,73 @@ package li.cil.oc.common.container
import li.cil.oc.common.InventorySlots
import li.cil.oc.common.inventory.ServerInventory
import li.cil.oc.server.component
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.InventoryPlayer
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.CompoundNBT
+
+class Server(selfType: ContainerType[_ <: Server], id: Int, playerInventory: PlayerInventory, val stack: ItemStack, serverInventory: IInventory, tier: Int, val rackSlot: Int)
+ extends Player(selfType, id, playerInventory, serverInventory) {
+
+ override protected def getHostClass = classOf[component.Server]
-class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory, val server: Option[component.Server] = None) extends Player(playerInventory, serverInventory) {
for (i <- 0 to 1) {
- val slot = InventorySlots.server(serverInventory.tier)(getInventory.size)
+ val slot = InventorySlots.server(tier)(slots.size)
addSlotToContainer(76, 7 + i * slotSize, slot.slot, slot.tier)
}
- val verticalSlots = math.min(3, 1 + serverInventory.tier)
+ val verticalSlots = math.min(3, 1 + tier)
for (i <- 0 to verticalSlots) {
- val slot = InventorySlots.server(serverInventory.tier)(getInventory.size)
+ val slot = InventorySlots.server(tier)(slots.size)
addSlotToContainer(100, 7 + i * slotSize, slot.slot, slot.tier)
}
for (i <- 0 to verticalSlots) {
- val slot = InventorySlots.server(serverInventory.tier)(getInventory.size)
+ val slot = InventorySlots.server(tier)(slots.size)
addSlotToContainer(124, 7 + i * slotSize, slot.slot, slot.tier)
}
for (i <- 0 to verticalSlots) {
- val slot = InventorySlots.server(serverInventory.tier)(getInventory.size)
+ val slot = InventorySlots.server(tier)(slots.size)
addSlotToContainer(148, 7 + i * slotSize, slot.slot, slot.tier)
}
for (i <- 2 to verticalSlots) {
- val slot = InventorySlots.server(serverInventory.tier)(getInventory.size)
+ val slot = InventorySlots.server(tier)(slots.size)
addSlotToContainer(76, 7 + i * slotSize, slot.slot, slot.tier)
}
{
- val slot = InventorySlots.server(serverInventory.tier)(getInventory.size)
+ val slot = InventorySlots.server(tier)(slots.size)
addSlotToContainer(26, 34, slot.slot, slot.tier)
}
// Show the player's inventory.
addPlayerInventorySlots(8, 84)
- override def canInteractWith(player: EntityPlayer) = {
- if (server.isDefined) super.canInteractWith(player)
- else player == playerInventory.player
+ override def stillValid(player: PlayerEntity) = {
+ otherInventory match {
+ case _: component.Server => super.stillValid(player)
+ case _ => player == playerInventory.player
+ }
}
var isRunning = false
var isItem = true
- override def updateCustomData(nbt: NBTTagCompound): Unit = {
+ override def updateCustomData(nbt: CompoundNBT): Unit = {
super.updateCustomData(nbt)
isRunning = nbt.getBoolean("isRunning")
isItem = nbt.getBoolean("isItem")
}
- override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
+ override protected def detectCustomDataChanges(nbt: CompoundNBT): Unit = {
super.detectCustomDataChanges(nbt)
- server match {
- case Some(s) => nbt.setBoolean("isRunning", s.machine.isRunning)
- case _ => nbt.setBoolean("isItem", true)
+ otherInventory match {
+ case s: component.Server => nbt.putBoolean("isRunning", s.machine.isRunning)
+ case _ => nbt.putBoolean("isItem", true)
}
}
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala
index 412c6dabed..d9180fe6cb 100644
--- a/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala
+++ b/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala
@@ -1,19 +1,25 @@
package li.cil.oc.common.container
+import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.client.Textures
import li.cil.oc.common
import net.minecraft.inventory.IInventory
+import net.minecraft.util.ResourceLocation
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-class StaticComponentSlot(val container: Player, inventory: IInventory, index: Int, x: Int, y: Int, val slot: String, val tier: Int) extends ComponentSlot(inventory, index, x, y) {
- if (container.playerInventory.player.getEntityWorld.isRemote) {
- setBackgroundLocation(Textures.Icons.get(slot))
- }
+class StaticComponentSlot(val agentContainer: Player, inventory: IInventory, index: Int, x: Int, y: Int, host: Class[_ <: EnvironmentHost], val slot: String, val tier: Int)
+ extends ComponentSlot(inventory, index, x, y, host) {
- val tierIcon = Textures.Icons.get(tier)
+ @OnlyIn(Dist.CLIENT)
+ def tierIcon = Textures.Icons.get(tier)
- override def getSlotStackLimit =
+ @OnlyIn(Dist.CLIENT)
+ override def getBackgroundLocation: ResourceLocation = Textures.Icons.get(slot)
+
+ override def getMaxStackSize =
slot match {
- case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getSlotStackLimit
+ case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getMaxStackSize
case common.Slot.None => 0
case _ => 1
}
diff --git a/src/main/scala/li/cil/oc/common/container/Tablet.scala b/src/main/scala/li/cil/oc/common/container/Tablet.scala
index 5e84bd3479..f00ff4ff80 100644
--- a/src/main/scala/li/cil/oc/common/container/Tablet.scala
+++ b/src/main/scala/li/cil/oc/common/container/Tablet.scala
@@ -1,13 +1,26 @@
package li.cil.oc.common.container
import li.cil.oc.common.item.TabletWrapper
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.InventoryPlayer
+import li.cil.oc.integration.opencomputers.DriverScreen
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.ContainerType
+import net.minecraft.item.ItemStack
-class Tablet(playerInventory: InventoryPlayer, tablet: TabletWrapper) extends Player(playerInventory, tablet) {
- addSlotToContainer(new StaticComponentSlot(this, otherInventory, otherInventory.getSizeInventory - 1, 80, 35, tablet.containerSlotType, tablet.containerSlotTier))
+class Tablet(selfType: ContainerType[_ <: Tablet], id: Int, playerInventory: PlayerInventory, val stack: ItemStack, tablet: IInventory, slot1: String, tier1: Int)
+ extends Player(selfType, id, playerInventory, tablet) {
+
+ override protected def getHostClass = classOf[TabletWrapper]
+
+ addSlot(new StaticComponentSlot(this, otherInventory, otherInventory.getContainerSize - 1, 80, 35, getHostClass, slot1, tier1) {
+ override def mayPlace(stack: ItemStack): Boolean = {
+ if (DriverScreen.worksWith(stack, getHostClass)) return false
+ super.mayPlace(stack)
+ }
+ })
addPlayerInventorySlots(8, 84)
- override def canInteractWith(player: EntityPlayer) = player == playerInventory.player
+ override def stillValid(player: PlayerEntity) = player == playerInventory.player
}
diff --git a/src/main/scala/li/cil/oc/common/entity/Drone.scala b/src/main/scala/li/cil/oc/common/entity/Drone.scala
index 552fbd817d..b2ccae8634 100644
--- a/src/main/scala/li/cil/oc/common/entity/Drone.scala
+++ b/src/main/scala/li/cil/oc/common/entity/Drone.scala
@@ -19,7 +19,8 @@ import li.cil.oc.api.machine.Context
import li.cil.oc.api.machine.MachineHost
import li.cil.oc.api.network._
import li.cil.oc.common.EventHandler
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.inventory.Inventory
import li.cil.oc.common.item.data.DroneData
@@ -30,45 +31,62 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils
-import net.minecraft.block.Block
+import net.minecraft.block.BlockState
import net.minecraft.block.material.Material
import net.minecraft.entity.Entity
+import net.minecraft.entity.EntitySize
+import net.minecraft.entity.EntityType
import net.minecraft.entity.MoverType
-import net.minecraft.entity.item.EntityItem
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.Pose
+import net.minecraft.entity.item.ItemEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.network.datasync.DataParameter
import net.minecraft.network.datasync.DataSerializers
import net.minecraft.network.datasync.EntityDataManager
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.tags.FluidTags
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.Vec3d
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import net.minecraftforge.fluids.IFluidTank
+import net.minecraftforge.fml.network.NetworkHooks
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
object Drone {
- val DataRunning: DataParameter[lang.Boolean] = EntityDataManager.createKey(classOf[Drone], DataSerializers.BOOLEAN)
- val DataTargetX: DataParameter[lang.Float] = EntityDataManager.createKey(classOf[Drone], DataSerializers.FLOAT)
- val DataTargetY: DataParameter[lang.Float] = EntityDataManager.createKey(classOf[Drone], DataSerializers.FLOAT)
- val DataTargetZ: DataParameter[lang.Float] = EntityDataManager.createKey(classOf[Drone], DataSerializers.FLOAT)
- val DataMaxAcceleration: DataParameter[lang.Float] = EntityDataManager.createKey(classOf[Drone], DataSerializers.FLOAT)
- val DataSelectedSlot: DataParameter[Integer] = EntityDataManager.createKey(classOf[Drone], DataSerializers.VARINT)
- val DataCurrentEnergy: DataParameter[Integer] = EntityDataManager.createKey(classOf[Drone], DataSerializers.VARINT)
- val DataMaxEnergy: DataParameter[Integer] = EntityDataManager.createKey(classOf[Drone], DataSerializers.VARINT)
- val DataStatusText: DataParameter[String] = EntityDataManager.createKey(classOf[Drone], DataSerializers.STRING)
- val DataInventorySize: DataParameter[Integer] = EntityDataManager.createKey(classOf[Drone], DataSerializers.VARINT)
- val DataLightColor: DataParameter[Integer] = EntityDataManager.createKey(classOf[Drone], DataSerializers.VARINT)
+ val DataRunning: DataParameter[lang.Boolean] = EntityDataManager.defineId(classOf[Drone], DataSerializers.BOOLEAN)
+ val DataTargetX: DataParameter[lang.Float] = EntityDataManager.defineId(classOf[Drone], DataSerializers.FLOAT)
+ val DataTargetY: DataParameter[lang.Float] = EntityDataManager.defineId(classOf[Drone], DataSerializers.FLOAT)
+ val DataTargetZ: DataParameter[lang.Float] = EntityDataManager.defineId(classOf[Drone], DataSerializers.FLOAT)
+ val DataMaxAcceleration: DataParameter[lang.Float] = EntityDataManager.defineId(classOf[Drone], DataSerializers.FLOAT)
+ val DataSelectedSlot: DataParameter[Integer] = EntityDataManager.defineId(classOf[Drone], DataSerializers.INT)
+ val DataCurrentEnergy: DataParameter[Integer] = EntityDataManager.defineId(classOf[Drone], DataSerializers.INT)
+ val DataMaxEnergy: DataParameter[Integer] = EntityDataManager.defineId(classOf[Drone], DataSerializers.INT)
+ val DataStatusText: DataParameter[String] = EntityDataManager.defineId(classOf[Drone], DataSerializers.STRING)
+ val DataInventorySize: DataParameter[Integer] = EntityDataManager.defineId(classOf[Drone], DataSerializers.INT)
+ val DataLightColor: DataParameter[Integer] = EntityDataManager.defineId(classOf[Drone], DataSerializers.INT)
}
+abstract class DroneInventory(val drone: Drone) extends Inventory
+
// internal.Rotatable is also in internal.Drone, but it wasn't since the start
// so this is to ensure it is implemented here, in the very unlikely case that
// someone decides to ship that specific version of the API.
-class Drone(world: World) extends Entity(world) with MachineHost with internal.Drone with internal.Rotatable with Analyzable with Context {
- override def world: World = getEntityWorld
+class Drone(selfType: EntityType[Drone], world: World) extends Entity(selfType, world) with MachineHost with internal.Drone with internal.Rotatable with Analyzable with Context {
+ override def world: World = level
// Some basic constants.
val gravity = 0.05f
@@ -77,8 +95,6 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
val maxAcceleration = 0.1f
val maxVelocity = 0.4f
val maxInventorySize = 8
- setSize(12 / 16f, 6 / 16f)
- isImmuneToFire = true
// Rendering stuff, purely eyecandy.
val targetFlapAngles: Array[Array[Float]] = Array.fill(4, 2)(0f)
@@ -91,24 +107,24 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
// Logic stuff, components, machine and such.
val info = new DroneData()
- val machine: api.machine.Machine = if (!world.isRemote) {
+ val machine: api.machine.Machine = if (!world.isClientSide) {
val m = Machine.create(this)
m.node.asInstanceOf[Connector].setLocalBufferSize(0)
m
} else null
- val control: component.Drone = if (!world.isRemote) new component.Drone(this) else null
+ val control: component.Drone = if (!world.isClientSide) new component.Drone(this) else null
val components = new ComponentInventory {
override def host: Drone = Drone.this
override def items: Array[ItemStack] = info.components
- override def getSizeInventory: Int = info.components.length
+ override def getContainerSize: Int = info.components.length
- override def markDirty() {}
+ override def setChanged() {}
- override def isItemValidForSlot(slot: Int, stack: ItemStack) = true
+ override def canPlaceItem(slot: Int, stack: ItemStack) = true
- override def isUsableByPlayer(player: EntityPlayer) = true
+ override def stillValid(player: PlayerEntity) = true
override def node: Node = Option(machine).map(_.node).orNull
@@ -121,28 +137,28 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
val equipmentInventory = new Inventory {
val items = Array.empty[ItemStack]
- override def getSizeInventory = 0
+ override def getContainerSize = 0
- override def getInventoryStackLimit = 0
+ override def getMaxStackSize = 0
- override def markDirty(): Unit = {}
+ override def setChanged(): Unit = {}
- override def isItemValidForSlot(slot: Int, stack: ItemStack) = false
+ override def canPlaceItem(slot: Int, stack: ItemStack) = false
- override def isUsableByPlayer(player: EntityPlayer) = false
+ override def stillValid(player: PlayerEntity) = false
}
- val mainInventory = new Inventory {
+ val mainInventory = new DroneInventory(this) {
val items: Array[ItemStack] = Array.fill[ItemStack](8)(ItemStack.EMPTY)
- override def getSizeInventory: Int = inventorySize
+ override def getContainerSize: Int = inventorySize
- override def getInventoryStackLimit = 64
+ override def getMaxStackSize = 64
- override def markDirty() {} // TODO update client GUI?
+ override def setChanged() {} // TODO update client GUI?
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = slot >= 0 && slot < getSizeInventory
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = slot >= 0 && slot < getContainerSize
- override def isUsableByPlayer(player: EntityPlayer): Boolean = player.getDistanceSq(Drone.this) < 64
+ override def stillValid(player: PlayerEntity): Boolean = player.distanceToSqr(drone) < 64
}
val tank = new MultiTank {
override def tankCount: Int = components.components.count {
@@ -160,9 +176,9 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
override def tier: Int = info.tier
- override def player(): EntityPlayer = {
+ override def player(): PlayerEntity = {
agent.Player.updatePositionAndRotation(player_, facing, facing)
- agent.Player.setInventoryPlayerItems(player_)
+ agent.Player.setPlayerInventoryItems(player_)
player_
}
@@ -187,7 +203,7 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
override def isPaused: Boolean = machine.isPaused
override def start(): Boolean = {
- if (world.isRemote || machine.isRunning) {
+ if (world.isClientSide || machine.isRunning) {
return false
}
preparePowerUp()
@@ -204,43 +220,47 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
// ----------------------------------------------------------------------- //
- override def getTarget = new Vec3d(targetX.floatValue(), targetY.floatValue(), targetZ.floatValue())
+ override def getTarget = new Vector3d(targetX.floatValue(), targetY.floatValue(), targetZ.floatValue())
- override def setTarget(value: Vec3d): Unit = {
+ override def setTarget(value: Vector3d): Unit = {
targetX = value.x.toFloat
targetY = value.y.toFloat
targetZ = value.z.toFloat
}
- override def getVelocity = new Vec3d(motionX, motionY, motionZ)
+ override def getVelocity = getDeltaMovement
// ----------------------------------------------------------------------- //
- override def canBeCollidedWith = true
+ override def isPickable = true
- override def canBePushed = true
+ override def isPushable = true
// ----------------------------------------------------------------------- //
- override def xPosition: Double = posX
+ override def xPosition: Double = getX
- override def yPosition: Double = posY
+ override def yPosition: Double = getY
- override def zPosition: Double = posZ
+ override def zPosition: Double = getZ
override def markChanged() {}
+ @OnlyIn(Dist.CLIENT)
+ override def getRopeHoldPosition(dt: Float): Vector3d =
+ getPosition(dt).add(0.0, -0.056, 0.0) // Offset: height * 0.85 * 0.7 - 0.25
+
// ----------------------------------------------------------------------- //
- override def facing = EnumFacing.SOUTH
+ override def facing = Direction.SOUTH
- override def toLocal(value: EnumFacing): EnumFacing = value
+ override def toLocal(value: Direction): Direction = value
- override def toGlobal(value: EnumFacing): EnumFacing = value
+ override def toGlobal(value: Direction): Direction = value
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(machine.node)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(machine.node)
// ----------------------------------------------------------------------- //
@@ -262,32 +282,32 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
// ----------------------------------------------------------------------- //
- override def entityInit() {
- getDataManager.register(Drone.DataRunning, java.lang.Boolean.FALSE)
- getDataManager.register(Drone.DataTargetX, Float.box(0f))
- getDataManager.register(Drone.DataTargetY, Float.box(0f))
- getDataManager.register(Drone.DataTargetZ, Float.box(0f))
- getDataManager.register(Drone.DataMaxAcceleration, Float.box(0f))
- getDataManager.register(Drone.DataSelectedSlot, Int.box(0))
- getDataManager.register(Drone.DataCurrentEnergy, Int.box(0))
- getDataManager.register(Drone.DataMaxEnergy, Int.box(100))
- getDataManager.register(Drone.DataStatusText, "")
- getDataManager.register(Drone.DataInventorySize, Int.box(0))
- getDataManager.register(Drone.DataLightColor, Int.box(0x66DD55))
+ override def defineSynchedData() {
+ entityData.define(Drone.DataRunning, java.lang.Boolean.FALSE)
+ entityData.define(Drone.DataTargetX, Float.box(0f))
+ entityData.define(Drone.DataTargetY, Float.box(0f))
+ entityData.define(Drone.DataTargetZ, Float.box(0f))
+ entityData.define(Drone.DataMaxAcceleration, Float.box(0f))
+ entityData.define(Drone.DataSelectedSlot, Int.box(0))
+ entityData.define(Drone.DataCurrentEnergy, Int.box(0))
+ entityData.define(Drone.DataMaxEnergy, Int.box(100))
+ entityData.define(Drone.DataStatusText, "")
+ entityData.define(Drone.DataInventorySize, Int.box(0))
+ entityData.define(Drone.DataLightColor, Int.box(0x66DD55))
}
- def initializeAfterPlacement(stack: ItemStack, player: EntityPlayer, position: Vec3d) {
- info.load(stack)
+ def initializeAfterPlacement(stack: ItemStack, player: PlayerEntity, position: Vector3d) {
+ info.loadData(stack)
control.node.changeBuffer(info.storedEnergy - control.node.localBuffer)
wireThingsTogether()
inventorySize = computeInventorySize()
- setPosition(position.x, position.y, position.z)
+ setPos(position.x, position.y, position.z)
}
def preparePowerUp() {
- targetX = math.floor(posX).toFloat + 0.5f
- targetY = math.round(posY).toFloat + 0.5f
- targetZ = math.floor(posZ).toFloat + 0.5f
+ targetX = math.floor(getX).toFloat + 0.5f
+ targetY = math.round(getY).toFloat + 0.5f
+ targetZ = math.floor(getZ).toFloat + 0.5f
targetAcceleration = maxAcceleration
wireThingsTogether()
@@ -300,57 +320,57 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
components.connectComponents()
}
- def isRunning: Boolean = getDataManager.get(Drone.DataRunning)
+ def isRunning: Boolean = entityData.get(Drone.DataRunning)
- def targetX: lang.Float = getDataManager.get(Drone.DataTargetX)
+ def targetX: lang.Float = entityData.get(Drone.DataTargetX)
- def targetY: lang.Float = getDataManager.get(Drone.DataTargetY)
+ def targetY: lang.Float = entityData.get(Drone.DataTargetY)
- def targetZ: lang.Float = getDataManager.get(Drone.DataTargetZ)
+ def targetZ: lang.Float = entityData.get(Drone.DataTargetZ)
- def targetAcceleration: lang.Float = getDataManager.get(Drone.DataMaxAcceleration)
+ def targetAcceleration: lang.Float = entityData.get(Drone.DataMaxAcceleration)
- def selectedSlot: Int = getDataManager.get(Drone.DataSelectedSlot) & 0xFF
+ def selectedSlot: Int = entityData.get(Drone.DataSelectedSlot) & 0xFF
- def globalBuffer: Integer = getDataManager.get(Drone.DataCurrentEnergy)
+ def globalBuffer: Integer = entityData.get(Drone.DataCurrentEnergy)
- def globalBufferSize: Integer = getDataManager.get(Drone.DataMaxEnergy)
+ def globalBufferSize: Integer = entityData.get(Drone.DataMaxEnergy)
- def statusText: String = getDataManager.get(Drone.DataStatusText)
+ def statusText: String = entityData.get(Drone.DataStatusText)
- def inventorySize: Int = getDataManager.get(Drone.DataInventorySize) & 0xFF
+ def inventorySize: Int = entityData.get(Drone.DataInventorySize) & 0xFF
- def lightColor: Integer = getDataManager.get(Drone.DataLightColor)
+ def lightColor: Integer = entityData.get(Drone.DataLightColor)
- def setRunning(value: Boolean): Unit = getDataManager.set(Drone.DataRunning, Boolean.box(value))
+ def setRunning(value: Boolean): Unit = entityData.set(Drone.DataRunning, Boolean.box(value))
// Round target values to low accuracy to avoid floating point errors accumulating.
- def targetX_=(value: Float): Unit = getDataManager.set(Drone.DataTargetX, Float.box(math.round(value * 4) / 4f))
+ def targetX_=(value: Float): Unit = entityData.set(Drone.DataTargetX, Float.box(math.round(value * 4) / 4f))
- def targetY_=(value: Float): Unit = getDataManager.set(Drone.DataTargetY, Float.box(math.round(value * 4) / 4f))
+ def targetY_=(value: Float): Unit = entityData.set(Drone.DataTargetY, Float.box(math.round(value * 4) / 4f))
- def targetZ_=(value: Float): Unit = getDataManager.set(Drone.DataTargetZ, Float.box(math.round(value * 4) / 4f))
+ def targetZ_=(value: Float): Unit = entityData.set(Drone.DataTargetZ, Float.box(math.round(value * 4) / 4f))
- def targetAcceleration_=(value: Float): Unit = getDataManager.set(Drone.DataMaxAcceleration, Float.box(math.max(0, math.min(maxAcceleration, value))))
+ def targetAcceleration_=(value: Float): Unit = entityData.set(Drone.DataMaxAcceleration, Float.box(math.max(0, math.min(maxAcceleration, value))))
- def setSelectedSlot(value: Int): Unit = getDataManager.set(Drone.DataSelectedSlot, Int.box(value.toByte))
+ def setSelectedSlot(value: Int): Unit = entityData.set(Drone.DataSelectedSlot, Int.box(value.toByte))
- def globalBuffer_=(value: Int): Unit = getDataManager.set(Drone.DataCurrentEnergy, Int.box(value))
+ def globalBuffer_=(value: Int): Unit = entityData.set(Drone.DataCurrentEnergy, Int.box(value))
- def globalBufferSize_=(value: Int): Unit = getDataManager.set(Drone.DataMaxEnergy, Int.box(value))
+ def globalBufferSize_=(value: Int): Unit = entityData.set(Drone.DataMaxEnergy, Int.box(value))
- def statusText_=(value: String): Unit = getDataManager.set(Drone.DataStatusText, Option(value).fold("")(_.lines.map(_.take(10)).take(2).mkString("\n")))
+ def statusText_=(value: String): Unit = entityData.set(Drone.DataStatusText, Option(value).fold("")(_.lines.map(_.take(10)).take(2).mkString("\n")))
- def inventorySize_=(value: Int): Unit = getDataManager.set(Drone.DataInventorySize, Int.box(value.toByte))
+ def inventorySize_=(value: Int): Unit = entityData.set(Drone.DataInventorySize, Int.box(value.toByte))
- def lightColor_=(value: Int): Unit = getDataManager.set(Drone.DataLightColor, Int.box(value))
+ def lightColor_=(value: Int): Unit = entityData.set(Drone.DataLightColor, Int.box(value))
- override def setPositionAndRotationDirect(x: Double, y: Double, z: Double, yaw: Float, pitch: Float, posRotationIncrements: Int, teleport: Boolean): Unit = {
+ override def lerpTo(x: Double, y: Double, z: Double, yaw: Float, pitch: Float, posRotationIncrements: Int, teleport: Boolean): Unit = {
// Only set exact position if we're too far away from the server's
// position, otherwise keep interpolating. This removes jitter and
// is good enough for drones.
- if (!isRunning || getDistanceSq(x, y, z) > 1) {
- super.setPositionAndRotation(x, y, z, yaw, pitch)
+ if (!isRunning || distanceToSqr(x, y, z) > 1) {
+ super.absMoveTo(x, y, z, yaw, pitch)
}
else {
targetX = x.toFloat
@@ -359,11 +379,11 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
}
}
- override def onUpdate() {
- super.onUpdate()
+ override def tick() {
+ super.tick()
- if (!world.isRemote) {
- if (isInsideOfMaterial(Material.WATER) || isInsideOfMaterial(Material.LAVA)) {
+ if (!world.isClientSide) {
+ if (isInWater || isInLava) {
// We're not water-proof!
machine.stop()
}
@@ -372,7 +392,7 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
setRunning(machine.isRunning)
val buffer = math.round(machine.node.asInstanceOf[Connector].globalBuffer).toInt
- if (math.abs(lastEnergyUpdate - buffer) > 1 || world.getTotalWorldTime % 200 == 0) {
+ if (math.abs(lastEnergyUpdate - buffer) > 1 || world.getGameTime % 200 == 0) {
lastEnergyUpdate = buffer
globalBuffer = buffer
globalBufferSize = machine.node.asInstanceOf[Connector].globalBufferSize.toInt
@@ -382,7 +402,7 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
if (isRunning) {
// Client side update; occasionally update wing pitch and rotation to
// make the drones look a bit more dynamic.
- val rng = world.rand
+ val rng = world.random
nextFlapChange -= 1
nextAngularVelocityChange -= 1
@@ -417,137 +437,134 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
}
}
- prevPosX = posX
- prevPosY = posY
- prevPosZ = posZ
- noClip = pushOutOfBlocks(posX, (getEntityBoundingBox.minY + getEntityBoundingBox.maxY) / 2, posZ)
+ xo = getX
+ yo = getY
+ zo = getZ
+ noPhysics = !level.noCollision(this)
+ if (noPhysics) moveTowardsClosestSpace(getX, (getBoundingBox.minY + getBoundingBox.maxY) / 2, getZ)
if (isRunning) {
- val toTarget = new Vec3d(targetX - posX, targetY - posY, targetZ - posZ)
- val distance = toTarget.lengthVector()
- val velocity = new Vec3d(motionX, motionY, motionZ)
- if (distance > 0 && (distance > 0.005f || velocity.dotProduct(velocity) > 0.005f)) {
+ val toTarget = new Vector3d(targetX - getX, targetY - getY, targetZ - getZ)
+ val distance = toTarget.length()
+ val velocity = getDeltaMovement
+ if (distance > 0 && (distance > 0.005f || velocity.dot(velocity) > 0.005f)) {
val acceleration = math.min(targetAcceleration.floatValue(), distance) / distance
val velocityX = velocity.x + toTarget.x * acceleration
val velocityY = velocity.y + toTarget.y * acceleration
val velocityZ = velocity.z + toTarget.z * acceleration
- motionX = math.max(-maxVelocity, math.min(maxVelocity, velocityX))
- motionY = math.max(-maxVelocity, math.min(maxVelocity, velocityY))
- motionZ = math.max(-maxVelocity, math.min(maxVelocity, velocityZ))
+ setDeltaMovement(new Vector3d(math.max(-maxVelocity, math.min(maxVelocity, velocityX)),
+ math.max(-maxVelocity, math.min(maxVelocity, velocityY)),
+ math.max(-maxVelocity, math.min(maxVelocity, velocityZ))))
}
else {
- motionX = 0
- motionY = 0
- motionZ = 0
- posX = targetX.floatValue()
- posY = targetY.floatValue()
- posZ = targetZ.floatValue()
+ setDeltaMovement(Vector3d.ZERO)
+ setPos(targetX.floatValue(), targetY.floatValue(), targetZ.floatValue())
}
}
else {
// No power, free fall: engage!
- motionY -= gravity
+ setDeltaMovement(getDeltaMovement.subtract(0, gravity, 0))
}
- move(MoverType.SELF, motionX, motionY, motionZ)
+ move(MoverType.SELF, getDeltaMovement)
// Make sure we don't get infinitely faster.
if (isRunning) {
- motionX *= drag
- motionY *= drag
- motionZ *= drag
+ setDeltaMovement(getDeltaMovement.scale(drag))
}
else {
- val groundDrag = world.getBlock(BlockPosition(this: Entity).offset(EnumFacing.DOWN)).slipperiness * drag
- motionX *= groundDrag
- motionY *= drag
- motionZ *= groundDrag
- if (onGround) {
- motionY *= -0.5
- }
+ val groundDrag = world.getBlock(BlockPosition(this: Entity).offset(Direction.DOWN)).getFriction * drag
+ setDeltaMovement(getDeltaMovement.multiply(groundDrag, drag * (if (isOnGround) -0.5 else 1), groundDrag))
}
}
- override def hitByEntity(entity: Entity): Boolean = {
+ override def skipAttackInteraction(entity: Entity): Boolean = {
if (isRunning) {
- val direction = new Vec3d(entity.posX - posX, entity.posY + entity.getEyeHeight - posY, entity.posZ - posZ).normalize()
- if (!world.isRemote) {
+ val direction = new Vector3d(entity.getX - getX, entity.getY + entity.getEyeHeight - getY, entity.getZ - getZ).normalize()
+ if (!world.isClientSide) {
if (Settings.get.inputUsername)
- machine.signal("hit", Double.box(direction.x), Double.box(direction.z), Double.box(direction.y), entity.getName)
+ machine.signal("hit", Double.box(direction.x), Double.box(direction.z), Double.box(direction.y), entity.getName.getString)
else
machine.signal("hit", Double.box(direction.x), Double.box(direction.z), Double.box(direction.y))
}
- motionX = (motionX - direction.x) * 0.5f
- motionY = (motionY - direction.y) * 0.5f
- motionZ = (motionZ - direction.z) * 0.5f
+ setDeltaMovement(getDeltaMovement.subtract(direction).scale(0.5))
}
- super.hitByEntity(entity)
+ super.skipAttackInteraction(entity)
+ }
+
+ // Not implemented in Drone itself because spectators would open this via vanilla PlayerEntity.openMenu (without extra data).
+ val containerProvider = new INamedContainerProvider {
+ override def getDisplayName = StringTextComponent.EMPTY
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Drone(ContainerTypes.DRONE, id, playerInventory, mainInventory, mainInventory.getContainerSize)
}
- override def processInitialInteract(player: EntityPlayer, hand: EnumHand): Boolean = {
- if (isDead) return false
- if (player.isSneaking) {
- if (Wrench.isWrench(player.getHeldItemMainhand)) {
- if(!world.isRemote) {
+ override def interact(player: PlayerEntity, hand: Hand): ActionResultType = {
+ if (!isAlive) return ActionResultType.PASS
+ if (player.isCrouching) {
+ if (Wrench.isWrench(player.getItemInHand(Hand.MAIN_HAND))) {
+ if(!world.isClientSide) {
outOfWorld()
}
}
- else if (!world.isRemote && !machine.isRunning) {
+ else if (!world.isClientSide && !machine.isRunning) {
start()
}
}
- else if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Drone.id, world, getEntityId, 0, 0)
+ else player match {
+ case srvPlr: ServerPlayerEntity if !world.isClientSide => ContainerTypes.openDroneGui(srvPlr, this)
+ case _ =>
}
- true
+ ActionResultType.sidedSuccess(world.isClientSide)
}
// No step sounds. Except on that one day.
- override def playStepSound(pos: BlockPos, block: Block): Unit = {
- if (EventHandler.isItTime) super.playStepSound(pos, block)
+ override def playStepSound(pos: BlockPos, state: BlockState): Unit = {
+ if (EventHandler.isItTime) super.playStepSound(pos, state)
}
// ----------------------------------------------------------------------- //
private var isChangingDimension = false
- override def changeDimension(dimension: Int): Entity = {
+ override def changeDimension(dimension: ServerWorld): Entity = {
// Store relative target as target, to allow adding that in our "new self"
// (entities get re-created after changing dimension).
- targetX = (targetX - posX).toFloat
- targetY = (targetY - posY).toFloat
- targetZ = (targetZ - posZ).toFloat
+ targetX = (targetX - getX).toFloat
+ targetY = (targetY - getY).toFloat
+ targetZ = (targetZ - getZ).toFloat
try {
isChangingDimension = true
super.changeDimension(dimension)
}
finally {
isChangingDimension = false
- setDead() // Again, to actually close old machine state after copying it.
+ remove() // Again, to actually close old machine state after copying it.
}
}
- override def copyDataFromOld(entity: Entity): Unit = {
- super.copyDataFromOld(entity)
+ override def restoreFrom(entity: Entity): Unit = {
+ super.restoreFrom(entity)
// Compute relative target based on old position and update, because our
// frame of reference most certainly changed (i.e. we'll spawn at different
// coordinates than the ones we started traveling from, e.g. when porting
// to the nether it'll be oldpos / 8).
entity match {
case drone: Drone =>
- targetX = (posX + drone.targetX).toFloat
- targetY = (posY + drone.targetY).toFloat
- targetZ = (posZ + drone.targetZ).toFloat
+ targetX = (getX + drone.targetX).toFloat
+ targetY = (getY + drone.targetY).toFloat
+ targetZ = (getZ + drone.targetZ).toFloat
case _ =>
- targetX = posX.toFloat
- targetY = posY.toFloat
- targetZ = posZ.toFloat
+ targetX = getX.toFloat
+ targetY = getY.toFloat
+ targetZ = getZ.toFloat
}
}
- override def setDead() {
- super.setDead()
- if (!world.isRemote && !isChangingDimension) {
+ override def remove() {
+ super.remove()
+ if (!world.isClientSide && !isChangingDimension) {
machine.stop()
machine.node.remove()
components.disconnectComponents()
@@ -556,34 +573,31 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
}
override def outOfWorld(): Unit = {
- if (isDead) return
+ if (!isAlive) return
super.outOfWorld()
- if (!world.isRemote) {
+ if (!world.isClientSide) {
val stack = api.Items.get(Constants.ItemName.Drone).createItemStack(1)
info.storedEnergy = control.node.localBuffer.toInt
- info.save(stack)
- val entity = new EntityItem(world, posX, posY, posZ, stack)
- entity.setPickupDelay(15)
- world.spawnEntity(entity)
+ info.saveData(stack)
+ val entity = new ItemEntity(world, getX, getY, getZ, stack)
+ entity.setPickUpDelay(15)
+ world.addFreshEntity(entity)
InventoryUtils.dropAllSlots(BlockPosition(this: Entity), mainInventory)
}
}
- override def getName: String = Localization.localizeImmediately("entity.oc.Drone.name")
+ override def getName: ITextComponent = Localization.localizeLater("entity.oc.Drone.name")
- override def handleWaterMovement(): Boolean = {
- inWater = world.handleMaterialAcceleration(getEntityBoundingBox, Material.WATER, this)
- inWater
- }
+ override protected def getAddEntityPacket = NetworkHooks.getEntitySpawningPacket(this)
- override def readEntityFromNBT(nbt: NBTTagCompound) {
- info.load(nbt.getCompoundTag("info"))
+ override protected def readAdditionalSaveData(nbt: CompoundNBT) {
+ info.loadData(nbt.getCompound("info"))
inventorySize = computeInventorySize()
- if (!world.isRemote) {
- machine.load(nbt.getCompoundTag("machine"))
- control.load(nbt.getCompoundTag("control"))
- components.load(nbt.getCompoundTag("components"))
- mainInventory.load(nbt.getCompoundTag("inventory"))
+ if (!world.isClientSide) {
+ machine.loadData(nbt.getCompound("machine"))
+ control.loadData(nbt.getCompound("control"))
+ components.loadData(nbt.getCompound("components"))
+ mainInventory.loadData(nbt.getCompound("inventory"))
wireThingsTogether()
}
@@ -594,35 +608,35 @@ class Drone(world: World) extends Entity(world) with MachineHost with internal.D
setSelectedSlot(nbt.getByte("selectedSlot") & 0xFF)
setSelectedTank(nbt.getByte("selectedTank") & 0xFF)
statusText = nbt.getString("statusText")
- lightColor = nbt.getInteger("lightColor")
- if (nbt.hasKey("owner")) {
+ lightColor = nbt.getInt("lightColor")
+ if (nbt.contains("owner")) {
ownerName = nbt.getString("owner")
}
- if (nbt.hasKey("ownerUuid")) {
+ if (nbt.contains("ownerUuid")) {
ownerUUID = UUID.fromString(nbt.getString("ownerUuid"))
}
}
- override def writeEntityToNBT(nbt: NBTTagCompound) {
- if (world.isRemote) return
+ override protected def addAdditionalSaveData(nbt: CompoundNBT) {
+ if (world.isClientSide) return
components.saveComponents()
info.storedEnergy = globalBuffer.toInt
- nbt.setNewCompoundTag("info", info.save)
- if (!world.isRemote) {
- nbt.setNewCompoundTag("machine", machine.save)
- nbt.setNewCompoundTag("control", control.save)
- nbt.setNewCompoundTag("components", components.save)
- nbt.setNewCompoundTag("inventory", mainInventory.save)
+ nbt.setNewCompoundTag("info", info.saveData)
+ if (!world.isClientSide) {
+ nbt.setNewCompoundTag("machine", machine.saveData)
+ nbt.setNewCompoundTag("control", control.saveData)
+ nbt.setNewCompoundTag("components", components.saveData)
+ nbt.setNewCompoundTag("inventory", mainInventory.saveData)
}
- nbt.setFloat("targetX", targetX)
- nbt.setFloat("targetY", targetY)
- nbt.setFloat("targetZ", targetZ)
- nbt.setFloat("targetAcceleration", targetAcceleration)
- nbt.setByte("selectedSlot", selectedSlot.toByte)
- nbt.setByte("selectedTank", selectedTank.toByte)
- nbt.setString("statusText", statusText)
- nbt.setInteger("lightColor", lightColor)
- nbt.setString("owner", ownerName)
- nbt.setString("ownerUuid", ownerUUID.toString)
+ nbt.putFloat("targetX", targetX)
+ nbt.putFloat("targetY", targetY)
+ nbt.putFloat("targetZ", targetZ)
+ nbt.putFloat("targetAcceleration", targetAcceleration)
+ nbt.putByte("selectedSlot", selectedSlot.toByte)
+ nbt.putByte("selectedTank", selectedTank.toByte)
+ nbt.putString("statusText", statusText)
+ nbt.putInt("lightColor", lightColor)
+ nbt.putString("owner", ownerName)
+ nbt.putString("ownerUuid", ownerUUID.toString)
}
}
diff --git a/src/main/scala/li/cil/oc/common/entity/EntityTypes.java b/src/main/scala/li/cil/oc/common/entity/EntityTypes.java
new file mode 100644
index 0000000000..9e1a61473f
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/entity/EntityTypes.java
@@ -0,0 +1,31 @@
+package li.cil.oc.common.entity;
+
+import li.cil.oc.OpenComputers;
+import net.minecraft.entity.EntityClassification;
+import net.minecraft.entity.EntityType;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.event.RegistryEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.registries.IForgeRegistry;
+import net.minecraftforge.registries.ObjectHolder;
+
+@ObjectHolder("opencomputers")
+public final class EntityTypes {
+ public static final EntityType DRONE = null;
+
+ @SubscribeEvent
+ public static void registerEntities(RegistryEvent.Register> e) {
+ register(e.getRegistry(), "drone", EntityType.Builder.of(Drone::new, EntityClassification.MISC)
+ .sized(12 / 16f, 6 / 16f).fireImmune());
+ }
+
+ private static void register(IForgeRegistry> registry, String name, EntityType.Builder> builder) {
+ EntityType> type = builder.build(name);
+ type.setRegistryName(new ResourceLocation(OpenComputers.ID(), name));
+ registry.register(type);
+ }
+
+ private EntityTypes() {
+ throw new Error();
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala b/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala
index bdb244e210..133d0b6142 100644
--- a/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala
@@ -3,9 +3,9 @@ package li.cil.oc.common.event
import li.cil.oc.api.event.RobotPlaceInAirEvent
import li.cil.oc.api.network.Node
import li.cil.oc.server.component.UpgradeAngel
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object AngelUpgradeHandler {
@SubscribeEvent
diff --git a/src/main/scala/li/cil/oc/common/event/BlockChangeHandler.scala b/src/main/scala/li/cil/oc/common/event/BlockChangeHandler.scala
index 1e52fe2538..fa9cc65c7c 100644
--- a/src/main/scala/li/cil/oc/common/event/BlockChangeHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/BlockChangeHandler.scala
@@ -2,22 +2,22 @@ package li.cil.oc.common.event
import li.cil.oc.common.EventHandler
import li.cil.oc.util.BlockPosition
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.entity.Entity
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.SoundCategory
import net.minecraft.util.SoundEvent
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IWorldEventListener
import net.minecraft.world.World
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import scala.collection.mutable
/**
* @author Vexatos
*/
+@Deprecated
object BlockChangeHandler {
def addListener(listener: ChangeListener, coord: BlockPosition) = {
@@ -30,44 +30,8 @@ object BlockChangeHandler {
private val changeListeners = mutable.WeakHashMap.empty[ChangeListener, BlockPosition]
- @SubscribeEvent
- def onWorldLoad(e: WorldEvent.Load) {
- e.getWorld.addEventListener(new Listener(e.getWorld))
- }
-
trait ChangeListener {
def onBlockChanged()
}
- private class Listener(world: World) extends IWorldEventListener {
- override def notifyBlockUpdate(worldIn: World, pos: BlockPos, oldState: IBlockState, newState: IBlockState, flags: Int): Unit = {
- val current = BlockPosition(pos, world)
- for ((listener, coord) <- changeListeners) if (coord.equals(current)) {
- listener.onBlockChanged()
- }
- }
-
- override def spawnParticle(id: Int, ignoreRange: Boolean, p_190570_3_ : Boolean, x: Double, y: Double, z: Double, xSpeed: Double, ySpeed: Double, zSpeed: Double, parameters: Int*): Unit = {}
-
- override def playRecord(soundIn: SoundEvent, pos: BlockPos): Unit = {}
-
- override def playEvent(player: EntityPlayer, `type`: Int, blockPosIn: BlockPos, data: Int): Unit = {}
-
- override def onEntityAdded(entityIn: Entity): Unit = {}
-
- override def spawnParticle(particleID: Int, ignoreRange: Boolean, xCoord: Double, yCoord: Double, zCoord: Double, xOffset: Double, yOffset: Double, zOffset: Double, parameters: Int*): Unit = {}
-
- override def onEntityRemoved(entityIn: Entity): Unit = {}
-
- override def broadcastSound(soundID: Int, pos: BlockPos, data: Int): Unit = {}
-
- override def playSoundToAllNearExcept(player: EntityPlayer, soundIn: SoundEvent, category: SoundCategory, x: Double, y: Double, z: Double, volume: Float, pitch: Float): Unit = {}
-
- override def markBlockRangeForRenderUpdate(x1: Int, y1: Int, z1: Int, x2: Int, y2: Int, z2: Int): Unit = {}
-
- override def sendBlockBreakProgress(breakerId: Int, pos: BlockPos, progress: Int): Unit = {}
-
- override def notifyLightSet(pos: BlockPos): Unit = {}
- }
-
}
diff --git a/src/main/scala/li/cil/oc/common/event/ChunkloaderUpgradeHandler.scala b/src/main/scala/li/cil/oc/common/event/ChunkloaderUpgradeHandler.scala
index 80395e3bd8..3d81c1b139 100644
--- a/src/main/scala/li/cil/oc/common/event/ChunkloaderUpgradeHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/ChunkloaderUpgradeHandler.scala
@@ -1,6 +1,6 @@
package li.cil.oc.common.event
-import java.util
+import java.util.UUID
import li.cil.oc.OpenComputers
import li.cil.oc.api.event.RobotMoveEvent
@@ -8,54 +8,87 @@ import li.cil.oc.server.component.UpgradeChunkloader
import li.cil.oc.util.BlockPosition
import net.minecraft.util.math.ChunkPos
import net.minecraft.world.World
-import net.minecraftforge.common.ForgeChunkManager
-import net.minecraftforge.common.ForgeChunkManager.LoadingCallback
-import net.minecraftforge.common.ForgeChunkManager.Ticket
+import net.minecraft.world.ForcedChunksSaveData
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.common.world.ForgeChunkManager
+import net.minecraftforge.common.world.ForgeChunkManager.LoadingValidationCallback
+import net.minecraftforge.common.world.ForgeChunkManager.TicketHelper
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraft.entity.Entity
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
+import scala.collection.immutable
import scala.collection.mutable
-object ChunkloaderUpgradeHandler extends LoadingCallback {
- val restoredTickets = mutable.Map.empty[String, Ticket]
+object ChunkloaderUpgradeHandler extends LoadingValidationCallback {
+ private val restoredTickets = mutable.Map.empty[UUID, ChunkPos]
- override def ticketsLoaded(tickets: util.List[Ticket], world: World) {
- for (ticket <- tickets) {
- val data = ticket.getModData
- val address = data.getString("address")
- restoredTickets += address -> ticket
- if (data.hasKey("x") && data.hasKey("z")) {
- val x = data.getInteger("x")
- val z = data.getInteger("z")
- OpenComputers.log.info(s"Restoring chunk loader ticket for upgrade at chunk ($x, $z) with address $address.")
+ private def parseAddress(addr: String): Option[UUID] = try {
+ Some(UUID.fromString(addr))
+ }
+ catch {
+ case _: RuntimeException => None
+ }
- ForgeChunkManager.forceChunk(ticket, new ChunkPos(x, z))
+ def claimTicket(addr: String) = parseAddress(addr).flatMap(restoredTickets.remove)
+
+ override def validateTickets(world: ServerWorld, helper: TicketHelper) {
+ for ((owner, ticketsPair) <- helper.getEntityTickets) {
+ // This ensures that malformed tickets are also cleared on world save.
+ restoredTickets += owner -> null
+ // Chunkloaders use only ticking tickets.
+ val tickets = ticketsPair.getSecond
+ if (tickets.size == 9) {
+ var (minX, minZ, maxX, maxZ) = (0, 0, 0, 0)
+ for (combinedPos <- tickets) {
+ val x = ChunkPos.getX(combinedPos)
+ val z = ChunkPos.getZ(combinedPos)
+ minX = minX min x
+ maxX = maxX max x
+ minZ = minZ min z
+ maxZ = maxZ max z
+ }
+ if (minX + 2 == maxX && minZ + 2 == maxZ) {
+ val x = minX + 1
+ val z = minZ + 1
+ OpenComputers.log.info(s"Restoring chunk loader ticket for upgrade at chunk ($x, $z) with address ${owner}.")
+ restoredTickets += owner -> new ChunkPos(x, z)
+ }
+ else {
+ OpenComputers.log.warn(s"Chunk loader ticket for $owner loads an incorrect shape.")
+ helper.removeAllTickets(owner)
+ }
+ }
+ else {
+ OpenComputers.log.warn(s"Chunk loader ticket for $owner loads ${tickets.size} chunks.")
+ helper.removeAllTickets(owner)
}
}
}
@SubscribeEvent
- def onWorldSave(e: WorldEvent.Save) {
- // Any tickets that were not reassigned by the time the world gets saved
- // again can be considered orphaned, so we release them.
- // TODO figure out a better event *after* tile entities were restored
- // but *before* the world is saved, because the tickets are saved first,
- // so if the save is because the game is being quit the tickets aren't
- // actually being cleared. This will *usually* not be a problem, but it
- // has room for improvement.
- restoredTickets.values.foreach(ticket => {
- try{
- val data = ticket.getModData
- OpenComputers.log.warn(s"A chunk loader ticket has been orphaned! Address: ${data.getString("address")}, position: (${data.getInteger("x")}, ${data.getInteger("z")}). Removing...")
- ForgeChunkManager.releaseTicket(ticket)
+ def onWorldSave(e: WorldEvent.Save) = e.getWorld match {
+ case world: ServerWorld => {
+ // Any tickets that were not reassigned by the time the world gets saved
+ // again can be considered orphaned, so we release them.
+ // TODO figure out a better event *after* tile entities were restored
+ // but *before* the world is saved, because the tickets are saved first,
+ // so if the save is because the game is being quit the tickets aren't
+ // actually being cleared. This will *usually* not be a problem, but it
+ // has room for improvement.
+ for ((owner, pos) <- restoredTickets) {
+ try {
+ OpenComputers.log.warn(s"A chunk loader ticket has been orphaned! Address: ${owner}, position: (${pos.x}, ${pos.z}). Removing...")
+ releaseTicket(world, owner.toString, pos)
+ }
+ catch {
+ case err: Throwable => OpenComputers.log.error(err)
+ }
}
- catch {
- case _: Throwable => // Ignored.
- }
- })
- restoredTickets.clear()
+ restoredTickets.clear()
+ }
+ case _ =>
}
// Note: it might be necessary to use pre move to force load the target chunk
@@ -74,23 +107,37 @@ object ChunkloaderUpgradeHandler extends LoadingCallback {
})
}
- def updateLoadedChunk(loader: UpgradeChunkloader) {
- val blockPos = BlockPosition(loader.host)
- val centerChunk = new ChunkPos(blockPos.x >> 4, blockPos.z >> 4)
- val robotChunks = (for (x <- -1 to 1; z <- -1 to 1) yield new ChunkPos(centerChunk.x + x, centerChunk.z + z)).toSet
-
- loader.ticket.foreach(ticket => {
- ticket.getChunkList.collect {
- case chunk: ChunkPos if !robotChunks.contains(chunk) => ForgeChunkManager.unforceChunk(ticket, chunk)
+ def releaseTicket(world: ServerWorld, addr: String, pos: ChunkPos): Unit = parseAddress(addr) match {
+ case Some(uuid) => {
+ for (x <- -1 to 1; z <- -1 to 1) {
+ ForgeChunkManager.forceChunk(world, OpenComputers.ID, uuid, pos.x + x, pos.z + z, false, true)
}
+ }
+ case _ => OpenComputers.log.warn("Address '$addr' could not be parsed")
+ }
- for (chunk <- robotChunks) {
- ForgeChunkManager.forceChunk(ticket, chunk)
+ def updateLoadedChunk(loader: UpgradeChunkloader) {
+ (loader.host.world, parseAddress(loader.node.address)) match {
+ // If loader.ticket is None that means we shouldn't load anything (as did the old ticketing system).
+ case (world: ServerWorld, Some(owner)) if loader.ticket.isDefined => {
+ val blockPos = BlockPosition(loader.host)
+ val centerChunk = new ChunkPos(blockPos.x >> 4, blockPos.z >> 4)
+ if (centerChunk != loader.ticket.get) {
+ val robotChunks = (for (x <- -1 to 1; z <- -1 to 1) yield new ChunkPos(centerChunk.x + x, centerChunk.z + z)).toSet
+ val existingChunks = loader.ticket match {
+ case Some(currPos) => (for (x <- -1 to 1; z <- -1 to 1) yield new ChunkPos(currPos.x + x, currPos.z + z)).toSet
+ case None => immutable.Set.empty[ChunkPos]
+ }
+ for (toRemove <- existingChunks if !robotChunks.contains(toRemove)) {
+ ForgeChunkManager.forceChunk(world, OpenComputers.ID, owner, toRemove.x, toRemove.z, false, true)
+ }
+ for (toAdd <- robotChunks if !existingChunks.contains(toAdd)) {
+ ForgeChunkManager.forceChunk(world, OpenComputers.ID, owner, toAdd.x, toAdd.z, true, true)
+ }
+ loader.ticket = Some(centerChunk)
+ }
}
-
- ticket.getModData.setString("address", loader.node.address)
- ticket.getModData.setInteger("x", centerChunk.x)
- ticket.getModData.setInteger("z", centerChunk.z)
- })
+ case _ =>
+ }
}
}
diff --git a/src/main/scala/li/cil/oc/common/event/ExperienceUpgradeHandler.scala b/src/main/scala/li/cil/oc/common/event/ExperienceUpgradeHandler.scala
index 7e61d8735a..aa0afbbe1b 100644
--- a/src/main/scala/li/cil/oc/common/event/ExperienceUpgradeHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/ExperienceUpgradeHandler.scala
@@ -1,5 +1,6 @@
package li.cil.oc.common.event
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Localization
import li.cil.oc.Settings
import li.cil.oc.api.event._
@@ -7,10 +8,10 @@ import li.cil.oc.api.internal.Agent
import li.cil.oc.api.internal.Robot
import li.cil.oc.api.network.Node
import li.cil.oc.server.component
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraft.util.Util
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object ExperienceUpgradeHandler {
@SubscribeEvent
@@ -18,7 +19,7 @@ object ExperienceUpgradeHandler {
val (level, experience) = getLevelAndExperience(e.agent)
// This is basically a 'does it have an experience upgrade' check.
if (experience != 0.0) {
- e.player.sendMessage(Localization.Analyzer.RobotXp(experience, level))
+ e.player.sendMessage(Localization.Analyzer.RobotXp(experience, level), Util.NIL_UUID)
}
}
@@ -37,7 +38,7 @@ object ExperienceUpgradeHandler {
def onRobotAttackEntityPost(e: RobotAttackEntityEvent.Post) {
e.agent match {
case robot: Robot =>
- if (robot.equipmentInventory.getStackInSlot(0) != null && e.target.isDead) {
+ if (robot.equipmentInventory.getItem(0) != null && !e.target.isAlive) {
addExperience(robot, Settings.get.robotActionXp)
}
case _ =>
@@ -69,7 +70,7 @@ object ExperienceUpgradeHandler {
val level = e.agent match {
case robot: Robot =>
var acc = 0
- for (index <- 0 until robot.getSizeInventory) {
+ for (index <- 0 until robot.getContainerSize) {
robot.getComponentInSlot(index) match {
case upgrade: component.UpgradeExperience =>
acc += upgrade.level
@@ -80,13 +81,10 @@ object ExperienceUpgradeHandler {
case _ => 0
}
if (level > 19) {
- GlStateManager.color(0.4f, 1, 1)
+ e.multiplyColors(0.4f, 1, 1)
}
else if (level > 9) {
- GlStateManager.color(1, 1, 0.4f)
- }
- else {
- GlStateManager.color(0.5f, 0.5f, 0.5f)
+ e.multiplyColors(1, 1, 0.4f)
}
}
diff --git a/src/main/scala/li/cil/oc/common/event/FileSystemAccessHandler.scala b/src/main/scala/li/cil/oc/common/event/FileSystemAccessHandler.scala
index a4f2ddb37a..1c9dbcacde 100644
--- a/src/main/scala/li/cil/oc/common/event/FileSystemAccessHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/FileSystemAccessHandler.scala
@@ -11,14 +11,14 @@ import li.cil.oc.server.component.Server
import net.minecraft.util.ResourceLocation
import net.minecraft.util.SoundCategory
import net.minecraft.util.SoundEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
object FileSystemAccessHandler {
@SubscribeEvent
def onFileSystemAccess(e: FileSystemAccessEvent.Server) {
- e.getTileEntity match {
+ e.getBlockEntity match {
case t: Rack =>
- for (slot <- 0 until t.getSizeInventory) {
+ for (slot <- 0 until t.getContainerSize) {
t.getMountable(slot) match {
case server: Server =>
val containsNode = server.componentSlot(e.getNode.address) >= 0
@@ -43,8 +43,8 @@ object FileSystemAccessHandler {
def onFileSystemAccess(e: FileSystemAccessEvent.Client) {
val volume = Settings.get.soundVolume
val sound = new SoundEvent(new ResourceLocation(e.getSound))
- e.getWorld.playSound(e.getX, e.getY, e.getZ, sound, SoundCategory.BLOCKS, volume, 1, false)
- e.getTileEntity match {
+ e.getWorld.playLocalSound(e.getX, e.getY, e.getZ, sound, SoundCategory.BLOCKS, volume, 1, false)
+ e.getBlockEntity match {
case t: DiskDrive => t.lastAccess = System.currentTimeMillis()
case t: Case => t.lastFileSystemAccess = System.currentTimeMillis()
case t: Raid => t.lastAccess = System.currentTimeMillis()
diff --git a/src/main/scala/li/cil/oc/common/event/HoverBootsHandler.scala b/src/main/scala/li/cil/oc/common/event/HoverBootsHandler.scala
index d990c8f341..8d621f5e9a 100644
--- a/src/main/scala/li/cil/oc/common/event/HoverBootsHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/HoverBootsHandler.scala
@@ -1,27 +1,28 @@
package li.cil.oc.common.event
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.Settings
import li.cil.oc.common.item.HoverBoots
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.entity.living.LivingEvent.LivingJumpEvent
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent
import net.minecraftforge.event.entity.living.LivingFallEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object HoverBootsHandler {
@SubscribeEvent
def onLivingUpdate(e: LivingUpdateEvent): Unit = e.getEntity match {
- case player: EntityPlayer if !player.isInstanceOf[FakePlayer] =>
- val nbt = player.getEntityData
+ case player: PlayerEntity if !player.isInstanceOf[FakePlayer] =>
+ val nbt = player.getPersistentData
val hadHoverBoots = nbt.getBoolean(Settings.namespace + "hasHoverBoots")
- val hasHoverBoots = !player.isSneaking && equippedArmor(player).exists(stack => stack.getItem match {
+ val hasHoverBoots = !player.isCrouching && equippedArmor(player).exists(stack => stack.getItem match {
case boots: HoverBoots =>
Settings.get.ignorePower || {
- if (player.onGround && !player.capabilities.isCreativeMode && player.world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
- val velocity = player.motionX * player.motionX + player.motionY * player.motionY + player.motionZ * player.motionZ
+ if (player.isOnGround && !player.isCreative && player.level.getGameTime % Settings.get.tickFrequency == 0) {
+ val velocity = player.getDeltaMovement.lengthSqr
if (velocity > 0.015f) {
boots.charge(stack, -Settings.get.hoverBootMove, simulate = false)
}
@@ -31,29 +32,30 @@ object HoverBootsHandler {
case _ => false
})
if (hasHoverBoots != hadHoverBoots) {
- nbt.setBoolean(Settings.namespace + "hasHoverBoots", hasHoverBoots)
- player.stepHeight = if (hasHoverBoots) 1f else 0.5f
+ nbt.putBoolean(Settings.namespace + "hasHoverBoots", hasHoverBoots)
+ player.maxUpStep = if (hasHoverBoots) 1f else 0.5f
}
- if (hasHoverBoots && !player.onGround && player.fallDistance < 5 && player.motionY < 0) {
- player.motionY *= 0.9f
+ if (hasHoverBoots && !player.isOnGround && player.fallDistance < 5 && player.getDeltaMovement.y < 0) {
+ player.setDeltaMovement(player.getDeltaMovement.multiply(1, 0.9, 1))
}
case _ => // Ignore.
}
@SubscribeEvent
def onLivingJump(e: LivingJumpEvent): Unit = e.getEntity match {
- case player: EntityPlayer if !player.isInstanceOf[FakePlayer] && !player.isSneaking =>
+ case player: PlayerEntity if !player.isInstanceOf[FakePlayer] && !player.isCrouching =>
equippedArmor(player).collectFirst {
case stack if stack.getItem.isInstanceOf[HoverBoots] =>
val boots = stack.getItem.asInstanceOf[HoverBoots]
val hoverJumpCost = -Settings.get.hoverBootJump
- val isCreative = Settings.get.ignorePower || player.capabilities.isCreativeMode
+ val isCreative = Settings.get.ignorePower || player.isCreative
if (isCreative || boots.charge(stack, hoverJumpCost, simulate = true) == 0) {
if (!isCreative) boots.charge(stack, hoverJumpCost, simulate = false)
+ val motion = player.getDeltaMovement
if (player.isSprinting)
- player.addVelocity(player.motionX * 0.5, 0.4, player.motionZ * 0.5)
+ player.push(motion.x * 0.5, 0.4, motion.z * 0.5)
else
- player.addVelocity(0, 0.4, 0)
+ player.push(0, 0.4, 0)
}
}
case _ => // Ignore.
@@ -61,12 +63,12 @@ object HoverBootsHandler {
@SubscribeEvent
def onLivingFall(e: LivingFallEvent): Unit = if (e.getDistance > 3) e.getEntity match {
- case player: EntityPlayer if !player.isInstanceOf[FakePlayer] =>
+ case player: PlayerEntity if !player.isInstanceOf[FakePlayer] =>
equippedArmor(player).collectFirst {
case stack if stack.getItem.isInstanceOf[HoverBoots] =>
val boots = stack.getItem.asInstanceOf[HoverBoots]
val hoverFallCost = -Settings.get.hoverBootAbsorb
- val isCreative = Settings.get.ignorePower || player.capabilities.isCreativeMode
+ val isCreative = Settings.get.ignorePower || player.isCreative
if (isCreative || boots.charge(stack, hoverFallCost, simulate = true) == 0) {
if (!isCreative) boots.charge(stack, hoverFallCost, simulate = false)
e.setDistance(e.getDistance * 0.3f)
@@ -75,5 +77,5 @@ object HoverBootsHandler {
case _ => // Ignore.
}
- private def equippedArmor(player: EntityPlayer) = player.getArmorInventoryList.filter(!_.isEmpty)
+ private def equippedArmor(player: PlayerEntity) = player.inventory.armor.filter(!_.isEmpty)
}
diff --git a/src/main/scala/li/cil/oc/common/event/NanomachinesHandler.scala b/src/main/scala/li/cil/oc/common/event/NanomachinesHandler.scala
index 05238940cf..fa272c7750 100644
--- a/src/main/scala/li/cil/oc/common/event/NanomachinesHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/NanomachinesHandler.scala
@@ -3,42 +3,48 @@ package li.cil.oc.common.event
import java.io.FileInputStream
import java.io.FileOutputStream
+import com.mojang.blaze3d.matrix.MatrixStack
+import com.mojang.blaze3d.vertex.IVertexBuilder
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.Controller
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.common.EventHandler
import li.cil.oc.common.nanomachines.ControllerImpl
import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.ScaledResolution
+import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.nbt.CompressedStreamTools
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.event.entity.living.LivingEvent
import net.minecraftforge.event.entity.player.PlayerEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent
-import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent
-import org.lwjgl.opengl.GL11
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent
+import net.minecraftforge.event.entity.player.PlayerEvent.PlayerRespawnEvent
object NanomachinesHandler {
object Client {
+ val TexNanomachines = RenderTypes.createTexturedQuad("nanomachines", Textures.GUI.Nanomachines, DefaultVertexFormats.POSITION_TEX, false)
+ val TexNanomachinesBar = RenderTypes.createTexturedQuad("nanomachines_bar", Textures.GUI.NanomachinesBar, DefaultVertexFormats.POSITION_TEX, false)
+
@SubscribeEvent
def onRenderGameOverlay(e: RenderGameOverlayEvent.Post): Unit = {
if (e.getType == RenderGameOverlayEvent.ElementType.TEXT) {
- val mc = Minecraft.getMinecraft
+ val mc = Minecraft.getInstance
api.Nanomachines.getController(mc.player) match {
case controller: Controller =>
- val res = new ScaledResolution(mc)
+ val stack = e.getMatrixStack
+ val window = mc.getWindow
val sizeX = 8
val sizeY = 12
- val width = res.getScaledWidth
- val height = res.getScaledHeight
+ val width = window.getGuiScaledWidth
+ val height = window.getGuiScaledHeight
val (x, y) = Settings.get.nanomachineHudPos
val left =
math.min(width - sizeX,
@@ -51,33 +57,29 @@ object NanomachinesHandler {
else if (y < 1) y * height
else y)
val fill = controller.getLocalBuffer / controller.getLocalBufferSize
- Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.GUI.Nanomachines)
- drawRect(left.toInt, top.toInt, sizeX, sizeY, sizeX, sizeY)
- Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.GUI.NanomachinesBar)
- drawRect(left.toInt, top.toInt, sizeX, sizeY, sizeX, sizeY, fill)
+ val buffer = IRenderTypeBuffer.immediate(Tessellator.getInstance.getBuilder)
+ drawRect(stack, buffer.getBuffer(TexNanomachines), left.toInt, top.toInt, sizeX, sizeY, sizeX, sizeY)
+ drawRect(stack, buffer.getBuffer(TexNanomachinesBar), left.toInt, top.toInt, sizeX, sizeY, sizeX, sizeY, fill.toFloat)
+ buffer.endBatch()
case _ => // Nothing to show.
}
}
}
- private def drawRect(x: Int, y: Int, w: Int, h: Int, tw: Int, th: Int, fill: Double = 1) {
+ private def drawRect(stack: MatrixStack, r: IVertexBuilder, x: Int, y: Int, w: Int, h: Int, tw: Int, th: Int, fill: Float = 1) {
val sx = 1f / tw
val sy = 1f / th
- val t = Tessellator.getInstance
- val r = t.getBuffer
- r.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX)
- r.pos(x, y + h, 0).tex(0, h * sy).endVertex()
- r.pos(x + w, y + h, 0).tex(w * sx, h * sy).endVertex()
- r.pos(x + w, y + h * (1 - fill), 0).tex(w * sx, 1 - fill).endVertex()
- r.pos(x, y + h * (1 - fill), 0).tex(0, 1 - fill).endVertex()
- t.draw()
+ r.vertex(stack.last.pose, x, y + h, 0).uv(0, h * sy).endVertex()
+ r.vertex(stack.last.pose, x + w, y + h, 0).uv(w * sx, h * sy).endVertex()
+ r.vertex(stack.last.pose, x + w, y + h * (1 - fill), 0).uv(w * sx, 1 - fill).endVertex()
+ r.vertex(stack.last.pose, x, y + h * (1 - fill), 0).uv(0, 1 - fill).endVertex()
}
}
object Common {
@SubscribeEvent
def onPlayerRespawn(e: PlayerRespawnEvent): Unit = {
- api.Nanomachines.getController(e.player) match {
+ api.Nanomachines.getController(e.getPlayer) match {
case controller: Controller => controller.changeBuffer(-controller.getLocalBuffer)
case _ => // Not a player with nanomachines.
}
@@ -86,19 +88,19 @@ object NanomachinesHandler {
@SubscribeEvent
def onLivingUpdate(e: LivingEvent.LivingUpdateEvent): Unit = {
e.getEntity match {
- case player: EntityPlayer => api.Nanomachines.getController(player) match {
+ case player: PlayerEntity => api.Nanomachines.getController(player) match {
case controller: ControllerImpl =>
if (controller.player eq player) {
controller.update()
}
else {
// Player entity instance changed (e.g. respawn), recreate the controller.
- val nbt = new NBTTagCompound()
- controller.save(nbt)
+ val nbt = new CompoundNBT()
+ controller.saveData(nbt)
api.Nanomachines.uninstallController(controller.player)
api.Nanomachines.installController(player) match {
case newController: ControllerImpl =>
- newController.load(nbt)
+ newController.loadData(nbt)
newController.reset()
case _ => // Eh?
}
@@ -112,11 +114,11 @@ object NanomachinesHandler {
@SubscribeEvent
def onPlayerSave(e: PlayerEvent.SaveToFile): Unit = {
val file = e.getPlayerFile("ocnm")
- api.Nanomachines.getController(e.getEntityPlayer) match {
+ api.Nanomachines.getController(e.getPlayer) match {
case controller: ControllerImpl =>
try {
- val nbt = new NBTTagCompound()
- controller.save(nbt)
+ val nbt = new CompoundNBT()
+ controller.saveData(nbt)
val fos = new FileOutputStream(file)
try CompressedStreamTools.writeCompressed(nbt, fos) catch {
case t: Throwable =>
@@ -136,11 +138,11 @@ object NanomachinesHandler {
def onPlayerLoad(e: PlayerEvent.LoadFromFile): Unit = {
val file = e.getPlayerFile("ocnm")
if (file.exists()) {
- api.Nanomachines.getController(e.getEntityPlayer) match {
+ api.Nanomachines.getController(e.getPlayer) match {
case controller: ControllerImpl =>
try {
val fis = new FileInputStream(file)
- try controller.load(CompressedStreamTools.readCompressed(fis)) catch {
+ try controller.loadData(CompressedStreamTools.readCompressed(fis)) catch {
case t: Throwable =>
OpenComputers.log.warn("Error loading nanomachine state.", t)
}
@@ -157,10 +159,10 @@ object NanomachinesHandler {
@SubscribeEvent
def onPlayerDisconnect(e: PlayerLoggedOutEvent): Unit = {
- api.Nanomachines.getController(e.player) match {
+ api.Nanomachines.getController(e.getPlayer) match {
case controller: ControllerImpl =>
// Wait a tick because saving is done after this event.
- EventHandler.scheduleServer(() => api.Nanomachines.uninstallController(e.player))
+ EventHandler.scheduleServer(() => api.Nanomachines.uninstallController(e.getPlayer))
case _ => // Not a player with nanomachines.
}
}
diff --git a/src/main/scala/li/cil/oc/common/event/NetworkActivityHandler.scala b/src/main/scala/li/cil/oc/common/event/NetworkActivityHandler.scala
index 934b851ce8..6a10705bf1 100644
--- a/src/main/scala/li/cil/oc/common/event/NetworkActivityHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/NetworkActivityHandler.scala
@@ -4,14 +4,14 @@ import li.cil.oc.api.event.NetworkActivityEvent
import li.cil.oc.api.internal.Rack
import li.cil.oc.common.tileentity.Case
import li.cil.oc.server.component.Server
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
object NetworkActivityHandler {
@SubscribeEvent
def onNetworkActivity(e: NetworkActivityEvent.Server) {
- e.getTileEntity match {
+ e.getBlockEntity match {
case t: Rack =>
- for (slot <- 0 until t.getSizeInventory) {
+ for (slot <- 0 until t.getContainerSize) {
t.getMountable(slot) match {
case server: Server =>
val containsNode = server.componentSlot(e.getNode.address) >= 0
@@ -28,7 +28,7 @@ object NetworkActivityHandler {
@SubscribeEvent
def onNetworkActivity(e: NetworkActivityEvent.Client) {
- e.getTileEntity match {
+ e.getBlockEntity match {
case t: Case => t.lastNetworkActivity = System.currentTimeMillis();
case _ =>
}
diff --git a/src/main/scala/li/cil/oc/common/event/RackMountableRenderHandler.scala b/src/main/scala/li/cil/oc/common/event/RackMountableRenderHandler.scala
index 033172a3b4..057a839684 100644
--- a/src/main/scala/li/cil/oc/common/event/RackMountableRenderHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/RackMountableRenderHandler.scala
@@ -1,22 +1,25 @@
package li.cil.oc.common.event
+import com.mojang.blaze3d.systems.RenderSystem
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.api.event.RackMountableRenderEvent
import li.cil.oc.client.Textures
+import li.cil.oc.client.renderer.RenderTypes
import li.cil.oc.client.renderer.tileentity.RenderUtil
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.OpenGlHelper
-import net.minecraft.client.renderer.block.model.ItemCameraTransforms
-import net.minecraft.entity.item.EntityItem
+import net.minecraft.client.renderer.model.ItemCameraTransforms
+import net.minecraft.entity.item.ItemEntity
import net.minecraft.item.ItemStack
+import net.minecraft.util.ResourceLocation
+import net.minecraft.util.math.vector.Vector3f
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.opengl.GL11
+import org.lwjgl.opengl.GL13
object RackMountableRenderHandler {
lazy val DiskDriveMountable = api.Items.get(Constants.ItemName.DiskDriveMountable)
@@ -32,90 +35,77 @@ object RackMountableRenderHandler {
@SubscribeEvent
def onRackMountableRendering(e: RackMountableRenderEvent.TileEntity): Unit = {
- if (e.data != null && DiskDriveMountable == api.Items.get(e.rack.getStackInSlot(e.mountable))) {
+ if (e.data != null && DiskDriveMountable == api.Items.get(e.rack.getItem(e.mountable))) {
// Disk drive.
- if (e.data.hasKey("disk")) {
- val stack = new ItemStack(e.data.getCompoundTag("disk"))
+ if (e.data.contains("disk")) {
+ val stack = ItemStack.of(e.data.getCompound("disk"))
if (!stack.isEmpty) {
- GlStateManager.pushMatrix()
- GlStateManager.scale(1, -1, 1)
- GlStateManager.translate(10 / 16f, -(3.5f + e.mountable * 3f) / 16f, -2 / 16f)
- GlStateManager.rotate(90, -1, 0, 0)
- GlStateManager.scale(0.5f, 0.5f, 0.5f)
-
- val brightness = e.rack.world.getLightBrightnessForSkyBlocks(BlockPosition(e.rack).offset(e.rack.facing), 0)
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536)
-
- // This is very 'meh', but item frames do it like this, too!
- val entity = new EntityItem(e.rack.world, 0, 0, 0, stack)
- entity.hoverStart = 0
- Minecraft.getMinecraft.getRenderItem.renderItem(entity.getItem, ItemCameraTransforms.TransformType.FIXED)
- GlStateManager.popMatrix()
+ val matrix = e.stack
+ matrix.pushPose()
+ matrix.scale(1, -1, 1)
+ matrix.translate(10 / 16f, -(3.5f + e.mountable * 3f) / 16f, -2 / 16f)
+ matrix.mulPose(Vector3f.XN.rotationDegrees(90))
+ matrix.scale(0.5f, 0.5f, 0.5f)
+
+ Minecraft.getInstance.getItemRenderer.renderStatic(stack, ItemCameraTransforms.TransformType.FIXED, e.light, e.overlay, matrix, e.typeBuffer)
+ matrix.popPose()
}
}
- if (System.currentTimeMillis() - e.data.getLong("lastAccess") < 400 && e.rack.world.rand.nextDouble() > 0.1) {
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
-
- e.renderOverlayFromAtlas(Textures.Block.RackDiskDriveActivity)
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
+ if (System.currentTimeMillis() - e.data.getLong("lastAccess") < 400 && e.rack.world.random.nextDouble() > 0.1) {
+ renderOverlayFromAtlas(e, Textures.Block.RackDiskDriveActivity)
}
}
- else if (e.data != null && Servers.contains(api.Items.get(e.rack.getStackInSlot(e.mountable)))) {
+ else if (e.data != null && Servers.contains(api.Items.get(e.rack.getItem(e.mountable)))) {
// Server.
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
-
if (e.data.getBoolean("isRunning")) {
- e.renderOverlayFromAtlas(Textures.Block.RackServerOn)
+ renderOverlayFromAtlas(e, Textures.Block.RackServerOn)
}
if (e.data.getBoolean("hasErrored") && RenderUtil.shouldShowErrorLight(e.rack.hashCode * (e.mountable + 1))) {
- e.renderOverlayFromAtlas(Textures.Block.RackServerError)
+ renderOverlayFromAtlas(e, Textures.Block.RackServerError)
}
- if (System.currentTimeMillis() - e.data.getLong("lastFileSystemAccess") < 400 && e.rack.world.rand.nextDouble() > 0.1) {
- e.renderOverlayFromAtlas(Textures.Block.RackServerActivity)
+ if (System.currentTimeMillis() - e.data.getLong("lastFileSystemAccess") < 400 && e.rack.world.random.nextDouble() > 0.1) {
+ renderOverlayFromAtlas(e, Textures.Block.RackServerActivity)
}
if ((System.currentTimeMillis() - e.data.getLong("lastNetworkActivity") < 300 && System.currentTimeMillis() % 200 > 100) && e.data.getBoolean("isRunning")) {
- e.renderOverlayFromAtlas(Textures.Block.RackServerNetworkActivity)
+ renderOverlayFromAtlas(e, Textures.Block.RackServerNetworkActivity)
}
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
}
- else if (e.data != null && TerminalServer == api.Items.get(e.rack.getStackInSlot(e.mountable))) {
+ else if (e.data != null && TerminalServer == api.Items.get(e.rack.getItem(e.mountable))) {
// Terminal server.
- RenderState.disableEntityLighting()
- RenderState.makeItBlend()
-
- e.renderOverlayFromAtlas(Textures.Block.RackTerminalServerOn)
- val countConnected = e.data.getTagList("keys", NBT.TAG_STRING).tagCount()
+ renderOverlayFromAtlas(e, Textures.Block.RackTerminalServerOn)
+ val countConnected = e.data.getList("keys", NBT.TAG_STRING).size()
if (countConnected > 0) {
val u0 = 7 / 16f
val u1 = u0 + (2 * countConnected - 1) / 16f
- e.renderOverlayFromAtlas(Textures.Block.RackTerminalServerPresence, u0, u1)
+ renderOverlayFromAtlas(e, Textures.Block.RackTerminalServerPresence, u0, u1)
}
-
- RenderState.disableBlend()
- RenderState.enableEntityLighting()
}
}
+ private def renderOverlayFromAtlas(e: RackMountableRenderEvent.TileEntity, texture: ResourceLocation, u0: Float = 0, u1: Float = 1) {
+ val matrix = e.stack.last.pose
+ val r = e.typeBuffer.getBuffer(RenderTypes.BLOCK_OVERLAY)
+ val icon = Textures.getSprite(texture)
+ r.vertex(matrix, u0, e.v1, 0).uv(icon.getU(u0 * 16), icon.getV(e.v1 * 16)).endVertex();
+ r.vertex(matrix, u1, e.v1, 0).uv(icon.getU(u1 * 16), icon.getV(e.v1 * 16)).endVertex();
+ r.vertex(matrix, u1, e.v0, 0).uv(icon.getU(u1 * 16), icon.getV(e.v0 * 16)).endVertex();
+ r.vertex(matrix, u0, e.v0, 0).uv(icon.getU(u0 * 16), icon.getV(e.v0 * 16)).endVertex();
+ }
+
@SubscribeEvent
def onRackMountableRendering(e: RackMountableRenderEvent.Block): Unit = {
- if (DiskDriveMountable == api.Items.get(e.rack.getStackInSlot(e.mountable))) {
+ if (DiskDriveMountable == api.Items.get(e.rack.getItem(e.mountable))) {
// Disk drive.
e.setFrontTextureOverride(Textures.getSprite(Textures.Block.RackDiskDrive))
}
- else if (Servers.contains(api.Items.get(e.rack.getStackInSlot(e.mountable)))) {
+ else if (Servers.contains(api.Items.get(e.rack.getItem(e.mountable)))) {
// Server.
e.setFrontTextureOverride(Textures.getSprite(Textures.Block.RackServer))
}
- else if (TerminalServer == api.Items.get(e.rack.getStackInSlot(e.mountable))) {
+ else if (TerminalServer == api.Items.get(e.rack.getItem(e.mountable))) {
// Terminal server.
e.setFrontTextureOverride(Textures.getSprite(Textures.Block.RackTerminalServer))
}
diff --git a/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala b/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala
index ed0485591e..603843da0e 100644
--- a/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala
@@ -5,24 +5,23 @@ import li.cil.oc.api.event.RobotMoveEvent
import li.cil.oc.api.event.RobotUsedToolEvent
import li.cil.oc.api.internal
import li.cil.oc.api.internal.Robot
-import li.cil.oc.common.item.Delegator
import li.cil.oc.common.item.UpgradeHover
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraft.util.Direction
+import net.minecraftforge.eventbus.api.SubscribeEvent
object RobotCommonHandler {
@SubscribeEvent
def onRobotApplyDamageRate(e: RobotUsedToolEvent.ApplyDamageRate) {
e.agent match {
case robot: internal.Robot =>
- if (e.toolAfterUse.isItemStackDamageable) {
- val damage = e.toolAfterUse.getItemDamage - e.toolBeforeUse.getItemDamage
+ if (e.toolAfterUse.isDamageableItem) {
+ val damage = e.toolAfterUse.getDamageValue - e.toolBeforeUse.getDamageValue
if (damage > 0) {
val actualDamage = damage * e.getDamageRate
- val repairedDamage = if (e.agent.player.getRNG.nextDouble() > 0.5) damage - math.floor(actualDamage).toInt else damage - math.ceil(actualDamage).toInt
- e.toolAfterUse.setItemDamage(e.toolAfterUse.getItemDamage - repairedDamage)
+ val repairedDamage = if (e.agent.player.getRandom.nextDouble() > 0.5) damage - math.floor(actualDamage).toInt else damage - math.ceil(actualDamage).toInt
+ e.toolAfterUse.setDamageValue(e.toolAfterUse.getDamageValue - repairedDamage)
}
}
case _ =>
@@ -36,20 +35,21 @@ object RobotCommonHandler {
val world = robot.world
var maxFlyingHeight = Settings.get.limitFlightHeight
- (0 until robot.equipmentInventory.getSizeInventory).
- map(robot.equipmentInventory.getStackInSlot).
- map(Delegator.subItem).
- collect { case Some(item: UpgradeHover) => maxFlyingHeight = math.max(maxFlyingHeight, Settings.get.upgradeFlightHeight(item.tier)) }
+ (0 until robot.equipmentInventory.getContainerSize).
+ map(robot.equipmentInventory.getItem(_).getItem).
+ collect { case item: UpgradeHover => maxFlyingHeight = math.max(maxFlyingHeight, Settings.get.upgradeFlightHeight(item.tier)) }
(0 until robot.componentCount).
- map(_ + robot.mainInventory.getSizeInventory + robot.equipmentInventory.getSizeInventory).
- map(robot.getStackInSlot).
- map(Delegator.subItem).
- collect { case Some(item: UpgradeHover) => maxFlyingHeight = math.max(maxFlyingHeight, Settings.get.upgradeFlightHeight(item.tier)) }
+ map(_ + robot.mainInventory.getContainerSize + robot.equipmentInventory.getContainerSize).
+ map(robot.getItem(_).getItem).
+ collect { case item: UpgradeHover => maxFlyingHeight = math.max(maxFlyingHeight, Settings.get.upgradeFlightHeight(item.tier)) }
- def isMovingDown = e.direction == EnumFacing.DOWN
- def hasAdjacentBlock(pos: BlockPosition) = EnumFacing.values.exists(side => world.isSideSolid(pos.offset(side), side.getOpposite))
- def isWithinFlyingHeight(pos: BlockPosition) = maxFlyingHeight >= world.getHeight || (1 to maxFlyingHeight).exists(n => !world.isAirBlock(pos.offset(EnumFacing.DOWN, n)))
+ def isMovingDown = e.direction == Direction.DOWN
+ def hasAdjacentBlock(pos: BlockPosition) = Direction.values.exists(side => {
+ val sidePos = pos.offset(side).toBlockPos
+ world.getBlockState(sidePos).isFaceSturdy(world, sidePos, side.getOpposite)
+ })
+ def isWithinFlyingHeight(pos: BlockPosition) = maxFlyingHeight >= world.getHeight() || (1 to maxFlyingHeight).exists(n => !world.isAirBlock(pos.offset(Direction.DOWN, n)))
val startPos = BlockPosition(robot)
val targetPos = startPos.offset(e.direction)
// New movement rules as of 1.5:
diff --git a/src/main/scala/li/cil/oc/common/event/WirelessNetworkCardHandler.scala b/src/main/scala/li/cil/oc/common/event/WirelessNetworkCardHandler.scala
index 1075e28949..a5bc98579e 100644
--- a/src/main/scala/li/cil/oc/common/event/WirelessNetworkCardHandler.scala
+++ b/src/main/scala/li/cil/oc/common/event/WirelessNetworkCardHandler.scala
@@ -3,9 +3,9 @@ package li.cil.oc.common.event
import li.cil.oc.api
import li.cil.oc.api.event.RobotMoveEvent
import li.cil.oc.server.component.WirelessNetworkCard
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object WirelessNetworkCardHandler {
@SubscribeEvent
diff --git a/src/main/scala/li/cil/oc/common/init/Blocks.scala b/src/main/scala/li/cil/oc/common/init/Blocks.scala
index c37b790b08..c2d0066322 100644
--- a/src/main/scala/li/cil/oc/common/init/Blocks.scala
+++ b/src/main/scala/li/cil/oc/common/init/Blocks.scala
@@ -1,92 +1,64 @@
package li.cil.oc.common.init
import li.cil.oc.Constants
+import li.cil.oc.CreativeTab
import li.cil.oc.Settings
import li.cil.oc.common.Tier
import li.cil.oc.common.block._
-import li.cil.oc.common.recipe.Recipes
-import li.cil.oc.common.tileentity
-import net.minecraft.tileentity.TileEntity
-import net.minecraftforge.fml.common.registry.GameRegistry
+import net.minecraft.block.AbstractBlock.Properties
+import net.minecraft.block.material.Material
+import net.minecraft.item.Rarity
+import net.minecraft.item.Item
object Blocks {
def init() {
- registerTileEntity(classOf[tileentity.Adapter], Settings.namespace + "adapter")
- registerTileEntity(classOf[tileentity.Assembler], Settings.namespace + "assembler")
- registerTileEntity(classOf[tileentity.Cable], Settings.namespace + "cable")
- registerTileEntity(classOf[tileentity.Capacitor], Settings.namespace + "capacitor")
- registerTileEntity(classOf[tileentity.CarpetedCapacitor], Settings.namespace + "carpetedCapacitor")
- registerTileEntity(classOf[tileentity.Case], Settings.namespace + "case")
- registerTileEntity(classOf[tileentity.Charger], Settings.namespace + "charger")
- registerTileEntity(classOf[tileentity.DiskDrive], Settings.namespace + "diskDrive")
- registerTileEntity(classOf[tileentity.Disassembler], Settings.namespace + "disassembler")
- registerTileEntity(classOf[tileentity.Keyboard], Settings.namespace + "keyboard")
- registerTileEntity(classOf[tileentity.Hologram], Settings.namespace + "hologram")
- registerTileEntity(classOf[tileentity.Geolyzer], Settings.namespace + "geolyzer")
- registerTileEntity(classOf[tileentity.Microcontroller], Settings.namespace + "microcontroller")
- registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motionSensor")
- registerTileEntity(classOf[tileentity.NetSplitter], Settings.namespace + "netSplitter")
- registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "powerConverter")
- registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "powerDistributor")
- registerTileEntity(classOf[tileentity.Print], Settings.namespace + "print")
- registerTileEntity(classOf[tileentity.Printer], Settings.namespace + "printer")
- registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid")
- registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone")
- registerTileEntity(classOf[tileentity.Relay], Settings.namespace + "relay")
- registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot")
- registerTileEntity(classOf[tileentity.Screen], Settings.namespace + "screen")
- registerTileEntity(classOf[tileentity.Rack], Settings.namespace + "rack")
- registerTileEntity(classOf[tileentity.Transposer], Settings.namespace + "transposer")
- registerTileEntity(classOf[tileentity.Waypoint], Settings.namespace + "waypoint")
+ def defaultProps = Properties.of(Material.METAL).strength(2, 5)
+ def defaultItemProps = new Item.Properties().tab(CreativeTab)
+ Items.registerBlock(new Adapter(defaultProps), Constants.BlockName.Adapter, defaultItemProps)
+ Items.registerBlock(new Assembler(defaultProps), Constants.BlockName.Assembler, defaultItemProps)
+ Items.registerBlock(new Cable(defaultProps), Constants.BlockName.Cable, defaultItemProps)
+ Items.registerBlock(new Capacitor(defaultProps), Constants.BlockName.Capacitor, defaultItemProps)
+ Items.registerBlock(new Case(defaultProps, Tier.One), Constants.BlockName.CaseTier1, defaultItemProps)
+ Items.registerBlock(new Case(defaultProps, Tier.Three), Constants.BlockName.CaseTier3, defaultItemProps.rarity(Rarity.RARE))
+ Items.registerBlock(new Case(defaultProps, Tier.Two), Constants.BlockName.CaseTier2, defaultItemProps.rarity(Rarity.UNCOMMON))
+ Items.registerBlock(new ChameliumBlock(Properties.of(Material.STONE).strength(2, 5)), Constants.BlockName.ChameliumBlock, defaultItemProps)
+ Items.registerBlock(new Charger(defaultProps), Constants.BlockName.Charger, defaultItemProps)
+ Items.registerBlock(new Disassembler(defaultProps), Constants.BlockName.Disassembler, defaultItemProps)
+ Items.registerBlock(new DiskDrive(defaultProps), Constants.BlockName.DiskDrive, defaultItemProps)
+ Items.registerBlock(new Geolyzer(defaultProps), Constants.BlockName.Geolyzer, defaultItemProps)
+ Items.registerBlock(new Hologram(defaultProps, Tier.One), Constants.BlockName.HologramTier1, defaultItemProps)
+ Items.registerBlock(new Hologram(defaultProps, Tier.Two), Constants.BlockName.HologramTier2, defaultItemProps.rarity(Rarity.UNCOMMON))
+ Items.registerBlock(new Keyboard(Properties.of(Material.STONE).strength(2, 5).noOcclusion), Constants.BlockName.Keyboard, defaultItemProps)
+ Items.registerBlock(new MotionSensor(defaultProps), Constants.BlockName.MotionSensor, defaultItemProps)
+ Items.registerBlock(new PowerConverter(defaultProps), Constants.BlockName.PowerConverter,
+ new Item.Properties().tab(if (!Settings.get.ignorePower) CreativeTab else null))
+ Items.registerBlock(new PowerDistributor(defaultProps), Constants.BlockName.PowerDistributor, defaultItemProps)
+ Items.registerBlock(new Printer(defaultProps), Constants.BlockName.Printer, defaultItemProps)
+ Items.registerBlock(new Raid(defaultProps), Constants.BlockName.Raid, defaultItemProps)
+ Items.registerBlock(new Redstone(defaultProps), Constants.BlockName.Redstone, defaultItemProps)
+ Items.registerBlock(new Relay(defaultProps), Constants.BlockName.Relay, defaultItemProps)
+ Items.registerBlock(new Screen(defaultProps, Tier.One), Constants.BlockName.ScreenTier1, defaultItemProps)
+ Items.registerBlock(new Screen(defaultProps, Tier.Three), Constants.BlockName.ScreenTier3, defaultItemProps.rarity(Rarity.RARE))
+ Items.registerBlock(new Screen(defaultProps, Tier.Two), Constants.BlockName.ScreenTier2, defaultItemProps.rarity(Rarity.UNCOMMON))
+ Items.registerBlock(new Rack(defaultProps), Constants.BlockName.Rack, defaultItemProps)
+ Items.registerBlock(new Waypoint(defaultProps), Constants.BlockName.Waypoint, defaultItemProps)
- Recipes.addBlock(new Adapter(), Constants.BlockName.Adapter, "oc:adapter")
- Recipes.addBlock(new Assembler(), Constants.BlockName.Assembler, "oc:assembler")
- Recipes.addBlock(new Cable(), Constants.BlockName.Cable, "oc:cable")
- Recipes.addBlock(new Capacitor(), Constants.BlockName.Capacitor, "oc:capacitor")
- Recipes.addBlock(new Case(Tier.One), Constants.BlockName.CaseTier1, "oc:case1")
- Recipes.addBlock(new Case(Tier.Three), Constants.BlockName.CaseTier3, "oc:case3")
- Recipes.addBlock(new Case(Tier.Two), Constants.BlockName.CaseTier2, "oc:case2")
- Recipes.addBlock(new ChameliumBlock(), Constants.BlockName.ChameliumBlock, "oc:chameliumBlock")
- Recipes.addBlock(new Charger(), Constants.BlockName.Charger, "oc:charger")
- Recipes.addBlock(new Disassembler(), Constants.BlockName.Disassembler, "oc:disassembler")
- Recipes.addBlock(new DiskDrive(), Constants.BlockName.DiskDrive, "oc:diskDrive")
- Recipes.addBlock(new Geolyzer(), Constants.BlockName.Geolyzer, "oc:geolyzer")
- Recipes.addBlock(new Hologram(Tier.One), Constants.BlockName.HologramTier1, "oc:hologram1")
- Recipes.addBlock(new Hologram(Tier.Two), Constants.BlockName.HologramTier2, "oc:hologram2")
- Recipes.addBlock(new Keyboard(), Constants.BlockName.Keyboard, "oc:keyboard")
- Recipes.addBlock(new MotionSensor(), Constants.BlockName.MotionSensor, "oc:motionSensor")
- Recipes.addBlock(new PowerConverter(), Constants.BlockName.PowerConverter, "oc:powerConverter")
- Recipes.addBlock(new PowerDistributor(), Constants.BlockName.PowerDistributor, "oc:powerDistributor")
- Recipes.addBlock(new Printer(), Constants.BlockName.Printer, "oc:printer")
- Recipes.addBlock(new Raid(), Constants.BlockName.Raid, "oc:raid")
- Recipes.addBlock(new Redstone(), Constants.BlockName.Redstone, "oc:redstone")
- Recipes.addBlock(new Relay(), Constants.BlockName.Relay, "oc:relay")
- Recipes.addBlock(new Screen(Tier.One), Constants.BlockName.ScreenTier1, "oc:screen1")
- Recipes.addBlock(new Screen(Tier.Three), Constants.BlockName.ScreenTier3, "oc:screen3")
- Recipes.addBlock(new Screen(Tier.Two), Constants.BlockName.ScreenTier2, "oc:screen2")
- Recipes.addBlock(new Rack(), Constants.BlockName.Rack, "oc:rack", "oc:rack")
- Recipes.addBlock(new Waypoint(), Constants.BlockName.Waypoint, "oc:waypoint")
-
- Items.registerBlock(new Case(Tier.Four), Constants.BlockName.CaseCreative)
- Items.registerBlock(new Microcontroller(), Constants.BlockName.Microcontroller)
- Items.registerBlock(new Print(), Constants.BlockName.Print)
- Items.registerBlock(new RobotAfterimage(), Constants.BlockName.RobotAfterimage)
- Items.registerBlock(new RobotProxy(), Constants.BlockName.Robot)
+ Items.registerBlock(new Case(defaultProps, Tier.Four), Constants.BlockName.CaseCreative, defaultItemProps.rarity(Rarity.EPIC))
+ Items.registerBlock(new Microcontroller(defaultProps), Constants.BlockName.Microcontroller, new Item.Properties())
+ Items.registerBlock(new Print(Properties.of(Material.METAL).strength(1, 5).noOcclusion.dynamicShape), Constants.BlockName.Print, new Item.Properties())
+ Items.registerBlockOnly(new RobotAfterimage(Properties.of(Material.AIR).instabreak.noOcclusion.dynamicShape.air), Constants.BlockName.RobotAfterimage)
+ Items.registerBlock(new RobotProxy(defaultProps.noOcclusion.dynamicShape), Constants.BlockName.Robot, new Item.Properties())
// v1.5.10
- Recipes.addBlock(new FakeEndstone(), Constants.BlockName.Endstone, "oc:stoneEndstone")
+ Items.registerBlock(new FakeEndstone(Properties.of(Material.STONE).strength(3, 15)), Constants.BlockName.Endstone, defaultItemProps)
// v1.5.14
- Recipes.addBlock(new NetSplitter(), Constants.BlockName.NetSplitter, "oc:netSplitter")
+ Items.registerBlock(new NetSplitter(defaultProps), Constants.BlockName.NetSplitter, defaultItemProps)
// v1.5.16
- Recipes.addBlock(new Transposer(), Constants.BlockName.Transposer, "oc:transposer")
+ Items.registerBlock(new Transposer(defaultProps), Constants.BlockName.Transposer, defaultItemProps)
// v1.7.2
- Recipes.addBlock(new CarpetedCapacitor(), Constants.BlockName.CarpetedCapacitor, "oc:carpetedCapacitor")
- }
-
- private def registerTileEntity(tileEntityClass: Class[_ <: TileEntity], key: String): Unit = {
- GameRegistry.registerTileEntity(tileEntityClass, key)
+ Items.registerBlock(new CarpetedCapacitor(defaultProps), Constants.BlockName.CarpetedCapacitor, defaultItemProps)
}
}
diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala
index a7e8c5cc7f..ee8c78703d 100644
--- a/src/main/scala/li/cil/oc/common/init/Items.scala
+++ b/src/main/scala/li/cil/oc/common/init/Items.scala
@@ -3,6 +3,7 @@ package li.cil.oc.common.init
import java.util.concurrent.Callable
import li.cil.oc.Constants
+import li.cil.oc.CreativeTab
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.detail.ItemAPI
@@ -13,26 +14,25 @@ import li.cil.oc.common.Loot
import li.cil.oc.common.Tier
import li.cil.oc.common.block.SimpleBlock
import li.cil.oc.common.item
-import li.cil.oc.common.item.Delegator
import li.cil.oc.common.item.data.DroneData
import li.cil.oc.common.item.data.HoverBootsData
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.item.data.TabletData
-import li.cil.oc.common.item.traits.Delegate
import li.cil.oc.common.item.traits.SimpleItem
-import li.cil.oc.common.recipe.Recipes
import li.cil.oc.server.machine.luac.LuaStateFactory
import net.minecraft.block.Block
-import net.minecraft.creativetab.CreativeTabs
-import net.minecraft.item.EnumDyeColor
+import net.minecraft.item.BlockItem
+import net.minecraft.item.DyeColor
import net.minecraft.item.Item
-import net.minecraft.item.ItemBlock
+import net.minecraft.item.Item.Properties
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.item.Rarity
import net.minecraft.util.NonNullList
import net.minecraft.util.ResourceLocation
-import net.minecraftforge.registries.{GameData}
+import net.minecraftforge.common.ToolType
+import net.minecraftforge.registries.GameData
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
@@ -54,20 +54,13 @@ object Items extends ItemAPI {
case _ => null
}
- def registerBlock(instance: Block, id: String): Block = {
+ def registerBlockOnly(instance: Block, id: String): Block = {
if (!descriptors.contains(id)) {
instance match {
case simple: SimpleBlock =>
- instance.setUnlocalizedName("oc." + id)
- instance.setRegistryName(id)
- GameData.register_impl(instance)
- OpenComputers.proxy.registerModel(instance, id)
-
- val item : Item = new common.block.Item(instance)
- item.setUnlocalizedName("oc." + id)
- item.setRegistryName(id)
- GameData.register_impl(item)
- OpenComputers.proxy.registerModel(item, id)
+ simple.setUnlocalizedName("oc." + id)
+ simple.setRegistryName(OpenComputers.ID, id)
+ GameData.register_impl[Block](simple)
case _ =>
}
descriptors += id -> new ItemInfo {
@@ -77,9 +70,9 @@ object Items extends ItemAPI {
override def item = null
- override def createItemStack(size: Int): ItemStack = instance match {
- case simple: SimpleBlock => simple.createItemStack(size)
- case _ => new ItemStack(instance, size)
+ override def createItemStack(size: Int): ItemStack = {
+ OpenComputers.log.warn(s"Attempt to get ItemStack for block ${instance} without item form")
+ ItemStack.EMPTY
}
}
names += instance -> id
@@ -87,30 +80,44 @@ object Items extends ItemAPI {
instance
}
- def registerItem[T <: Delegate](delegate: T, id: String): T = {
+ def registerBlock(instance: Block, id: String, itemProps: Properties): Block = {
if (!descriptors.contains(id)) {
- OpenComputers.proxy.registerModel(delegate, id)
+ val itemInst = instance match {
+ case simple: SimpleBlock =>
+ simple.setUnlocalizedName("oc." + id)
+ simple.setRegistryName(OpenComputers.ID, id)
+ GameData.register_impl[Block](simple)
+
+ val item : Item = new common.block.Item(simple, itemProps)
+ item.setRegistryName(OpenComputers.ID, id)
+ GameData.register_impl(item)
+ OpenComputers.proxy.registerModel(item, id)
+ item
+ case _ => null.asInstanceOf[Item]
+ }
descriptors += id -> new ItemInfo {
override def name: String = id
- override def block = null
+ override def block = instance
- override def item: Delegator = delegate.parent
+ override def item = itemInst
- override def createItemStack(size: Int): ItemStack = delegate.createItemStack(size)
+ override def createItemStack(size: Int): ItemStack = instance match {
+ case simple: SimpleBlock => simple.createItemStack(size)
+ case _ => new ItemStack(instance, size)
+ }
}
- names += delegate -> id
+ names += instance -> id
}
- delegate
+ instance
}
def registerItem(instance: Item, id: String): Item = {
if (!descriptors.contains(id)) {
instance match {
case simple: SimpleItem =>
- simple.setUnlocalizedName("oc." + id)
GameData.register_impl(simple.setRegistryName(new ResourceLocation(Settings.resourceDomain, id)))
- OpenComputers.proxy.registerModel(instance, id)
+ OpenComputers.proxy.registerModel(simple, id)
case _ =>
}
descriptors += id -> new ItemInfo {
@@ -150,17 +157,17 @@ object Items extends ItemAPI {
private def getBlockOrItem(stack: ItemStack): Any =
if (stack.isEmpty) null
- else Delegator.subItem(stack).getOrElse(stack.getItem match {
- case block: ItemBlock => block.getBlock
+ else stack.getItem match {
+ case block: BlockItem => block.getBlock
case item => item
- })
+ }
// ----------------------------------------------------------------------- //
val registeredItems: ArrayBuffer[ItemStack] = mutable.ArrayBuffer.empty[ItemStack]
- override def registerFloppy(name: String, color: EnumDyeColor, factory: Callable[FileSystem], doRecipeCycling: Boolean): ItemStack = {
- val stack = Loot.registerLootDisk(name, color, factory, doRecipeCycling)
+ override def registerFloppy(name: String, loc: ResourceLocation, color: DyeColor, factory: Callable[FileSystem], doRecipeCycling: Boolean): ItemStack = {
+ val stack = Loot.registerLootDisk(name, loc, color, factory, doRecipeCycling)
registeredItems += stack
@@ -168,23 +175,18 @@ object Items extends ItemAPI {
}
override def registerEEPROM(name: String, code: Array[Byte], data: Array[Byte], readonly: Boolean): ItemStack = {
- val nbt = new NBTTagCompound()
+ val stack = get(Constants.ItemName.EEPROM).createItemStack(1)
+ val nbt = stack.getOrCreateTagElement(Settings.namespace + "data")
if (name != null) {
- nbt.setString(Settings.namespace + "label", name.trim.take(24))
+ nbt.putString(Settings.namespace + "label", name.trim.take(24))
}
if (code != null) {
- nbt.setByteArray(Settings.namespace + "eeprom", code.take(Settings.get.eepromSize))
+ nbt.putByteArray(Settings.namespace + "eeprom", code.take(Settings.get.eepromSize))
}
if (data != null) {
- nbt.setByteArray(Settings.namespace + "userdata", data.take(Settings.get.eepromDataSize))
+ nbt.putByteArray(Settings.namespace + "userdata", data.take(Settings.get.eepromDataSize))
}
- nbt.setBoolean(Settings.namespace + "readonly", readonly)
-
- val stackNbt = new NBTTagCompound()
- stackNbt.setTag(Settings.namespace + "data", nbt)
-
- val stack = get(Constants.ItemName.EEPROM).createItemStack(1)
- stack.setTagCompound(stackNbt)
+ nbt.putBoolean(Settings.namespace + "readonly", readonly)
registeredItems += stack
@@ -328,6 +330,8 @@ object Items extends ItemAPI {
// ----------------------------------------------------------------------- //
+ private def defaultProps = new Properties().tab(CreativeTab)
+
def init() {
initMaterials()
initTools()
@@ -345,214 +349,190 @@ object Items extends ItemAPI {
// Crafting materials.
private def initMaterials(): Unit = {
- val materials = newItem(new item.Delegator(), "material")
-
- Recipes.addSubItem(new item.CuttingWire(materials), Constants.ItemName.CuttingWire, "oc:materialCuttingWire")
- Recipes.addSubItem(new item.Acid(materials), Constants.ItemName.Acid, "oc:materialAcid")
- Recipes.addSubItem(new item.RawCircuitBoard(materials), Constants.ItemName.RawCircuitBoard, "oc:materialCircuitBoardRaw")
- Recipes.addSubItem(new item.CircuitBoard(materials), Constants.ItemName.CircuitBoard, "oc:materialCircuitBoard")
- Recipes.addSubItem(new item.PrintedCircuitBoard(materials), Constants.ItemName.PrintedCircuitBoard, "oc:materialCircuitBoardPrinted")
- Recipes.addSubItem(new item.CardBase(materials), Constants.ItemName.Card, "oc:materialCard")
- Recipes.addSubItem(new item.Transistor(materials), Constants.ItemName.Transistor, "oc:materialTransistor")
- Recipes.addSubItem(new item.Microchip(materials, Tier.One), Constants.ItemName.ChipTier1, "oc:circuitChip1")
- Recipes.addSubItem(new item.Microchip(materials, Tier.Two), Constants.ItemName.ChipTier2, "oc:circuitChip2")
- Recipes.addSubItem(new item.Microchip(materials, Tier.Three), Constants.ItemName.ChipTier3, "oc:circuitChip3")
- Recipes.addSubItem(new item.ALU(materials), Constants.ItemName.Alu, "oc:materialALU")
- Recipes.addSubItem(new item.ControlUnit(materials), Constants.ItemName.ControlUnit, "oc:materialCU")
- Recipes.addSubItem(new item.Disk(materials), Constants.ItemName.Disk, "oc:materialDisk")
- Recipes.addSubItem(new item.Interweb(materials), Constants.ItemName.Interweb, "oc:materialInterweb")
- Recipes.addSubItem(new item.ButtonGroup(materials), Constants.ItemName.ButtonGroup, "oc:materialButtonGroup")
- Recipes.addSubItem(new item.ArrowKeys(materials), Constants.ItemName.ArrowKeys, "oc:materialArrowKey")
- Recipes.addSubItem(new item.NumPad(materials), Constants.ItemName.NumPad, "oc:materialNumPad")
-
- Recipes.addSubItem(new item.TabletCase(materials, Tier.One), Constants.ItemName.TabletCaseTier1, "oc:tabletCase1")
- Recipes.addSubItem(new item.TabletCase(materials, Tier.Two), Constants.ItemName.TabletCaseTier2, "oc:tabletCase2")
- registerItem(new item.TabletCase(materials, Tier.Four), Constants.ItemName.TabletCaseCreative)
- Recipes.addSubItem(new item.MicrocontrollerCase(materials, Tier.One), Constants.ItemName.MicrocontrollerCaseTier1, "oc:microcontrollerCase1")
- Recipes.addSubItem(new item.MicrocontrollerCase(materials, Tier.Two), Constants.ItemName.MicrocontrollerCaseTier2, "oc:microcontrollerCase2")
- registerItem(new item.MicrocontrollerCase(materials, Tier.Four), Constants.ItemName.MicrocontrollerCaseCreative)
- Recipes.addSubItem(new item.DroneCase(materials, Tier.One), Constants.ItemName.DroneCaseTier1, "oc:droneCase1")
- Recipes.addSubItem(new item.DroneCase(materials, Tier.Two), Constants.ItemName.DroneCaseTier2, "oc:droneCase2")
- registerItem(new item.DroneCase(materials, Tier.Four), Constants.ItemName.DroneCaseCreative)
-
- Recipes.addSubItem(new item.InkCartridgeEmpty(materials), Constants.ItemName.InkCartridgeEmpty, "oc:inkCartridgeEmpty")
- Recipes.addSubItem(new item.InkCartridge(materials), Constants.ItemName.InkCartridge, "oc:inkCartridge")
- Recipes.addSubItem(new item.Chamelium(materials), Constants.ItemName.Chamelium, "oc:chamelium")
-
- registerItem(new item.DiamondChip(materials), Constants.ItemName.DiamondChip)
+ registerItem(new item.CuttingWire(defaultProps), Constants.ItemName.CuttingWire)
+ registerItem(new item.Acid(defaultProps), Constants.ItemName.Acid)
+ registerItem(new item.RawCircuitBoard(defaultProps), Constants.ItemName.RawCircuitBoard)
+ registerItem(new item.CircuitBoard(defaultProps), Constants.ItemName.CircuitBoard)
+ registerItem(new item.PrintedCircuitBoard(defaultProps), Constants.ItemName.PrintedCircuitBoard)
+ registerItem(new item.CardBase(defaultProps), Constants.ItemName.Card)
+ registerItem(new item.Transistor(defaultProps), Constants.ItemName.Transistor)
+ registerItem(new item.Microchip(defaultProps, Tier.One), Constants.ItemName.ChipTier1)
+ registerItem(new item.Microchip(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.ChipTier2)
+ registerItem(new item.Microchip(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.ChipTier3)
+ registerItem(new item.ALU(defaultProps), Constants.ItemName.Alu)
+ registerItem(new item.ControlUnit(defaultProps), Constants.ItemName.ControlUnit)
+ registerItem(new item.Disk(defaultProps), Constants.ItemName.Disk)
+ registerItem(new item.Interweb(defaultProps), Constants.ItemName.Interweb)
+ registerItem(new item.ButtonGroup(defaultProps), Constants.ItemName.ButtonGroup)
+ registerItem(new item.ArrowKeys(defaultProps), Constants.ItemName.ArrowKeys)
+ registerItem(new item.NumPad(defaultProps), Constants.ItemName.NumPad)
+
+ registerItem(new item.TabletCase(defaultProps, Tier.One), Constants.ItemName.TabletCaseTier1)
+ registerItem(new item.TabletCase(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.TabletCaseTier2)
+ registerItem(new item.TabletCase(defaultProps.rarity(Rarity.EPIC), Tier.Four), Constants.ItemName.TabletCaseCreative)
+ registerItem(new item.MicrocontrollerCase(defaultProps, Tier.One), Constants.ItemName.MicrocontrollerCaseTier1)
+ registerItem(new item.MicrocontrollerCase(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.MicrocontrollerCaseTier2)
+ registerItem(new item.MicrocontrollerCase(defaultProps.rarity(Rarity.EPIC), Tier.Four), Constants.ItemName.MicrocontrollerCaseCreative)
+ registerItem(new item.DroneCase(defaultProps, Tier.One), Constants.ItemName.DroneCaseTier1)
+ registerItem(new item.DroneCase(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.DroneCaseTier2)
+ registerItem(new item.DroneCase(defaultProps.rarity(Rarity.EPIC), Tier.Four), Constants.ItemName.DroneCaseCreative)
+
+ registerItem(new item.InkCartridgeEmpty(defaultProps.stacksTo(1)), Constants.ItemName.InkCartridgeEmpty)
+ registerItem(new item.InkCartridge(defaultProps.stacksTo(1).craftRemainder(get(Constants.ItemName.InkCartridgeEmpty).item)), Constants.ItemName.InkCartridge)
+ registerItem(new item.Chamelium(defaultProps), Constants.ItemName.Chamelium)
+
+ registerItem(new item.DiamondChip(defaultProps), Constants.ItemName.DiamondChip)
}
+ val WrenchType: ToolType = ToolType.get("wrench")
+
// All kinds of tools.
private def initTools(): Unit = {
- val tools = newItem(new item.Delegator(), "tool")
-
- Recipes.addSubItem(new item.Analyzer(tools), Constants.ItemName.Analyzer, "oc:analyzer")
- registerItem(new item.Debugger(tools), Constants.ItemName.Debugger)
- Recipes.addSubItem(new item.Terminal(tools), Constants.ItemName.Terminal, "oc:terminal")
- Recipes.addSubItem(new item.TexturePicker(tools), Constants.ItemName.TexturePicker, "oc:texturePicker")
- Recipes.addSubItem(new item.Manual(tools), Constants.ItemName.Manual, "oc:manual")
- Recipes.addItem(new item.Wrench(), Constants.ItemName.Wrench, "oc:wrench")
+ registerItem(new item.Analyzer(defaultProps), Constants.ItemName.Analyzer)
+ registerItem(new item.Debugger(defaultProps), Constants.ItemName.Debugger)
+ registerItem(new item.Terminal(defaultProps.stacksTo(1)), Constants.ItemName.Terminal)
+ registerItem(new item.TexturePicker(defaultProps), Constants.ItemName.TexturePicker)
+ registerItem(new item.Manual(defaultProps), Constants.ItemName.Manual)
+ registerItem(new item.Wrench(defaultProps.stacksTo(1).addToolType(WrenchType, 1)), Constants.ItemName.Wrench)
// 1.5.11
- Recipes.addItem(new item.HoverBoots(), Constants.ItemName.HoverBoots, "oc:hoverBoots")
+ registerItem(new item.HoverBoots(defaultProps.stacksTo(1).rarity(Rarity.UNCOMMON).setNoRepair), Constants.ItemName.HoverBoots)
// 1.5.18
- Recipes.addSubItem(new item.Nanomachines(tools), Constants.ItemName.Nanomachines, "oc:nanomachines")
+ registerItem(new item.Nanomachines(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.Nanomachines)
}
// General purpose components.
private def initComponents(): Unit = {
- val components = newItem(new item.Delegator(), "component")
-
- Recipes.addSubItem(new item.CPU(components, Tier.One), Constants.ItemName.CPUTier1, "oc:cpu1")
- Recipes.addSubItem(new item.CPU(components, Tier.Two), Constants.ItemName.CPUTier2, "oc:cpu2")
- Recipes.addSubItem(new item.CPU(components, Tier.Three), Constants.ItemName.CPUTier3, "oc:cpu3")
-
- Recipes.addSubItem(new item.ComponentBus(components, Tier.One), Constants.ItemName.ComponentBusTier1, "oc:componentBus1")
- Recipes.addSubItem(new item.ComponentBus(components, Tier.Two), Constants.ItemName.ComponentBusTier2, "oc:componentBus2")
- Recipes.addSubItem(new item.ComponentBus(components, Tier.Three), Constants.ItemName.ComponentBusTier3, "oc:componentBus3")
-
- Recipes.addSubItem(new item.Memory(components, Tier.One), Constants.ItemName.RAMTier1, "oc:ram1")
- Recipes.addSubItem(new item.Memory(components, Tier.Two), Constants.ItemName.RAMTier2, "oc:ram2")
- Recipes.addSubItem(new item.Memory(components, Tier.Three), Constants.ItemName.RAMTier3, "oc:ram3")
- Recipes.addSubItem(new item.Memory(components, Tier.Four), Constants.ItemName.RAMTier4, "oc:ram4")
- Recipes.addSubItem(new item.Memory(components, Tier.Five), Constants.ItemName.RAMTier5, "oc:ram5")
- Recipes.addSubItem(new item.Memory(components, Tier.Six), Constants.ItemName.RAMTier6, "oc:ram6")
-
- registerItem(new item.Server(components, Tier.Four), Constants.ItemName.ServerCreative)
- Recipes.addSubItem(new item.Server(components, Tier.One), Constants.ItemName.ServerTier1, "oc:server1")
- Recipes.addSubItem(new item.Server(components, Tier.Two), Constants.ItemName.ServerTier2, "oc:server2")
- Recipes.addSubItem(new item.Server(components, Tier.Three), Constants.ItemName.ServerTier3, "oc:server3")
+ registerItem(new item.CPU(defaultProps, Tier.One), Constants.ItemName.CPUTier1)
+ registerItem(new item.CPU(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.CPUTier2)
+ registerItem(new item.CPU(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.CPUTier3)
+
+ registerItem(new item.ComponentBus(defaultProps, Tier.One), Constants.ItemName.ComponentBusTier1)
+ registerItem(new item.ComponentBus(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.ComponentBusTier2)
+ registerItem(new item.ComponentBus(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.ComponentBusTier3)
+
+ registerItem(new item.Memory(defaultProps, Tier.One), Constants.ItemName.RAMTier1)
+ registerItem(new item.Memory(defaultProps, Tier.Two), Constants.ItemName.RAMTier2)
+ registerItem(new item.Memory(defaultProps.rarity(Rarity.UNCOMMON), Tier.Three), Constants.ItemName.RAMTier3)
+ registerItem(new item.Memory(defaultProps.rarity(Rarity.UNCOMMON), Tier.Four), Constants.ItemName.RAMTier4)
+ registerItem(new item.Memory(defaultProps.rarity(Rarity.RARE), Tier.Five), Constants.ItemName.RAMTier5)
+ registerItem(new item.Memory(defaultProps.rarity(Rarity.RARE), Tier.Six), Constants.ItemName.RAMTier6)
+
+ registerItem(new item.Server(defaultProps.stacksTo(1).rarity(Rarity.EPIC), Tier.Four), Constants.ItemName.ServerCreative)
+ registerItem(new item.Server(defaultProps.stacksTo(1), Tier.One), Constants.ItemName.ServerTier1)
+ registerItem(new item.Server(defaultProps.stacksTo(1).rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.ServerTier2)
+ registerItem(new item.Server(defaultProps.stacksTo(1).rarity(Rarity.RARE), Tier.Three), Constants.ItemName.ServerTier3)
// 1.5.10
- Recipes.addSubItem(new item.APU(components, Tier.One), Constants.ItemName.APUTier1, "oc:apu1")
- Recipes.addSubItem(new item.APU(components, Tier.Two), Constants.ItemName.APUTier2, "oc:apu2")
+ registerItem(new item.APU(defaultProps.rarity(Rarity.UNCOMMON), Tier.One), Constants.ItemName.APUTier1)
+ registerItem(new item.APU(defaultProps.rarity(Rarity.RARE), Tier.Two), Constants.ItemName.APUTier2)
// 1.5.12
- registerItem(new item.APU(components, Tier.Three), Constants.ItemName.APUCreative)
+ registerItem(new item.APU(defaultProps.rarity(Rarity.EPIC), Tier.Three), Constants.ItemName.APUCreative)
// 1.6
- Recipes.addSubItem(new item.TerminalServer(components), Constants.ItemName.TerminalServer, "oc:terminalServer")
- Recipes.addSubItem(new item.DiskDriveMountable(components), Constants.ItemName.DiskDriveMountable, "oc:diskDriveMountable")
+ registerItem(new item.TerminalServer(defaultProps.stacksTo(1)), Constants.ItemName.TerminalServer)
+ registerItem(new item.DiskDriveMountable(defaultProps.stacksTo(1)), Constants.ItemName.DiskDriveMountable)
}
// Card components.
private def initCards(): Unit = {
- val cards = newItem(new item.Delegator(), "card")
-
- registerItem(new item.DebugCard(cards), Constants.ItemName.DebugCard)
- Recipes.addSubItem(new item.GraphicsCard(cards, Tier.One), Constants.ItemName.GraphicsCardTier1, "oc:graphicsCard1")
- Recipes.addSubItem(new item.GraphicsCard(cards, Tier.Two), Constants.ItemName.GraphicsCardTier2, "oc:graphicsCard2")
- Recipes.addSubItem(new item.GraphicsCard(cards, Tier.Three), Constants.ItemName.GraphicsCardTier3, "oc:graphicsCard3")
- Recipes.addSubItem(new item.RedstoneCard(cards, Tier.One), Constants.ItemName.RedstoneCardTier1, "oc:redstoneCard1")
- Recipes.addSubItem(new item.RedstoneCard(cards, Tier.Two), Constants.ItemName.RedstoneCardTier2, "oc:redstoneCard2")
- Recipes.addSubItem(new item.NetworkCard(cards), Constants.ItemName.NetworkCard, "oc:lanCard")
- Recipes.addSubItem(new item.WirelessNetworkCard(cards, Tier.Two), Constants.ItemName.WirelessNetworkCardTier2, "oc:wlanCard2")
- Recipes.addSubItem(new item.InternetCard(cards), Constants.ItemName.InternetCard, "oc:internetCard")
- Recipes.addSubItem(new item.LinkedCard(cards), Constants.ItemName.LinkedCard, "oc:linkedCard")
+ registerItem(new item.DebugCard(defaultProps), Constants.ItemName.DebugCard)
+ registerItem(new item.GraphicsCard(defaultProps, Tier.One), Constants.ItemName.GraphicsCardTier1)
+ registerItem(new item.GraphicsCard(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.GraphicsCardTier2)
+ registerItem(new item.GraphicsCard(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.GraphicsCardTier3)
+ registerItem(new item.RedstoneCard(defaultProps, Tier.One), Constants.ItemName.RedstoneCardTier1)
+ registerItem(new item.RedstoneCard(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.RedstoneCardTier2)
+ registerItem(new item.NetworkCard(defaultProps), Constants.ItemName.NetworkCard)
+ registerItem(new item.WirelessNetworkCard(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.WirelessNetworkCardTier2)
+ registerItem(new item.InternetCard(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.InternetCard)
+ registerItem(new item.LinkedCard(defaultProps.rarity(Rarity.RARE)), Constants.ItemName.LinkedCard)
// 1.5.13
- Recipes.addSubItem(new item.DataCard(cards, Tier.One), Constants.ItemName.DataCardTier1, "oc:dataCard1")
+ registerItem(new item.DataCard(defaultProps, Tier.One), Constants.ItemName.DataCardTier1)
// 1.5.15
- Recipes.addSubItem(new item.DataCard(cards, Tier.Two), Constants.ItemName.DataCardTier2, "oc:dataCard2")
- Recipes.addSubItem(new item.DataCard(cards, Tier.Three), Constants.ItemName.DataCardTier3, "oc:dataCard3")
+ registerItem(new item.DataCard(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.DataCardTier2)
+ registerItem(new item.DataCard(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.DataCardTier3)
}
// Upgrade components.
private def initUpgrades(): Unit = {
- val upgrades = newItem(new item.Delegator(), "upgrade")
-
- Recipes.addSubItem(new item.UpgradeAngel(upgrades), Constants.ItemName.AngelUpgrade, "oc:angelUpgrade")
- Recipes.addSubItem(new item.UpgradeBattery(upgrades, Tier.One), Constants.ItemName.BatteryUpgradeTier1, "oc:batteryUpgrade1")
- Recipes.addSubItem(new item.UpgradeBattery(upgrades, Tier.Two), Constants.ItemName.BatteryUpgradeTier2, "oc:batteryUpgrade2")
- Recipes.addSubItem(new item.UpgradeBattery(upgrades, Tier.Three), Constants.ItemName.BatteryUpgradeTier3, "oc:batteryUpgrade3")
- Recipes.addSubItem(new item.UpgradeChunkloader(upgrades), Constants.ItemName.ChunkloaderUpgrade, "oc:chunkloaderUpgrade")
- Recipes.addSubItem(new item.UpgradeContainerCard(upgrades, Tier.One), Constants.ItemName.CardContainerTier1, "oc:cardContainer1")
- Recipes.addSubItem(new item.UpgradeContainerCard(upgrades, Tier.Two), Constants.ItemName.CardContainerTier2, "oc:cardContainer2")
- Recipes.addSubItem(new item.UpgradeContainerCard(upgrades, Tier.Three), Constants.ItemName.CardContainerTier3, "oc:cardContainer3")
- Recipes.addSubItem(new item.UpgradeContainerUpgrade(upgrades, Tier.One), Constants.ItemName.UpgradeContainerTier1, "oc:upgradeContainer1")
- Recipes.addSubItem(new item.UpgradeContainerUpgrade(upgrades, Tier.Two), Constants.ItemName.UpgradeContainerTier2, "oc:upgradeContainer2")
- Recipes.addSubItem(new item.UpgradeContainerUpgrade(upgrades, Tier.Three), Constants.ItemName.UpgradeContainerTier3, "oc:upgradeContainer3")
- Recipes.addSubItem(new item.UpgradeCrafting(upgrades), Constants.ItemName.CraftingUpgrade, "oc:craftingUpgrade")
- Recipes.addSubItem(new item.UpgradeDatabase(upgrades, Tier.One), Constants.ItemName.DatabaseUpgradeTier1, "oc:databaseUpgrade1")
- Recipes.addSubItem(new item.UpgradeDatabase(upgrades, Tier.Two), Constants.ItemName.DatabaseUpgradeTier2, "oc:databaseUpgrade2")
- Recipes.addSubItem(new item.UpgradeDatabase(upgrades, Tier.Three), Constants.ItemName.DatabaseUpgradeTier3, "oc:databaseUpgrade3")
- Recipes.addSubItem(new item.UpgradeExperience(upgrades), Constants.ItemName.ExperienceUpgrade, "oc:experienceUpgrade")
- Recipes.addSubItem(new item.UpgradeGenerator(upgrades), Constants.ItemName.GeneratorUpgrade, "oc:generatorUpgrade")
- Recipes.addSubItem(new item.UpgradeInventory(upgrades), Constants.ItemName.InventoryUpgrade, "oc:inventoryUpgrade")
- Recipes.addSubItem(new item.UpgradeInventoryController(upgrades), Constants.ItemName.InventoryControllerUpgrade, "oc:inventoryControllerUpgrade")
- Recipes.addSubItem(new item.UpgradeNavigation(upgrades), Constants.ItemName.NavigationUpgrade, "oc:navigationUpgrade")
- Recipes.addSubItem(new item.UpgradePiston(upgrades), Constants.ItemName.PistonUpgrade, "oc:pistonUpgrade")
- Recipes.addSubItem(new item.UpgradeSign(upgrades), Constants.ItemName.SignUpgrade, "oc:signUpgrade")
- Recipes.addSubItem(new item.UpgradeSolarGenerator(upgrades), Constants.ItemName.SolarGeneratorUpgrade, "oc:solarGeneratorUpgrade")
- Recipes.addSubItem(new item.UpgradeTank(upgrades), Constants.ItemName.TankUpgrade, "oc:tankUpgrade")
- Recipes.addSubItem(new item.UpgradeTankController(upgrades), Constants.ItemName.TankControllerUpgrade, "oc:tankControllerUpgrade")
- Recipes.addSubItem(new item.UpgradeTractorBeam(upgrades), Constants.ItemName.TractorBeamUpgrade, "oc:tractorBeamUpgrade")
- Recipes.addSubItem(new item.UpgradeLeash(upgrades), Constants.ItemName.LeashUpgrade, "oc:leashUpgrade")
+ registerItem(new item.UpgradeAngel(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.AngelUpgrade)
+ registerItem(new item.UpgradeBattery(defaultProps, Tier.One), Constants.ItemName.BatteryUpgradeTier1)
+ registerItem(new item.UpgradeBattery(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.BatteryUpgradeTier2)
+ registerItem(new item.UpgradeBattery(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.BatteryUpgradeTier3)
+ registerItem(new item.UpgradeChunkloader(defaultProps.rarity(Rarity.RARE)), Constants.ItemName.ChunkloaderUpgrade)
+ registerItem(new item.UpgradeContainerCard(defaultProps, Tier.One), Constants.ItemName.CardContainerTier1)
+ registerItem(new item.UpgradeContainerCard(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.CardContainerTier2)
+ registerItem(new item.UpgradeContainerCard(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.CardContainerTier3)
+ registerItem(new item.UpgradeContainerUpgrade(defaultProps, Tier.One), Constants.ItemName.UpgradeContainerTier1)
+ registerItem(new item.UpgradeContainerUpgrade(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.UpgradeContainerTier2)
+ registerItem(new item.UpgradeContainerUpgrade(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.UpgradeContainerTier3)
+ registerItem(new item.UpgradeCrafting(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.CraftingUpgrade)
+ registerItem(new item.UpgradeDatabase(defaultProps, Tier.One), Constants.ItemName.DatabaseUpgradeTier1)
+ registerItem(new item.UpgradeDatabase(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.DatabaseUpgradeTier2)
+ registerItem(new item.UpgradeDatabase(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.DatabaseUpgradeTier3)
+ registerItem(new item.UpgradeExperience(defaultProps.rarity(Rarity.RARE)), Constants.ItemName.ExperienceUpgrade)
+ registerItem(new item.UpgradeGenerator(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.GeneratorUpgrade)
+ registerItem(new item.UpgradeInventory(defaultProps), Constants.ItemName.InventoryUpgrade)
+ registerItem(new item.UpgradeInventoryController(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.InventoryControllerUpgrade)
+ registerItem(new item.UpgradeNavigation(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.NavigationUpgrade)
+ registerItem(new item.UpgradePiston(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.PistonUpgrade)
+ registerItem(new item.UpgradeSign(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.SignUpgrade)
+ registerItem(new item.UpgradeSolarGenerator(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.SolarGeneratorUpgrade)
+ registerItem(new item.UpgradeTank(defaultProps), Constants.ItemName.TankUpgrade)
+ registerItem(new item.UpgradeTankController(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.TankControllerUpgrade)
+ registerItem(new item.UpgradeTractorBeam(defaultProps.rarity(Rarity.RARE)), Constants.ItemName.TractorBeamUpgrade)
+ registerItem(new item.UpgradeLeash(defaultProps), Constants.ItemName.LeashUpgrade)
// 1.5.8
- Recipes.addSubItem(new item.UpgradeHover(upgrades, Tier.One), Constants.ItemName.HoverUpgradeTier1, "oc:hoverUpgrade1")
- Recipes.addSubItem(new item.UpgradeHover(upgrades, Tier.Two), Constants.ItemName.HoverUpgradeTier2, "oc:hoverUpgrade2")
+ registerItem(new item.UpgradeHover(defaultProps, Tier.One), Constants.ItemName.HoverUpgradeTier1)
+ registerItem(new item.UpgradeHover(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.HoverUpgradeTier2)
// 1.6
- Recipes.addSubItem(new item.UpgradeTrading(upgrades), Constants.ItemName.TradingUpgrade, "oc:tradingUpgrade")
- Recipes.addSubItem(new item.UpgradeMF(upgrades), Constants.ItemName.MFU, "oc:mfu")
+ registerItem(new item.UpgradeTrading(defaultProps.rarity(Rarity.UNCOMMON)), Constants.ItemName.TradingUpgrade)
+ registerItem(new item.UpgradeMF(defaultProps.rarity(Rarity.RARE)), Constants.ItemName.MFU)
// 1.7.2
- Recipes.addSubItem(new item.WirelessNetworkCard(upgrades, Tier.One), Constants.ItemName.WirelessNetworkCardTier1, "oc:wlanCard1")
- registerItem(new item.ComponentBus(upgrades, Tier.Four), Constants.ItemName.ComponentBusCreative)
+ registerItem(new item.WirelessNetworkCard(defaultProps, Tier.One), Constants.ItemName.WirelessNetworkCardTier1)
+ registerItem(new item.ComponentBus(defaultProps.rarity(Rarity.EPIC), Tier.Four), Constants.ItemName.ComponentBusCreative)
// 1.8
- Recipes.addSubItem(new item.UpgradeStickyPiston(upgrades), Constants.ItemName.StickyPistonUpgrade, "oc:stickyPistonUpgrade")
+ registerItem(new item.UpgradeStickyPiston(defaultProps), Constants.ItemName.StickyPistonUpgrade)
}
// Storage media of all kinds.
private def initStorage(): Unit = {
- val storage = newItem(new item.Delegator(), "storage")
-
- Recipes.addSubItem(new item.EEPROM(storage), Constants.ItemName.EEPROM, "oc:eeprom")
- Recipes.addSubItem(new item.FloppyDisk(storage), Constants.ItemName.Floppy, "oc:floppy")
- Recipes.addSubItem(new item.HardDiskDrive(storage, Tier.One), Constants.ItemName.HDDTier1, "oc:hdd1")
- Recipes.addSubItem(new item.HardDiskDrive(storage, Tier.Two), Constants.ItemName.HDDTier2, "oc:hdd2")
- Recipes.addSubItem(new item.HardDiskDrive(storage, Tier.Three), Constants.ItemName.HDDTier3, "oc:hdd3")
+ registerItem(new item.EEPROM(defaultProps), Constants.ItemName.EEPROM)
+ registerItem(new item.FloppyDisk(defaultProps), Constants.ItemName.Floppy)
+ registerItem(new item.HardDiskDrive(defaultProps, Tier.One), Constants.ItemName.HDDTier1)
+ registerItem(new item.HardDiskDrive(defaultProps.rarity(Rarity.UNCOMMON), Tier.Two), Constants.ItemName.HDDTier2)
+ registerItem(new item.HardDiskDrive(defaultProps.rarity(Rarity.RARE), Tier.Three), Constants.ItemName.HDDTier3)
val luaBios = {
val code = new Array[Byte](4 * 1024)
val count = OpenComputers.getClass.getResourceAsStream(Settings.scriptPath + "bios.lua").read(code)
registerEEPROM("EEPROM (Lua BIOS)", code.take(count), null, readonly = false)
}
- Recipes.addStack(luaBios, Constants.ItemName.LuaBios)
+ registerStack(luaBios, Constants.ItemName.LuaBios)
}
// Special purpose items that don't fit into any other category.
private def initSpecial(): Unit = {
- val misc = newItem(new item.Delegator() {
- private def configuredItems = Array(
- Items.createConfiguredDrone(),
- Items.createConfiguredMicrocontroller(),
- Items.createConfiguredRobot(),
- Items.createConfiguredTablet(),
- Items.createChargedHoverBoots()
- ) ++ Loot.disksForClient ++ registeredItems
-
- override def getSubItems(tab: CreativeTabs, list: NonNullList[ItemStack]): Unit = {
- super.getSubItems(tab, list)
- if(isInCreativeTab(tab)){
- configuredItems.foreach(list.add)
- }
- }
- }, "misc")
-
- registerItem(new item.Tablet(misc), Constants.ItemName.Tablet)
- registerItem(new item.Drone(misc), Constants.ItemName.Drone)
- registerItem(new item.Present(misc), Constants.ItemName.Present)
+ registerItem(new item.Tablet(defaultProps.stacksTo(1)), Constants.ItemName.Tablet)
+ registerItem(new item.Drone(defaultProps), Constants.ItemName.Drone)
+ registerItem(new item.Present(defaultProps), Constants.ItemName.Present)
}
- private def newItem[T <: Item](item: T, name: String): T = {
- item.setUnlocalizedName("oc." + name)
- GameData.register_impl(item.setRegistryName(new ResourceLocation(Settings.resourceDomain, name)))
- item
+ def decorateCreativeTab(list: NonNullList[ItemStack]) {
+ list.add(Items.createConfiguredDrone())
+ list.add(Items.createConfiguredMicrocontroller())
+ list.add(Items.createConfiguredRobot())
+ list.add(Items.createConfiguredTablet())
+ Loot.disksForClient.foreach(list.add)
+ registeredItems.foreach(list.add)
}
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala
index 7fbdf4be94..8ec5e5f402 100644
--- a/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala
@@ -11,9 +11,9 @@ import li.cil.oc.api.network.Node
import li.cil.oc.api.util.Lifecycle
import li.cil.oc.integration.opencomputers.Item
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
trait ComponentInventory extends Inventory with network.Environment {
@@ -22,7 +22,7 @@ trait ComponentInventory extends Inventory with network.Environment {
def components: Array[Option[ManagedEnvironment]] = {
if (_components == null && isSizeInventoryReady) {
- _components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None)
+ _components = Array.fill[Option[ManagedEnvironment]](getContainerSize)(None)
}
if (_components == null) Array[Option[ManagedEnvironment]]() else _components
}
@@ -53,8 +53,8 @@ trait ComponentInventory extends Inventory with network.Environment {
// ----------------------------------------------------------------------- //
def connectComponents() {
- for (slot <- 0 until getSizeInventory if slot >= 0 && slot < components.length) {
- val stack = getStackInSlot(slot)
+ for (slot <- 0 until getContainerSize if slot >= 0 && slot < components.length) {
+ val stack = getItem(slot)
if (!stack.isEmpty && components(slot).isEmpty && isComponentSlot(slot, stack)) {
components(slot) = Option(Driver.driverFor(stack)) match {
case Some(driver) =>
@@ -62,7 +62,7 @@ trait ComponentInventory extends Inventory with network.Environment {
case Some(component) =>
applyLifecycleState(component, Lifecycle.LifecycleState.Constructing)
try {
- component.load(dataTag(driver, stack))
+ component.loadData(dataTag(driver, stack))
}
catch {
case e: Throwable => OpenComputers.log.warn(s"An item component of type '${component.getClass.getName}' (provided by driver '${driver.getClass.getName}') threw an error while loading.", e)
@@ -99,20 +99,20 @@ trait ComponentInventory extends Inventory with network.Environment {
// ----------------------------------------------------------------------- //
- override def save(nbt: NBTTagCompound) = {
+ override def saveData(nbt: CompoundNBT) {
saveComponents()
- super.save(nbt) // Save items after updating their tags.
+ super.saveData(nbt) // Save items after updating their tags.
}
def saveComponents() {
- for (slot <- 0 until getSizeInventory) {
- val stack = getStackInSlot(slot)
+ for (slot <- 0 until getContainerSize) {
+ val stack = getItem(slot)
if (!stack.isEmpty) {
if (slot >= components.length) {
// isSizeInventoryReady was added to resolve issues where an inventory was used before its
// nbt data had been parsed. See https://github.com/MightyPirates/OpenComputers/issues/2522
// If this error is hit again, perhaps another subtype needs to handle nbt loading like Case does
- OpenComputers.log.error(s"ComponentInventory components length ${components.length} does not accommodate inventory size ${getSizeInventory}")
+ OpenComputers.log.error(s"ComponentInventory components length ${components.length} does not accommodate inventory size ${getContainerSize}")
return
} else {
components(slot) match {
@@ -128,7 +128,7 @@ trait ComponentInventory extends Inventory with network.Environment {
// ----------------------------------------------------------------------- //
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
override protected def onItemAdded(slot: Int, stack: ItemStack) = if (slot >= 0 && slot < components.length && isComponentSlot(slot, stack)) {
Option(Driver.driverFor(stack)).foreach(driver =>
@@ -137,7 +137,7 @@ trait ComponentInventory extends Inventory with network.Environment {
components(slot) = Some(component)
applyLifecycleState(component, Lifecycle.LifecycleState.Constructing)
try {
- component.load(dataTag(driver, stack))
+ component.loadData(dataTag(driver, stack))
} catch {
case e: Throwable => OpenComputers.log.warn(s"An item component of type '${component.getClass.getName}' (provided by driver '${driver.getClass.getName}') threw an error while loading.", e)
}
@@ -194,10 +194,10 @@ trait ComponentInventory extends Inventory with network.Environment {
val tag = dataTag(driver, stack)
// Clear the tag compound before saving to get the same behavior as
// in tile entities (otherwise entries have to be cleared manually).
- for (key <- tag.getKeySet.map(_.asInstanceOf[String])) {
- tag.removeTag(key)
+ for (key <- tag.getAllKeys.map(_.asInstanceOf[String])) {
+ tag.remove(key)
}
- component.save(tag)
+ component.saveData(tag)
} catch {
case e: Throwable => OpenComputers.log.warn(s"An item component of type '${component.getClass.getName}' (provided by driver '${driver.getClass.getName}') threw an error while saving.", e)
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/DatabaseInventory.scala b/src/main/scala/li/cil/oc/common/inventory/DatabaseInventory.scala
index 086ab83424..a1fcba76b4 100644
--- a/src/main/scala/li/cil/oc/common/inventory/DatabaseInventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/DatabaseInventory.scala
@@ -1,19 +1,30 @@
package li.cil.oc.common.inventory
import li.cil.oc.Settings
+import li.cil.oc.common.container.ContainerTypes
+import li.cil.oc.common.container.{Database => DatabaseContainer}
import li.cil.oc.integration.opencomputers.DriverUpgradeDatabase
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.StringTextComponent
-trait DatabaseInventory extends ItemStackInventory {
+trait DatabaseInventory extends ItemStackInventory with INamedContainerProvider {
def tier: Int = DriverUpgradeDatabase.tier(container)
- override def getSizeInventory = Settings.get.databaseEntriesPerTier(tier)
+ override def getContainerSize = Settings.get.databaseEntriesPerTier(tier)
override protected def inventoryName = "database"
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
override def getInventoryStackRequired = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack) = stack != container
+ override def canPlaceItem(slot: Int, stack: ItemStack) = stack != container
+
+ override def getDisplayName = StringTextComponent.EMPTY
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new DatabaseContainer(ContainerTypes.DATABASE, id, playerInventory, container, this, tier)
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/DiskDriveMountableInventory.scala b/src/main/scala/li/cil/oc/common/inventory/DiskDriveMountableInventory.scala
index 58a00ca8da..3bbd9abeac 100644
--- a/src/main/scala/li/cil/oc/common/inventory/DiskDriveMountableInventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/DiskDriveMountableInventory.scala
@@ -1,21 +1,32 @@
package li.cil.oc.common.inventory
import li.cil.oc.api.Driver
-import li.cil.oc.common.tileentity
import li.cil.oc.common.Slot
+import li.cil.oc.common.container.ContainerTypes
+import li.cil.oc.common.container.{DiskDrive => DiskDriveContainer}
+import li.cil.oc.common.tileentity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.StringTextComponent
-trait DiskDriveMountableInventory extends ItemStackInventory {
+trait DiskDriveMountableInventory extends ItemStackInventory with INamedContainerProvider {
def tier: Int = 1
- override def getSizeInventory = 1
+ override def getContainerSize = 1
override protected def inventoryName = "diskdrive"
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, classOf[tileentity.DiskDrive]))) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, classOf[tileentity.DiskDrive]))) match {
case (0, Some(driver)) => driver.slot(stack) == Slot.Floppy
case _ => false
}
+
+ override def getDisplayName = StringTextComponent.EMPTY
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new DiskDriveContainer(ContainerTypes.DISK_DRIVE, id, playerInventory, this)
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/Inventory.scala b/src/main/scala/li/cil/oc/common/inventory/Inventory.scala
index 74fd0e8bd0..174f2efbb8 100644
--- a/src/main/scala/li/cil/oc/common/inventory/Inventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/Inventory.scala
@@ -4,7 +4,9 @@ import li.cil.oc.Settings
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.StackOption
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.TranslationTextComponent
import net.minecraftforge.common.util.Constants.NBT
trait Inventory extends SimpleInventory {
@@ -14,12 +16,12 @@ trait Inventory extends SimpleInventory {
// ----------------------------------------------------------------------- //
- override def getStackInSlot(slot: Int): ItemStack =
- if (slot >= 0 && slot < getSizeInventory) items(slot)
+ override def getItem(slot: Int): ItemStack =
+ if (slot >= 0 && slot < getContainerSize) items(slot)
else ItemStack.EMPTY
- override def setInventorySlotContents(slot: Int, stack: ItemStack): Unit = {
- if (slot >= 0 && slot < getSizeInventory) {
+ override def setItem(slot: Int, stack: ItemStack): Unit = {
+ if (slot >= 0 && slot < getContainerSize) {
if (stack.isEmpty && items(slot).isEmpty) {
return
}
@@ -33,8 +35,8 @@ trait Inventory extends SimpleInventory {
onItemRemoved(slot, oldStack)
}
if (!stack.isEmpty && stack.getCount >= getInventoryStackRequired) {
- if (stack.getCount > getInventoryStackLimit) {
- stack.setCount(getInventoryStackLimit)
+ if (stack.getCount > getMaxStackSize) {
+ stack.setCount(getMaxStackSize)
}
updateItems(slot, stack)
}
@@ -43,11 +45,11 @@ trait Inventory extends SimpleInventory {
onItemAdded(slot, items(slot))
}
- markDirty()
+ setChanged()
}
}
- override def getName: String = Settings.namespace + "container." + inventoryName
+ override def getName: ITextComponent = new TranslationTextComponent(Settings.namespace + "container." + inventoryName)
protected def inventoryName: String = getClass.getSimpleName.toLowerCase
@@ -59,26 +61,26 @@ trait Inventory extends SimpleInventory {
private final val SlotTag = "slot"
private final val ItemTag = "item"
- def load(nbt: NBTTagCompound) {
- nbt.getTagList(ItemsTag, NBT.TAG_COMPOUND).foreach((tag: NBTTagCompound) => {
- if (tag.hasKey(SlotTag)) {
+ def loadData(nbt: CompoundNBT) {
+ nbt.getList(ItemsTag, NBT.TAG_COMPOUND).foreach((tag: CompoundNBT) => {
+ if (tag.contains(SlotTag)) {
val slot = tag.getByte(SlotTag)
if (slot >= 0 && slot < items.length) {
- updateItems(slot, new ItemStack(tag.getCompoundTag(ItemTag)))
+ updateItems(slot, ItemStack.of(tag.getCompound(ItemTag)))
}
}
})
}
- def save(nbt: NBTTagCompound) {
+ def saveData(nbt: CompoundNBT) {
nbt.setNewTagList(ItemsTag,
items.zipWithIndex collect {
case (stack, slot) if !stack.isEmpty => (stack, slot)
} map {
case (stack, slot) =>
- val slotNbt = new NBTTagCompound()
- slotNbt.setByte(SlotTag, slot.toByte)
- slotNbt.setNewCompoundTag(ItemTag, stack.writeToNBT)
+ val slotNbt = new CompoundNBT()
+ slotNbt.putByte(SlotTag, slot.toByte)
+ slotNbt.setNewCompoundTag(ItemTag, stack.save)
})
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/InventoryProxy.scala b/src/main/scala/li/cil/oc/common/inventory/InventoryProxy.scala
index 020f62ec59..dd036ce1fc 100644
--- a/src/main/scala/li/cil/oc/common/inventory/InventoryProxy.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/InventoryProxy.scala
@@ -1,6 +1,6 @@
package li.cil.oc.common.inventory
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.util.text.ITextComponent
@@ -12,59 +12,47 @@ trait InventoryProxy extends IInventory {
override def isEmpty: Boolean = inventory.isEmpty
- override def getSizeInventory: Int = inventory.getSizeInventory
+ override def getContainerSize: Int = inventory.getContainerSize
- override def getInventoryStackLimit: Int = inventory.getInventoryStackLimit
+ override def getMaxStackSize: Int = inventory.getMaxStackSize
- override def getName: String = inventory.getName
+ override def stillValid(player: PlayerEntity): Boolean = inventory.stillValid(player)
- override def getDisplayName: ITextComponent = inventory.getDisplayName
-
- override def hasCustomName: Boolean = inventory.hasCustomName
-
- override def isUsableByPlayer(player: EntityPlayer): Boolean = inventory.isUsableByPlayer(player)
-
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = {
val offsetSlot = slot + offset
- isValidSlot(offsetSlot) && inventory.isItemValidForSlot(offsetSlot, stack)
+ isValidSlot(offsetSlot) && inventory.canPlaceItem(offsetSlot, stack)
}
- override def getStackInSlot(slot: Int): ItemStack = {
+ override def getItem(slot: Int): ItemStack = {
val offsetSlot = slot + offset
- if (isValidSlot(offsetSlot)) inventory.getStackInSlot(offsetSlot)
+ if (isValidSlot(offsetSlot)) inventory.getItem(offsetSlot)
else ItemStack.EMPTY
}
- override def decrStackSize(slot: Int, amount: Int): ItemStack = {
+ override def removeItem(slot: Int, amount: Int): ItemStack = {
val offsetSlot = slot + offset
- if (isValidSlot(offsetSlot)) inventory.decrStackSize(offsetSlot, amount)
+ if (isValidSlot(offsetSlot)) inventory.removeItem(offsetSlot, amount)
else ItemStack.EMPTY
}
- override def removeStackFromSlot(slot: Int): ItemStack = {
+ override def removeItemNoUpdate(slot: Int): ItemStack = {
val offsetSlot = slot + offset
- if (isValidSlot(offsetSlot)) inventory.removeStackFromSlot(offsetSlot)
+ if (isValidSlot(offsetSlot)) inventory.removeItemNoUpdate(offsetSlot)
else ItemStack.EMPTY
}
- override def setInventorySlotContents(slot: Int, stack: ItemStack): Unit = {
+ override def setItem(slot: Int, stack: ItemStack): Unit = {
val offsetSlot = slot + offset
- if (isValidSlot(offsetSlot)) inventory.setInventorySlotContents(offsetSlot, stack)
+ if (isValidSlot(offsetSlot)) inventory.setItem(offsetSlot, stack)
}
- override def markDirty(): Unit = inventory.markDirty()
-
- override def openInventory(player: EntityPlayer): Unit = inventory.openInventory(player)
-
- override def closeInventory(player: EntityPlayer): Unit = inventory.closeInventory(player)
-
- override def setField(id: Int, value: Int): Unit = inventory.setField(id, value)
+ override def setChanged(): Unit = inventory.setChanged()
- override def clear(): Unit = inventory.clear()
+ override def startOpen(player: PlayerEntity): Unit = inventory.startOpen(player)
- override def getFieldCount: Int = inventory.getFieldCount
+ override def stopOpen(player: PlayerEntity): Unit = inventory.stopOpen(player)
- override def getField(id: Int): Int = inventory.getField(id)
+ override def clearContent(): Unit = inventory.clearContent()
- private def isValidSlot(slot: Int) = slot >= offset && slot < getSizeInventory + offset
+ private def isValidSlot(slot: Int) = slot >= offset && slot < getContainerSize + offset
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala
index 1c04f22fde..9c621952e7 100644
--- a/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala
@@ -1,13 +1,13 @@
package li.cil.oc.common.inventory
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
trait ItemStackInventory extends Inventory {
// The item stack that provides the inventory.
def container: ItemStack
- private lazy val inventory = Array.fill[ItemStack](getSizeInventory)(ItemStack.EMPTY)
+ private lazy val inventory = Array.fill[ItemStack](getContainerSize)(ItemStack.EMPTY)
override def items = inventory
@@ -24,17 +24,11 @@ trait ItemStackInventory extends Inventory {
for (i <- items.indices) {
updateItems(i, ItemStack.EMPTY)
}
- if (!container.hasTagCompound) {
- container.setTagCompound(new NBTTagCompound())
- }
- load(container.getTagCompound)
+ loadData(container.getOrCreateTag)
}
// Write items back to tag.
- override def markDirty() {
- if (!container.hasTagCompound) {
- container.setTagCompound(new NBTTagCompound())
- }
- save(container.getTagCompound)
+ override def setChanged() {
+ saveData(container.getOrCreateTag)
}
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/ServerInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ServerInventory.scala
index ec03c0faaf..b026ebc8c5 100644
--- a/src/main/scala/li/cil/oc/common/inventory/ServerInventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/ServerInventory.scala
@@ -3,24 +3,33 @@ package li.cil.oc.common.inventory
import li.cil.oc.api.Driver
import li.cil.oc.api.internal
import li.cil.oc.common.InventorySlots
+import li.cil.oc.common.container.ContainerTypes
+import li.cil.oc.common.container.{Server => ServerContainer}
import li.cil.oc.util.ItemUtils
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-trait ServerInventory extends ItemStackInventory {
+trait ServerInventory extends ItemStackInventory with INamedContainerProvider {
+ def rackSlot: Int
+
def tier: Int = ItemUtils.caseTier(container) max 0
- override def getSizeInventory = InventorySlots.server(tier).length
+ override def getContainerSize = InventorySlots.server(tier).length
override protected def inventoryName = "server"
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
- override def isUsableByPlayer(player: EntityPlayer) = false
+ override def stillValid(player: PlayerEntity) = false
- override def isItemValidForSlot(slot: Int, stack: ItemStack) =
+ override def canPlaceItem(slot: Int, stack: ItemStack) =
Option(Driver.driverFor(stack, classOf[internal.Server])).fold(false)(driver => {
val provided = InventorySlots.server(tier)(slot)
driver.slot(stack) == provided.slot && driver.tier(stack) <= provided.tier
})
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new ServerContainer(ContainerTypes.SERVER, id, playerInventory, container, this, tier, rackSlot)
}
diff --git a/src/main/scala/li/cil/oc/common/inventory/SimpleInventory.scala b/src/main/scala/li/cil/oc/common/inventory/SimpleInventory.scala
index 34113b7288..36b67e46d6 100644
--- a/src/main/scala/li/cil/oc/common/inventory/SimpleInventory.scala
+++ b/src/main/scala/li/cil/oc/common/inventory/SimpleInventory.scala
@@ -1,34 +1,35 @@
package li.cil.oc.common.inventory
import li.cil.oc.Localization
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
+import net.minecraft.util.INameable
import net.minecraft.util.text.ITextComponent
-trait SimpleInventory extends IInventory {
+trait SimpleInventory extends IInventory with INameable {
override def hasCustomName = false
- override def getDisplayName: ITextComponent = Localization.localizeLater(getName)
+ override def getDisplayName: ITextComponent = getName
- override def getInventoryStackLimit = 64
+ override def getMaxStackSize = 64
// Items required in a slot before it's set to null (for ghost stacks).
def getInventoryStackRequired = 1
- override def openInventory(player: EntityPlayer): Unit = {}
+ override def startOpen(player: PlayerEntity): Unit = {}
- override def closeInventory(player: EntityPlayer): Unit = {}
+ override def stopOpen(player: PlayerEntity): Unit = {}
- override def decrStackSize(slot: Int, amount: Int): ItemStack = {
- if (slot >= 0 && slot < getSizeInventory) {
- (getStackInSlot(slot) match {
+ override def removeItem(slot: Int, amount: Int): ItemStack = {
+ if (slot >= 0 && slot < getContainerSize) {
+ (getItem(slot) match {
case stack: ItemStack if stack.getCount - amount < getInventoryStackRequired =>
- setInventorySlotContents(slot, ItemStack.EMPTY)
+ setItem(slot, ItemStack.EMPTY)
stack
case stack: ItemStack =>
- val result = stack.splitStack(amount)
- markDirty()
+ val result = stack.split(amount)
+ setChanged()
result
case _ => ItemStack.EMPTY
}) match {
@@ -39,24 +40,18 @@ trait SimpleInventory extends IInventory {
else ItemStack.EMPTY
}
- override def removeStackFromSlot(slot: Int) = {
- if (slot >= 0 && slot < getSizeInventory) {
- val stack = getStackInSlot(slot)
- setInventorySlotContents(slot, ItemStack.EMPTY)
+ override def removeItemNoUpdate(slot: Int) = {
+ if (slot >= 0 && slot < getContainerSize) {
+ val stack = getItem(slot)
+ setItem(slot, ItemStack.EMPTY)
stack
}
else ItemStack.EMPTY
}
- override def clear(): Unit = {
- for (slot <- 0 until getSizeInventory) {
- setInventorySlotContents(slot, ItemStack.EMPTY)
+ override def clearContent(): Unit = {
+ for (slot <- 0 until getContainerSize) {
+ setItem(slot, ItemStack.EMPTY)
}
}
-
- override def getField(id: Int) = 0
-
- override def setField(id: Int, value: Int) {}
-
- override def getFieldCount = 0
}
diff --git a/src/main/scala/li/cil/oc/common/item/ALU.scala b/src/main/scala/li/cil/oc/common/item/ALU.scala
index 48daf66d1f..804824109b 100644
--- a/src/main/scala/li/cil/oc/common/item/ALU.scala
+++ b/src/main/scala/li/cil/oc/common/item/ALU.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class ALU(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class ALU(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/APU.scala b/src/main/scala/li/cil/oc/common/item/APU.scala
index 57835d6871..9672b8c9ad 100644
--- a/src/main/scala/li/cil/oc/common/item/APU.scala
+++ b/src/main/scala/li/cil/oc/common/item/APU.scala
@@ -1,24 +1,22 @@
package li.cil.oc.common.item
import li.cil.oc.common.Tier
-import li.cil.oc.util.Rarity
-import net.minecraft.item.EnumRarity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
import scala.language.existentials
-class APU(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier with traits.CPULike with traits.GPULike {
- override val unlocalizedName = super[Delegate].unlocalizedName + tier
-
- override def rarity(stack: ItemStack): EnumRarity =
- if (tier == Tier.Three) Rarity.byTier(Tier.Four)
- else super.rarity(stack)
+class APU(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier with traits.CPULike with traits.GPULike {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
override def cpuTier = math.min(Tier.Three, tier + 1)
override def gpuTier = tier
- override protected def tooltipName = Option(super[Delegate].unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData: Seq[Any] = {
super[CPULike].tooltipData ++ super[GPULike].tooltipData
diff --git a/src/main/scala/li/cil/oc/common/item/Acid.scala b/src/main/scala/li/cil/oc/common/item/Acid.scala
index 0ba9912f2e..a567e94d0c 100644
--- a/src/main/scala/li/cil/oc/common/item/Acid.scala
+++ b/src/main/scala/li/cil/oc/common/item/Acid.scala
@@ -3,36 +3,40 @@ package li.cil.oc.common.item
import javax.annotation.Nonnull
import li.cil.oc.api
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumAction
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.potion.Potion
-import net.minecraft.potion.PotionEffect
+import net.minecraft.item.UseAction
+import net.minecraft.potion.Effect
+import net.minecraft.potion.Effects
+import net.minecraft.potion.EffectInstance
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-class Acid(val parent: Delegator) extends traits.Delegate {
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- player.setActiveHand(if (player.getHeldItemMainhand == stack) EnumHand.MAIN_HAND else EnumHand.OFF_HAND)
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+class Acid(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ player.startUsingItem(if (player.getItemInHand(Hand.MAIN_HAND) == stack) Hand.MAIN_HAND else Hand.OFF_HAND)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
- override def getItemUseAction(stack: ItemStack): EnumAction = EnumAction.DRINK
+ override def getUseAnimation(stack: ItemStack): UseAction = UseAction.DRINK
- override def getMaxItemUseDuration(stack: ItemStack): Int = 32
+ override def getUseDuration(stack: ItemStack): Int = 32
- override def onItemUseFinish(stack: ItemStack, world: World, entity: EntityLivingBase): ItemStack = {
+ override def finishUsingItem(stack: ItemStack, world: World, entity: LivingEntity): ItemStack = {
entity match {
- case player: EntityPlayer =>
- if (!world.isRemote) {
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("blindness"), 200))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("poison"), 100))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("slowness"), 600))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("nausea"), 1200))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("saturation"), 2000))
+ case player: PlayerEntity =>
+ if (!world.isClientSide) {
+ player.addEffect(new EffectInstance(Effects.BLINDNESS, 200))
+ player.addEffect(new EffectInstance(Effects.POISON, 100))
+ player.addEffect(new EffectInstance(Effects.MOVEMENT_SLOWDOWN, 600))
+ player.addEffect(new EffectInstance(Effects.CONFUSION, 1200))
+ player.addEffect(new EffectInstance(Effects.SATURATION, 2000))
// Remove nanomachines if installed.
api.Nanomachines.uninstallController(player)
diff --git a/src/main/scala/li/cil/oc/common/item/Analyzer.scala b/src/main/scala/li/cil/oc/common/item/Analyzer.scala
index 47935d6506..89379cd5b7 100644
--- a/src/main/scala/li/cil/oc/common/item/Analyzer.scala
+++ b/src/main/scala/li/cil/oc/common/item/Analyzer.scala
@@ -11,46 +11,50 @@ import li.cil.oc.common.tileentity
import li.cil.oc.server.PacketSender
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
+import net.minecraft.util.Util
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.entity.player.PlayerInteractEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
object Analyzer {
private lazy val analyzer = api.Items.get(Constants.ItemName.Analyzer)
@SubscribeEvent
def onInteract(e: PlayerInteractEvent.EntityInteract): Unit = {
- val player = e.getEntityPlayer
- val held = player.getHeldItem(e.getHand)
+ val player = e.getPlayer
+ val held = player.getItemInHand(e.getHand)
if (api.Items.get(held) == analyzer) {
- if (analyze(e.getTarget, player, EnumFacing.DOWN, 0, 0, 0)) {
- player.swingArm(e.getHand)
+ if (analyze(e.getTarget, player, Direction.DOWN, 0, 0, 0)) {
+ player.swing(e.getHand)
e.setCanceled(true)
}
}
}
- def analyze(thing: AnyRef, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- val world = player.world
+ def analyze(thing: AnyRef, player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ val world = player.level
thing match {
case analyzable: Analyzable =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
analyzeNodes(analyzable.onAnalyze(player, side, hitX, hitY, hitZ), player)
}
true
case host: SidedEnvironment =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
analyzeNodes(Array(host.sidedNode(side)), player)
}
true
case host: Environment =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
analyzeNodes(Array(host.node), player)
}
true
@@ -59,20 +63,20 @@ object Analyzer {
}
}
- private def analyzeNodes(nodes: Array[Node], player: EntityPlayer) = if (nodes != null) for (node <- nodes if node != null) {
+ private def analyzeNodes(nodes: Array[Node], player: PlayerEntity) = if (nodes != null) for (node <- nodes if node != null) {
player match {
case _: FakePlayer => // Nope
- case playerMP: EntityPlayerMP =>
+ case playerMP: ServerPlayerEntity =>
if (node != null) node.host match {
case machine: Machine =>
if (machine != null) {
if (machine.lastError != null) {
- playerMP.sendMessage(Localization.Analyzer.LastError(machine.lastError))
+ playerMP.sendMessage(Localization.Analyzer.LastError(machine.lastError), Util.NIL_UUID)
}
- playerMP.sendMessage(Localization.Analyzer.Components(machine.componentCount, machine.maxComponents))
+ playerMP.sendMessage(Localization.Analyzer.Components(machine.componentCount, machine.maxComponents), Util.NIL_UUID)
val list = machine.users
if (list.nonEmpty) {
- playerMP.sendMessage(Localization.Analyzer.Users(list))
+ playerMP.sendMessage(Localization.Analyzer.Users(list), Util.NIL_UUID)
}
}
case _ =>
@@ -80,19 +84,19 @@ object Analyzer {
node match {
case connector: Connector =>
if (connector.localBufferSize > 0) {
- playerMP.sendMessage(Localization.Analyzer.StoredEnergy(f"${connector.localBuffer}%.2f/${connector.localBufferSize}%.2f"))
+ playerMP.sendMessage(Localization.Analyzer.StoredEnergy(f"${connector.localBuffer}%.2f/${connector.localBufferSize}%.2f"), Util.NIL_UUID)
}
- playerMP.sendMessage(Localization.Analyzer.TotalEnergy(f"${connector.globalBuffer}%.2f/${connector.globalBufferSize}%.2f"))
+ playerMP.sendMessage(Localization.Analyzer.TotalEnergy(f"${connector.globalBuffer}%.2f/${connector.globalBufferSize}%.2f"), Util.NIL_UUID)
case _ =>
}
node match {
case component: Component =>
- playerMP.sendMessage(Localization.Analyzer.ComponentName(component.name))
+ playerMP.sendMessage(Localization.Analyzer.ComponentName(component.name), Util.NIL_UUID)
case _ =>
}
val address = node.address()
if (address != null && !address.isEmpty) {
- playerMP.sendMessage(Localization.Analyzer.Address(address))
+ playerMP.sendMessage(Localization.Analyzer.Address(address), Util.NIL_UUID)
PacketSender.sendAnalyze(address, playerMP)
}
case _ =>
@@ -100,32 +104,29 @@ object Analyzer {
}
}
-class Analyzer(val parent: Delegator) extends traits.Delegate {
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (player.isSneaking && stack.hasTagCompound) {
- stack.getTagCompound.removeTag(Settings.namespace + "clipboard")
- if (stack.getTagCompound.hasNoTags) {
- stack.setTagCompound(null)
- }
+class Analyzer(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (player.isCrouching && stack.hasTag) {
+ stack.removeTagKey(Settings.namespace + "clipboard")
}
- super.onItemRightClick(stack, world, player)
+ super.use(stack, world, player)
}
- override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- val world = player.getEntityWorld
- world.getTileEntity(position) match {
+ override def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = {
+ val world = player.level
+ world.getBlockEntity(position) match {
case screen: tileentity.Screen if side == screen.facing =>
- if (player.isSneaking) {
+ if (player.isCrouching) {
screen.copyToAnalyzer(hitX, hitY, hitZ)
}
- else if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "clipboard")) {
- if (!world.isRemote) {
- screen.origin.buffer.clipboard(stack.getTagCompound.getString(Settings.namespace + "clipboard"), player)
+ else if (stack.hasTag && stack.getTag.contains(Settings.namespace + "clipboard")) {
+ if (!world.isClientSide) {
+ screen.origin.buffer.clipboard(stack.getTag.getString(Settings.namespace + "clipboard"), player)
}
true
}
else false
- case _ => Analyzer.analyze(position.world.get.getTileEntity(position), player, side, hitX, hitY, hitZ)
+ case _ => Analyzer.analyze(position.world.get.getBlockEntity(position), player, side, hitX, hitY, hitZ)
}
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/ArrowKeys.scala b/src/main/scala/li/cil/oc/common/item/ArrowKeys.scala
index fef4d0850f..7a63055992 100644
--- a/src/main/scala/li/cil/oc/common/item/ArrowKeys.scala
+++ b/src/main/scala/li/cil/oc/common/item/ArrowKeys.scala
@@ -1,5 +1,9 @@
package li.cil.oc.common.item
-class ArrowKeys(val parent: Delegator) extends traits.Delegate {
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class ArrowKeys(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
override protected def tooltipName = None
}
diff --git a/src/main/scala/li/cil/oc/common/item/ButtonGroup.scala b/src/main/scala/li/cil/oc/common/item/ButtonGroup.scala
index c6450d41d3..030f51a438 100644
--- a/src/main/scala/li/cil/oc/common/item/ButtonGroup.scala
+++ b/src/main/scala/li/cil/oc/common/item/ButtonGroup.scala
@@ -1,5 +1,9 @@
package li.cil.oc.common.item
-class ButtonGroup(val parent: Delegator) extends traits.Delegate {
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class ButtonGroup(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
override protected def tooltipName = None
}
diff --git a/src/main/scala/li/cil/oc/common/item/CPU.scala b/src/main/scala/li/cil/oc/common/item/CPU.scala
index bc8aacce44..9a7c6e4974 100644
--- a/src/main/scala/li/cil/oc/common/item/CPU.scala
+++ b/src/main/scala/li/cil/oc/common/item/CPU.scala
@@ -1,11 +1,16 @@
package li.cil.oc.common.item
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
import scala.language.existentials
-class CPU(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier with traits.CPULike {
- override val unlocalizedName = super.unlocalizedName + tier
+class CPU(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier with traits.CPULike {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
override def cpuTier = tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/CardBase.scala b/src/main/scala/li/cil/oc/common/item/CardBase.scala
index dfb3362ae3..af0667686a 100644
--- a/src/main/scala/li/cil/oc/common/item/CardBase.scala
+++ b/src/main/scala/li/cil/oc/common/item/CardBase.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class CardBase(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class CardBase(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/Chamelium.scala b/src/main/scala/li/cil/oc/common/item/Chamelium.scala
index 7486f2fac4..8be92fd7c0 100644
--- a/src/main/scala/li/cil/oc/common/item/Chamelium.scala
+++ b/src/main/scala/li/cil/oc/common/item/Chamelium.scala
@@ -1,33 +1,37 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumAction
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.potion.Potion
-import net.minecraft.potion.PotionEffect
+import net.minecraft.item.UseAction
+import net.minecraft.potion.Effect
+import net.minecraft.potion.Effects
+import net.minecraft.potion.EffectInstance
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-class Chamelium(val parent: Delegator) extends traits.Delegate {
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
+class Chamelium(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
if (Settings.get.chameliumEdible) {
- player.setActiveHand(if (player.getHeldItemMainhand == stack) EnumHand.MAIN_HAND else EnumHand.OFF_HAND)
+ player.startUsingItem(if (player.getItemInHand(Hand.MAIN_HAND) == stack) Hand.MAIN_HAND else Hand.OFF_HAND)
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
- override def getItemUseAction(stack: ItemStack): EnumAction = EnumAction.EAT
+ override def getUseAnimation(stack: ItemStack): UseAction = UseAction.EAT
- override def getMaxItemUseDuration(stack: ItemStack): Int = 32
+ override def getUseDuration(stack: ItemStack): Int = 32
- override def onItemUseFinish(stack: ItemStack, world: World, player: EntityLivingBase): ItemStack = {
- if (!world.isRemote) {
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("invisibility"), 100, 0))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("blindness"), 200, 0))
+ override def finishUsingItem(stack: ItemStack, world: World, player: LivingEntity): ItemStack = {
+ if (!world.isClientSide) {
+ player.addEffect(new EffectInstance(Effects.INVISIBILITY, 100, 0))
+ player.addEffect(new EffectInstance(Effects.BLINDNESS, 200, 0))
}
stack.shrink(1)
if (stack.getCount > 0) stack
diff --git a/src/main/scala/li/cil/oc/common/item/CircuitBoard.scala b/src/main/scala/li/cil/oc/common/item/CircuitBoard.scala
index b24c2a0321..b88c00c253 100644
--- a/src/main/scala/li/cil/oc/common/item/CircuitBoard.scala
+++ b/src/main/scala/li/cil/oc/common/item/CircuitBoard.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class CircuitBoard(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class CircuitBoard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/ComponentBus.scala b/src/main/scala/li/cil/oc/common/item/ComponentBus.scala
index 867fe47fe6..2c33d2adc3 100644
--- a/src/main/scala/li/cil/oc/common/item/ComponentBus.scala
+++ b/src/main/scala/li/cil/oc/common/item/ComponentBus.scala
@@ -1,21 +1,16 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
-import li.cil.oc.common.Tier
-import li.cil.oc.util.Rarity
-import net.minecraft.item.EnumRarity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
-class ComponentBus(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class ComponentBus(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- // Because the driver considers the creative bus to be tier 3, the superclass
- // will believe it has T3 rarity. We override that here.
- override def rarity(stack: ItemStack): EnumRarity =
- if (tier == Tier.Four) Rarity.byTier(Tier.Four)
- else super.rarity(stack)
-
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData = Seq(Settings.get.cpuComponentSupport(tier))
}
diff --git a/src/main/scala/li/cil/oc/common/item/ControlUnit.scala b/src/main/scala/li/cil/oc/common/item/ControlUnit.scala
index b9eab26ab0..637cdcca40 100644
--- a/src/main/scala/li/cil/oc/common/item/ControlUnit.scala
+++ b/src/main/scala/li/cil/oc/common/item/ControlUnit.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class ControlUnit(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class ControlUnit(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/CustomModel.scala b/src/main/scala/li/cil/oc/common/item/CustomModel.scala
index 33a52b337a..e8a114d05c 100644
--- a/src/main/scala/li/cil/oc/common/item/CustomModel.scala
+++ b/src/main/scala/li/cil/oc/common/item/CustomModel.scala
@@ -1,18 +1,18 @@
package li.cil.oc.common.item
-import net.minecraft.client.renderer.block.model.ModelResourceLocation
+import net.minecraft.client.renderer.model.ModelResourceLocation
import net.minecraft.item.ItemStack
import net.minecraftforge.client.event.ModelBakeEvent
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
trait CustomModel {
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
def getModelLocation(stack: ItemStack): ModelResourceLocation
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
def registerModelLocations(): Unit = {}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
def bakeModels(bakeEvent: ModelBakeEvent): Unit = {}
}
diff --git a/src/main/scala/li/cil/oc/common/item/CuttingWire.scala b/src/main/scala/li/cil/oc/common/item/CuttingWire.scala
index 6814a420d9..07399930aa 100644
--- a/src/main/scala/li/cil/oc/common/item/CuttingWire.scala
+++ b/src/main/scala/li/cil/oc/common/item/CuttingWire.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class CuttingWire(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class CuttingWire(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/DataCard.scala b/src/main/scala/li/cil/oc/common/item/DataCard.scala
index 69479fd05a..488ea499ac 100644
--- a/src/main/scala/li/cil/oc/common/item/DataCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/DataCard.scala
@@ -1,5 +1,10 @@
package li.cil.oc.common.item
-class DataCard(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class DataCard(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/DebugCard.scala b/src/main/scala/li/cil/oc/common/item/DebugCard.scala
index 278f1009d7..d12821576c 100644
--- a/src/main/scala/li/cil/oc/common/item/DebugCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/DebugCard.scala
@@ -6,43 +6,48 @@ import li.cil.oc.Settings
import li.cil.oc.Settings.DebugCardAccess
import li.cil.oc.common.item.data.DebugCardData
import li.cil.oc.server.component.{DebugCard => CDebugCard}
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
-import net.minecraft.util.text.TextComponentString
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
+import net.minecraft.util.Util
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-class DebugCard(val parent: Delegator) extends traits.Delegate {
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
+class DebugCard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[ITextComponent]): Unit = {
super.tooltipExtended(stack, tooltip)
val data = new DebugCardData(stack)
- data.access.foreach(access => tooltip.add(s"§8${access.player}§r"))
+ data.access.foreach(access => tooltip.add(new StringTextComponent(s"§8${access.player}§r")))
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (!world.isRemote && player.isSneaking) {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (!world.isClientSide && player.isCrouching) {
val data = new DebugCardData(stack)
val name = player.getName
if (data.access.exists(_.player == name)) data.access = None
else data.access =
- Some(CDebugCard.AccessContext(name, Settings.get.debugCardAccess match {
- case wl: DebugCardAccess.Whitelist => wl.nonce(name) match {
+ Some(CDebugCard.AccessContext(name.getString, Settings.get.debugCardAccess match {
+ case wl: DebugCardAccess.Whitelist => wl.nonce(name.getString) match {
case Some(n) => n
case None =>
- player.sendMessage(new TextComponentString("§cYou are not whitelisted to use debug card"))
- player.swingArm(EnumHand.MAIN_HAND)
- return new ActionResult[ItemStack](EnumActionResult.FAIL, stack)
+ player.sendMessage(new StringTextComponent("§cYou are not whitelisted to use debug card"), Util.NIL_UUID)
+ player.swing(Hand.MAIN_HAND)
+ return new ActionResult[ItemStack](ActionResultType.FAIL, stack)
}
case _ => ""
}))
- data.save(stack)
- player.swingArm(EnumHand.MAIN_HAND)
+ data.saveData(stack)
+ player.swing(Hand.MAIN_HAND)
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/Debugger.scala b/src/main/scala/li/cil/oc/common/item/Debugger.scala
index 7b20cdba63..bb6daeb819 100644
--- a/src/main/scala/li/cil/oc/common/item/Debugger.scala
+++ b/src/main/scala/li/cil/oc/common/item/Debugger.scala
@@ -5,31 +5,34 @@ import li.cil.oc.api
import li.cil.oc.api.network._
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.FakePlayer
+import net.minecraftforge.common.extensions.IForgeItem
-class Debugger(val parent: Delegator) extends traits.Delegate {
- override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
+class Debugger(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = {
val world = position.world.get
player match {
case _: FakePlayer => false // Nope
- case realPlayer: EntityPlayerMP =>
- world.getTileEntity(position) match {
+ case realPlayer: ServerPlayerEntity =>
+ world.getBlockEntity(position) match {
case host: SidedEnvironment =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
Debugger.reconnect(Array(host.sidedNode(side)))
}
true
case host: Environment =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
Debugger.reconnect(Array(host.node))
}
true
case _ =>
- if (!world.isRemote) {
+ if (!world.isClientSide) {
Debugger.node.remove()
}
true
diff --git a/src/main/scala/li/cil/oc/common/item/Delegator.scala b/src/main/scala/li/cil/oc/common/item/Delegator.scala
deleted file mode 100644
index fbbdca01f9..0000000000
--- a/src/main/scala/li/cil/oc/common/item/Delegator.scala
+++ /dev/null
@@ -1,245 +0,0 @@
-package li.cil.oc.common.item
-
-import java.util
-import li.cil.oc.CreativeTab
-import li.cil.oc.OpenComputers
-import li.cil.oc.api.driver
-import li.cil.oc.api.driver.item.Chargeable
-import li.cil.oc.api.event.RobotRenderEvent.MountPoint
-import li.cil.oc.api.internal.Robot
-import li.cil.oc.client.renderer.item.UpgradeRenderer
-import li.cil.oc.common.item.traits.Delegate
-import li.cil.oc.integration.opencomputers.{Item => OpenComputersItem}
-import li.cil.oc.util.BlockPosition
-import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.creativetab.CreativeTabs
-import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumAction
-import net.minecraft.item.EnumRarity
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
-import net.minecraft.util.NonNullList
-import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
-import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-import scala.collection.mutable
-import scala.collection.mutable.ArrayBuffer
-
-object Delegator {
- def subItem(stack: ItemStack): Option[Delegate] =
- if (!stack.isEmpty) stack.getItem match {
- case delegator: Delegator => delegator.subItem(stack.getItemDamage)
- case _ => None
- }
- else None
-}
-
-class Delegator extends Item with driver.item.UpgradeRenderer with Chargeable {
- setHasSubtypes(true)
- setCreativeTab(CreativeTab)
-
- // ----------------------------------------------------------------------- //
- // SubItem
- // ----------------------------------------------------------------------- //
-
- override def getItemStackLimit(stack: ItemStack): Int =
- Delegator.subItem(stack) match {
- case Some(subItem) => OpenComputersItem.address(stack) match {
- case Some(address) => 1
- case _ => subItem.maxStackSize
- }
- case _ => maxStackSize
- }
-
- val subItems: ArrayBuffer[Delegate] = mutable.ArrayBuffer.empty[traits.Delegate]
-
- def add(subItem: traits.Delegate): Int = {
- val itemId = subItems.length
- subItems += subItem
- itemId
- }
-
- def subItem(damage: Int): Option[Delegate] =
- damage match {
- case itemId if itemId >= 0 && itemId < subItems.length => Some(subItems(itemId))
- case _ => None
- }
-
- override def getSubItems(tab: CreativeTabs, list: NonNullList[ItemStack]) {
- // Workaround for MC's untyped lists...
- if(isInCreativeTab(tab)){
- subItems.indices.filter(subItems(_).showInItemList).
- map(subItems(_).createItemStack()).
- sortBy(_.getUnlocalizedName).
- foreach(list.add)
- }
- }
-
- // ----------------------------------------------------------------------- //
- // Item
- // ----------------------------------------------------------------------- //
-
- override def getUnlocalizedName(stack: ItemStack): String =
- Delegator.subItem(stack) match {
- case Some(subItem) => "item.oc." + subItem.unlocalizedName
- case _ => getUnlocalizedName
- }
-
- override def isBookEnchantable(itemA: ItemStack, itemB: ItemStack): Boolean = false
-
- override def getRarity(stack: ItemStack): EnumRarity =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.rarity(stack)
- case _ => EnumRarity.COMMON
- }
-
-// override def getColorFromItemStack(stack: ItemStack, pass: Int) =
-// Delegator.subItem(stack) match {
-// case Some(subItem) => subItem.color(stack, pass)
-// case _ => super.getColorFromItemStack(stack, pass)
-// }
-
- override def getContainerItem(stack: ItemStack): ItemStack =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.getContainerItem(stack)
- case _ => super.getContainerItem(stack)
- }
-
- override def hasContainerItem(stack: ItemStack): Boolean =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.hasContainerItem(stack)
- case _ => super.hasContainerItem(stack)
- }
-
- // ----------------------------------------------------------------------- //
-
- override def doesSneakBypassUse(stack: ItemStack, world: IBlockAccess, pos: BlockPos, player: EntityPlayer): Boolean =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.doesSneakBypassUse(world, pos, player)
- case _ => super.doesSneakBypassUse(stack, world, pos, player)
- }
-
- override def onItemUseFirst(player: EntityPlayer, world: World, pos: BlockPos, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, hand: EnumHand): EnumActionResult =
- player.getHeldItem(hand) match {
- case stack:ItemStack => Delegator.subItem(stack) match {
- case Some(subItem) => subItem.onItemUseFirst(stack, player, BlockPosition(pos, world), side, hitX, hitY, hitZ)
- case _ => super.onItemUseFirst(player, world, pos, side, hitX, hitY, hitZ, hand)
- }
- case _ => super.onItemUseFirst(player, world, pos, side, hitX, hitY, hitZ, hand)
- }
-
- override def onItemUse(player: EntityPlayer, world: World, pos: BlockPos, hand: EnumHand, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): EnumActionResult =
- player.getHeldItem(hand) match {
- case stack: ItemStack => Delegator.subItem(stack) match {
- case Some(subItem) => if (subItem.onItemUse(stack, player, BlockPosition(pos, world), side, hitX, hitY, hitZ)) EnumActionResult.SUCCESS else EnumActionResult.PASS
- case _ => super.onItemUse(player, world, pos, hand, side, hitX, hitY, hitZ)
- }
- case _ => super.onItemUse(player, world, pos, hand, side, hitX, hitY, hitZ)
- }
-
- override def onItemRightClick(world: World, player: EntityPlayer, hand: EnumHand): ActionResult[ItemStack] =
- player.getHeldItem(hand) match {
- case stack: ItemStack => Delegator.subItem(stack) match {
- case Some(subItem) => subItem.onItemRightClick(stack, world, player)
- case _ => super.onItemRightClick(world, player, hand)
- }
- case _ => super.onItemRightClick(world, player, hand)
- }
-
- // ----------------------------------------------------------------------- //
-
- override def onItemUseFinish(stack: ItemStack, world: World, entity: EntityLivingBase): ItemStack =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.onItemUseFinish(stack, world, entity)
- case _ => super.onItemUseFinish(stack, world, entity)
- }
-
- override def getItemUseAction(stack: ItemStack): EnumAction =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.getItemUseAction(stack)
- case _ => super.getItemUseAction(stack)
- }
-
- override def getMaxItemUseDuration(stack: ItemStack): Int =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.getMaxItemUseDuration(stack)
- case _ => super.getMaxItemUseDuration(stack)
- }
-
- override def onPlayerStoppedUsing(stack: ItemStack, world: World, entity: EntityLivingBase, timeLeft: Int): Unit =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.onPlayerStoppedUsing(stack, entity, timeLeft)
- case _ => super.onPlayerStoppedUsing(stack, world, entity, timeLeft)
- }
-
- def internalGetItemStackDisplayName(stack: ItemStack): String = super.getItemStackDisplayName(stack)
-
- override def getItemStackDisplayName(stack: ItemStack): String =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.displayName(stack) match {
- case Some(name) => name
- case _ => super.getItemStackDisplayName(stack)
- }
- case _ => super.getItemStackDisplayName(stack)
- }
-
- @SideOnly(Side.CLIENT)
- override def addInformation(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- super.addInformation(stack, world, tooltip, flag)
- Delegator.subItem(stack) match {
- case Some(subItem) => try subItem.tooltipLines(stack, world, tooltip, flag) catch {
- case t: Throwable => OpenComputers.log.warn("Error in item tooltip.", t)
- }
- case _ => // Nothing to add.
- }
- }
-
- override def getDurabilityForDisplay(stack: ItemStack): Double =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.durability(stack)
- case _ => super.getDurabilityForDisplay(stack)
- }
-
- override def showDurabilityBar(stack: ItemStack): Boolean =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.showDurabilityBar(stack)
- case _ => super.showDurabilityBar(stack)
- }
-
- override def onUpdate(stack: ItemStack, world: World, player: Entity, slot: Int, selected: Boolean): Unit =
- Delegator.subItem(stack) match {
- case Some(subItem) => subItem.update(stack, world, player, slot, selected)
- case _ => super.onUpdate(stack, world, player, slot, selected)
- }
-
- override def toString: String = getUnlocalizedName
-
- // ----------------------------------------------------------------------- //
-
- def canCharge(stack: ItemStack): Boolean =
- Delegator.subItem(stack) match {
- case Some(subItem: Chargeable) => true
- case _ => false
- }
-
- def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double =
- Delegator.subItem(stack) match {
- case Some(subItem: Chargeable) => subItem.charge(stack, amount, simulate)
- case _ => amount
- }
-
- // ----------------------------------------------------------------------- //
-
- override def computePreferredMountPoint(stack: ItemStack, robot: Robot, availableMountPoints: util.Set[String]): String = UpgradeRenderer.preferredMountPoint(stack, availableMountPoints)
-
- override def render(stack: ItemStack, mountPoint: MountPoint, robot: Robot, pt: Float): Unit = UpgradeRenderer.render(stack, mountPoint)
-}
diff --git a/src/main/scala/li/cil/oc/common/item/DiamondChip.scala b/src/main/scala/li/cil/oc/common/item/DiamondChip.scala
index 813d7cae4d..28cc9b7cac 100644
--- a/src/main/scala/li/cil/oc/common/item/DiamondChip.scala
+++ b/src/main/scala/li/cil/oc/common/item/DiamondChip.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class DiamondChip(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class DiamondChip(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/Disk.scala b/src/main/scala/li/cil/oc/common/item/Disk.scala
index 38ba6f950e..afd23bb19d 100644
--- a/src/main/scala/li/cil/oc/common/item/Disk.scala
+++ b/src/main/scala/li/cil/oc/common/item/Disk.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class Disk(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class Disk(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/DiskDriveMountable.scala b/src/main/scala/li/cil/oc/common/item/DiskDriveMountable.scala
index 5f275155a9..36b89310b1 100644
--- a/src/main/scala/li/cil/oc/common/item/DiskDriveMountable.scala
+++ b/src/main/scala/li/cil/oc/common/item/DiskDriveMountable.scala
@@ -1,21 +1,28 @@
package li.cil.oc.common.item
import li.cil.oc.OpenComputers
-import li.cil.oc.common.GuiType
-import net.minecraft.entity.player.EntityPlayer
+import li.cil.oc.common.container.ContainerTypes
+import li.cil.oc.common.inventory.DiskDriveMountableInventory
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.util.{ActionResult, EnumActionResult, EnumHand}
+import net.minecraft.util.{ActionResult, ActionResultType, Hand}
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-class DiskDriveMountable(val parent: Delegator) extends traits.Delegate {
- override def maxStackSize = 1
+class DiskDriveMountable(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity) = {
+ if (!world.isClientSide) player match {
+ case srvPlr: ServerPlayerEntity => ContainerTypes.openDiskDriveGui(srvPlr, new DiskDriveMountableInventory {
+ override def container: ItemStack = stack
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer) = {
- // Open the GUI immediately on the client, too, to avoid the player
- // changing the current slot before it actually opens, which can lead to
- // desynchronization of the player inventory.
- player.openGui(OpenComputers, GuiType.DiskDriveMountable.id, world, 0, 0, 0)
- player.swingArm(EnumHand.MAIN_HAND)
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ override def stillValid(player: PlayerEntity) = player == srvPlr
+ })
+ case _ =>
+ }
+ player.swing(Hand.MAIN_HAND)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/Drone.scala b/src/main/scala/li/cil/oc/common/item/Drone.scala
index e6df199904..13a19402d1 100644
--- a/src/main/scala/li/cil/oc/common/item/Drone.scala
+++ b/src/main/scala/li/cil/oc/common/item/Drone.scala
@@ -6,61 +6,67 @@ import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.client.KeyBindings
import li.cil.oc.client.renderer.block.DroneModel
-import li.cil.oc.common.entity
import li.cil.oc.common.item.data.DroneData
-import li.cil.oc.integration.util.ItemBlacklist
+import li.cil.oc.common.entity
import li.cil.oc.server.agent
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.Rarity
-import net.minecraft.client.renderer.block.model.ModelResourceLocation
-import net.minecraft.entity.player.EntityPlayer
+import li.cil.oc.util.Tooltip
+import net.minecraft.client.renderer.model.ModelResourceLocation
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
+import net.minecraft.util.NonNullList
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraftforge.client.event.ModelBakeEvent
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-class Drone(val parent: Delegator) extends traits.Delegate with CustomModel {
- ItemBlacklist.hide(this)
+import net.minecraftforge.common.extensions.IForgeItem
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
- showInItemList = false
-
- @SideOnly(Side.CLIENT)
+class Drone(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with CustomModel {
+ @OnlyIn(Dist.CLIENT)
override def getModelLocation(stack: ItemStack) = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.ItemName.Drone, "inventory")
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def bakeModels(bakeEvent: ModelBakeEvent): Unit = {
- bakeEvent.getModelRegistry.putObject(getModelLocation(createItemStack()), DroneModel)
+ bakeEvent.getModelRegistry.put(getModelLocation(createItemStack()), DroneModel)
}
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[ITextComponent]): Unit = {
if (KeyBindings.showExtendedTooltips) {
val info = new DroneData(stack)
for (component <- info.components if !component.isEmpty) {
- tooltip.add("- " + component.getDisplayName)
+ tooltip.add(new StringTextComponent("- " + component.getHoverName.getString).setStyle(Tooltip.DefaultStyle))
}
}
}
- override def rarity(stack: ItemStack) = {
+ override def getRarity(stack: ItemStack) = {
val data = new DroneData(stack)
Rarity.byTier(data.tier)
}
- override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
+ // Must be assembled to be usable so we hide it in the item list.
+ override def fillItemCategory(tab: ItemGroup, list: NonNullList[ItemStack]) {}
+
+ override def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = {
val world = position.world.get
- if (!world.isRemote) {
- val drone = new entity.Drone(world)
+ if (!world.isClientSide) {
+ val drone = entity.EntityTypes.DRONE.create(world)
player match {
case fakePlayer: agent.Player =>
drone.ownerName = fakePlayer.agent.ownerName
drone.ownerUUID = fakePlayer.agent.ownerUUID
case _ =>
- drone.ownerName = player.getName
+ drone.ownerName = player.getName.getString
drone.ownerUUID = player.getGameProfile.getId
}
drone.initializeAfterPlacement(stack, player, position.offset(hitX * 1.1f, hitY * 1.1f, hitZ * 1.1f))
- world.spawnEntity(drone)
+ world.addFreshEntity(drone)
}
stack.shrink(1)
true
diff --git a/src/main/scala/li/cil/oc/common/item/DroneCase.scala b/src/main/scala/li/cil/oc/common/item/DroneCase.scala
index 8564082602..5cab2ea526 100644
--- a/src/main/scala/li/cil/oc/common/item/DroneCase.scala
+++ b/src/main/scala/li/cil/oc/common/item/DroneCase.scala
@@ -1,11 +1,15 @@
package li.cil.oc.common.item
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
-class DroneCase(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class DroneCase(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
override protected def tierFromDriver(stack: ItemStack) = tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/EEPROM.scala b/src/main/scala/li/cil/oc/common/item/EEPROM.scala
index b39cd96913..c19dde357e 100644
--- a/src/main/scala/li/cil/oc/common/item/EEPROM.scala
+++ b/src/main/scala/li/cil/oc/common/item/EEPROM.scala
@@ -2,24 +2,29 @@ package li.cil.oc.common.item
import li.cil.oc.Settings
import li.cil.oc.util.BlockPosition
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IWorldReader
+import net.minecraftforge.common.extensions.IForgeItem
-class EEPROM(val parent: Delegator) extends traits.Delegate {
- override def displayName(stack: ItemStack): Option[String] = {
- if (stack.hasTagCompound) {
- val tag = stack.getTagCompound
- if (tag.hasKey(Settings.namespace + "data")) {
- val data = tag.getCompoundTag(Settings.namespace + "data")
- if (data.hasKey(Settings.namespace + "label")) {
- return Some(data.getString(Settings.namespace + "label"))
+class EEPROM(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def getName(stack: ItemStack): ITextComponent = {
+ if (stack.hasTag) {
+ val tag = stack.getTag
+ if (tag.contains(Settings.namespace + "data")) {
+ val data = tag.getCompound(Settings.namespace + "data")
+ if (data.contains(Settings.namespace + "label")) {
+ return new StringTextComponent(data.getString(Settings.namespace + "label"))
}
}
}
- super.displayName(stack)
+ super.getName(stack)
}
- override def doesSneakBypassUse(world: IBlockAccess, pos: BlockPos, player: EntityPlayer): Boolean = true
+ override def doesSneakBypassUse(stack: ItemStack, world: IWorldReader, pos: BlockPos, player: PlayerEntity): Boolean = true
}
diff --git a/src/main/scala/li/cil/oc/common/item/FloppyDisk.scala b/src/main/scala/li/cil/oc/common/item/FloppyDisk.scala
index c122216b9b..31732aa3d0 100644
--- a/src/main/scala/li/cil/oc/common/item/FloppyDisk.scala
+++ b/src/main/scala/li/cil/oc/common/item/FloppyDisk.scala
@@ -2,45 +2,49 @@ package li.cil.oc.common.item
import li.cil.oc.Constants
import li.cil.oc.Settings
-import li.cil.oc.util.Color
-import net.minecraft.client.renderer.block.model.ModelBakery
-import net.minecraft.client.renderer.block.model.ModelResourceLocation
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.client.renderer.model.ModelBakery
+import net.minecraft.client.renderer.model.ModelResourceLocation
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.DyeColor
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.world.IWorldReader
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.client.model.ModelLoader
+import net.minecraftforge.common.extensions.IForgeItem
-class FloppyDisk(val parent: Delegator) extends traits.Delegate with CustomModel with traits.FileSystemLike {
+class FloppyDisk(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with CustomModel with traits.FileSystemLike {
// Necessary for anonymous subclasses used for loot disks.
- override def unlocalizedName = "floppydisk"
+ unlocalizedName = "floppydisk"
val kiloBytes = Settings.get.floppySize
- @SideOnly(Side.CLIENT)
- private def modelLocationFromDyeName(name: String) = {
- new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.ItemName.Floppy + "_" + name, "inventory")
+ @OnlyIn(Dist.CLIENT)
+ private def modelLocationFromDyeName(dye: DyeColor) = {
+ new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.ItemName.Floppy + "_" + dye.getName, "inventory")
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def getModelLocation(stack: ItemStack): ModelResourceLocation = {
val dyeIndex =
- if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "color"))
- stack.getTagCompound.getInteger(Settings.namespace + "color")
+ if (stack.hasTag && stack.getTag.contains(Settings.namespace + "color"))
+ stack.getTag.getInt(Settings.namespace + "color")
else
- 8
- modelLocationFromDyeName(Color.dyes(dyeIndex max 0 min 15))
+ DyeColor.LIGHT_GRAY.getId
+ modelLocationFromDyeName(DyeColor.byId(dyeIndex max 0 min 15))
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def registerModelLocations(): Unit = {
- for (dyeName <- Color.dyes) {
- val location = modelLocationFromDyeName(dyeName)
- ModelBakery.registerItemVariants(parent, new ResourceLocation(location.getResourceDomain + ":" + location.getResourcePath))
+ for (dye <- DyeColor.values) {
+ val location = modelLocationFromDyeName(dye)
+ ModelLoader.addSpecialModel(location)
}
}
- override def doesSneakBypassUse(world: IBlockAccess, pos: BlockPos, player: EntityPlayer): Boolean = true
+ override def doesSneakBypassUse(stack: ItemStack, world: IWorldReader, pos: BlockPos, player: PlayerEntity): Boolean = true
}
diff --git a/src/main/scala/li/cil/oc/common/item/GraphicsCard.scala b/src/main/scala/li/cil/oc/common/item/GraphicsCard.scala
index 0fb7074615..777e1ddda5 100644
--- a/src/main/scala/li/cil/oc/common/item/GraphicsCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/GraphicsCard.scala
@@ -1,9 +1,14 @@
package li.cil.oc.common.item
-class GraphicsCard(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier with traits.GPULike {
- override val unlocalizedName = super.unlocalizedName + tier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class GraphicsCard(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier with traits.GPULike {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
override def gpuTier = tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/HardDiskDrive.scala b/src/main/scala/li/cil/oc/common/item/HardDiskDrive.scala
index 2f6ba39c42..d4457b5131 100644
--- a/src/main/scala/li/cil/oc/common/item/HardDiskDrive.scala
+++ b/src/main/scala/li/cil/oc/common/item/HardDiskDrive.scala
@@ -1,20 +1,28 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraftforge.common.extensions.IForgeItem
+
+class HardDiskDrive(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier with traits.FileSystemLike {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
-class HardDiskDrive(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier with traits.FileSystemLike {
- override val unlocalizedName: String = super.unlocalizedName + tier
val kiloBytes: Int = Settings.get.hddSizes(tier)
val platterCount: Int = Settings.get.hddPlatterCounts(tier)
- override def displayName(stack: ItemStack): Some[String] = {
- val localizedName = parent.internalGetItemStackDisplayName(stack)
- Some(if (kiloBytes >= 1024) {
- localizedName + s" (${kiloBytes / 1024}MB)"
+ override def getName(stack: ItemStack): ITextComponent = {
+ val localizedName = super.getName(stack).copy()
+ if (kiloBytes >= 1024) {
+ localizedName.append(s" (${kiloBytes / 1024}MB)")
}
else {
- localizedName + s" (${kiloBytes}KB)"
- })
+ localizedName.append(s" (${kiloBytes}KB)")
+ }
+ localizedName
}
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/HoverBoots.scala b/src/main/scala/li/cil/oc/common/item/HoverBoots.scala
index 722a44059d..7d61f9defa 100644
--- a/src/main/scala/li/cil/oc/common/item/HoverBoots.scala
+++ b/src/main/scala/li/cil/oc/common/item/HoverBoots.scala
@@ -2,30 +2,34 @@ package li.cil.oc.common.item
import li.cil.oc.Settings
import li.cil.oc.client.renderer.item.HoverBootRenderer
+import li.cil.oc.common.init.Items
import li.cil.oc.common.item.data.HoverBootsData
import li.cil.oc.util.ItemColorizer
-import net.minecraft.block.BlockCauldron
-import net.minecraft.client.model.ModelBiped
-import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.item.EntityItem
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.init.Blocks
-import net.minecraft.inventory.EntityEquipmentSlot
-import net.minecraft.item.EnumRarity
-import net.minecraft.item.ItemArmor
+import net.minecraft.block.Blocks
+import net.minecraft.block.CauldronBlock
+import net.minecraft.client.renderer.entity.model.BipedModel
+import net.minecraft.inventory.EquipmentSlotType
+import net.minecraft.item.ArmorItem
+import net.minecraft.item.ArmorMaterial
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
-import net.minecraft.potion.Potion
-import net.minecraft.potion.PotionEffect
+import net.minecraft.item.Rarity
+import net.minecraft.entity.Entity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.item.ItemEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.potion.Effect
+import net.minecraft.potion.Effects
+import net.minecraft.potion.EffectInstance
+import net.minecraft.util.NonNullList
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, EntityEquipmentSlot.FEET) with traits.SimpleItem with traits.Chargeable {
- setNoRepair()
-
- override def getRarity(stack: ItemStack): EnumRarity = EnumRarity.UNCOMMON
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.common.extensions.IForgeItem
+class HoverBoots(props: Properties) extends ArmorItem(ArmorMaterial.DIAMOND, EquipmentSlotType.FEET, props) with IForgeItem with traits.SimpleItem with traits.Chargeable {
override def maxCharge(stack: ItemStack): Double = Settings.get.bufferHoverBoots
override def getCharge(stack: ItemStack): Double =
@@ -34,7 +38,7 @@ class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, EntityEqu
override def setCharge(stack: ItemStack, amount: Double): Unit = {
val data = new HoverBootsData(stack)
data.charge = math.min(maxCharge(stack), math.max(0, amount))
- data.save(stack)
+ data.saveData(stack)
}
override def canCharge(stack: ItemStack): Boolean = true
@@ -43,45 +47,50 @@ class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, EntityEqu
val data = new HoverBootsData(stack)
traits.Chargeable.applyCharge(amount, data.charge, Settings.get.bufferHoverBoots, used => if (!simulate) {
data.charge += used
- data.save(stack)
+ data.saveData(stack)
})
}
- @SideOnly(Side.CLIENT)
- override def getArmorModel(entityLiving: EntityLivingBase, itemStack: ItemStack, armorSlot: EntityEquipmentSlot, _default: ModelBiped): ModelBiped = {
- if (armorSlot == armorType) {
+ override def fillItemCategory(tab: ItemGroup, list: NonNullList[ItemStack]): Unit = {
+ super.fillItemCategory(tab, list)
+ if (allowdedIn(tab)) list.add(Items.createChargedHoverBoots())
+ }
+
+ @OnlyIn(Dist.CLIENT)
+ override def getArmorModel[A <: BipedModel[_]](entityLiving: LivingEntity, itemStack: ItemStack, armorSlot: EquipmentSlotType, _default: A): A = {
+ if (armorSlot == slot) {
HoverBootRenderer.lightColor = if (ItemColorizer.hasColor(itemStack)) ItemColorizer.getColor(itemStack) else 0x66DD55
- HoverBootRenderer
+ HoverBootRenderer.asInstanceOf[A]
}
else super.getArmorModel(entityLiving, itemStack, armorSlot, _default)
}
- override def getArmorTexture(stack: ItemStack, entity: Entity, slot: EntityEquipmentSlot, subType: String): String = {
- if (entity.world.isRemote) HoverBootRenderer.texture.toString
+ override def getArmorTexture(stack: ItemStack, entity: Entity, slot: EquipmentSlotType, subType: String): String = {
+ if (entity.level.isClientSide) HoverBootRenderer.texture.toString
else null
}
- override def onArmorTick(world: World, player: EntityPlayer, stack: ItemStack): Unit = {
- super.onArmorTick(world, player, stack)
- if (!Settings.get.ignorePower && player.getActivePotionEffect(Potion.getPotionFromResourceLocation("slowness")) == null && getCharge(stack) == 0) {
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("slowness"), 20, 1))
+ override def onArmorTick(stack: ItemStack, world: World, player: PlayerEntity): Unit = {
+ super.onArmorTick(stack, world, player)
+ if (!Settings.get.ignorePower && player.getEffect(Effects.MOVEMENT_SLOWDOWN) == null && getCharge(stack) == 0) {
+ player.addEffect(new EffectInstance(Effects.MOVEMENT_SLOWDOWN, 20, 1))
}
}
- override def onEntityItemUpdate(entity: EntityItem): Boolean = {
- if (entity != null && entity.world != null && !entity.world.isRemote && ItemColorizer.hasColor(entity.getItem)) {
- val pos = entity.getPosition
- val state = entity.world.getBlockState(pos)
+ override def onEntityItemUpdate(stack: ItemStack, entity: ItemEntity): Boolean = {
+ if (entity != null && entity.level != null && !entity.level.isClientSide && ItemColorizer.hasColor(stack)) {
+ val pos = entity.blockPosition
+ val state = entity.level.getBlockState(pos)
if (state.getBlock == Blocks.CAULDRON) {
- val level = state.getValue(BlockCauldron.LEVEL).toInt
+ val level = state.getValue(CauldronBlock.LEVEL).toInt
if (level > 0) {
- ItemColorizer.removeColor(entity.getItem)
- entity.world.setBlockState(pos, state.withProperty(BlockCauldron.LEVEL, Int.box(level - 1)), 3)
+ ItemColorizer.removeColor(stack)
+ entity.level.setBlock(pos, state.setValue(CauldronBlock.LEVEL, Int.box(level - 1)), 3)
return true
}
}
}
- super.onEntityItemUpdate(entity)
+ super.onEntityItemUpdate(stack, entity)
}
override def showDurabilityBar(stack: ItemStack): Boolean = true
@@ -97,7 +106,7 @@ class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, EntityEqu
override def isDamaged(stack: ItemStack): Boolean = true
// Contradictory as it may seem with the above, this avoids actual damage value changing.
- override def isDamageable: Boolean = false
+ override def canBeDepleted: Boolean = false
override def setDamage(stack: ItemStack, damage: Int): Unit = {
// Subtract energy when taking damage instead of actually damaging the item.
diff --git a/src/main/scala/li/cil/oc/common/item/InkCartridge.scala b/src/main/scala/li/cil/oc/common/item/InkCartridge.scala
index 1477984fae..a85168a066 100644
--- a/src/main/scala/li/cil/oc/common/item/InkCartridge.scala
+++ b/src/main/scala/li/cil/oc/common/item/InkCartridge.scala
@@ -1,18 +1,7 @@
package li.cil.oc.common.item
-import li.cil.oc.Constants
-import li.cil.oc.api
-import net.minecraft.item.ItemStack
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
-class InkCartridge(val parent: Delegator) extends traits.Delegate {
- override def maxStackSize = 1
-
- override def getContainerItem(stack: ItemStack): ItemStack = {
- if (api.Items.get(stack) == api.Items.get(Constants.ItemName.InkCartridge))
- api.Items.get(Constants.ItemName.InkCartridgeEmpty).createItemStack(1)
- else
- super.getContainerItem(stack)
- }
-
- override def hasContainerItem(stack: ItemStack): Boolean = true
-}
+class InkCartridge(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala b/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala
index f7a879ca21..cb68dc3dd3 100644
--- a/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala
+++ b/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala
@@ -1,5 +1,7 @@
package li.cil.oc.common.item
-class InkCartridgeEmpty(val parent: Delegator) extends traits.Delegate {
- override def maxStackSize = 1
-}
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class InkCartridgeEmpty(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/InternetCard.scala b/src/main/scala/li/cil/oc/common/item/InternetCard.scala
index 5c43ebc508..fc0cc79e24 100644
--- a/src/main/scala/li/cil/oc/common/item/InternetCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/InternetCard.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class InternetCard(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class InternetCard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/Interweb.scala b/src/main/scala/li/cil/oc/common/item/Interweb.scala
index 7e1fdbc78c..bd13b0f0cc 100644
--- a/src/main/scala/li/cil/oc/common/item/Interweb.scala
+++ b/src/main/scala/li/cil/oc/common/item/Interweb.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class Interweb(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class Interweb(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/LinkedCard.scala b/src/main/scala/li/cil/oc/common/item/LinkedCard.scala
index 11a24cccec..e97ba02620 100644
--- a/src/main/scala/li/cil/oc/common/item/LinkedCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/LinkedCard.scala
@@ -5,24 +5,38 @@ import java.util
import li.cil.oc.Settings
import li.cil.oc.util.Tooltip
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.common.extensions.IForgeItem
-class LinkedCard(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
- override def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "data")) {
- val data = stack.getTagCompound.getCompoundTag(Settings.namespace + "data")
- if (data.hasKey(Settings.namespace + "tunnel")) {
+import scala.collection.convert.ImplicitConversionsToScala._
+
+class LinkedCard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
+ if (stack.hasTag && stack.getTag.contains(Settings.namespace + "data")) {
+ val data = stack.getTag.getCompound(Settings.namespace + "data")
+ if (data.contains(Settings.namespace + "tunnel")) {
val channel = data.getString(Settings.namespace + "tunnel")
if (channel.length > 13) {
- tooltip.addAll(Tooltip.get(unlocalizedName + "_channel", channel.substring(0, 13) + "..."))
+ for (curr <- Tooltip.get(unlocalizedName + "_channel", channel.substring(0, 13) + "...")) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
else {
- tooltip.addAll(Tooltip.get(unlocalizedName + "_channel", channel))
+ for (curr <- Tooltip.get(unlocalizedName + "_channel", channel)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
}
}
- super.tooltipLines(stack, world, tooltip, flag)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/Manual.scala b/src/main/scala/li/cil/oc/common/item/Manual.scala
index bafecea267..5a4c667338 100644
--- a/src/main/scala/li/cil/oc/common/item/Manual.scala
+++ b/src/main/scala/li/cil/oc/common/item/Manual.scala
@@ -6,38 +6,43 @@ import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.util.BlockPosition
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TextFormatting
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.common.extensions.IForgeItem
-class Manual(val parent: Delegator) extends traits.Delegate {
- @SideOnly(Side.CLIENT)
- override def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag): Unit = {
- tooltip.add(TextFormatting.DARK_GRAY.toString + "v" + OpenComputers.Version)
- super.tooltipLines(stack, world, tooltip, flag)
+class Manual(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
+ tooltip.add(new StringTextComponent(TextFormatting.DARK_GRAY.toString + "v" + OpenComputers.get.Version))
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (world.isRemote) {
- if (player.isSneaking) {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (world.isClientSide) {
+ if (player.isCrouching) {
api.Manual.reset()
}
api.Manual.openFor(player)
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
- override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- val world = player.getEntityWorld
+ override def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ val world = player.level
api.Manual.pathFor(world, position.toBlockPos) match {
case path: String =>
- if (world.isRemote) {
+ if (world.isClientSide) {
api.Manual.openFor(player)
api.Manual.reset()
api.Manual.navigate(path)
diff --git a/src/main/scala/li/cil/oc/common/item/Memory.scala b/src/main/scala/li/cil/oc/common/item/Memory.scala
index 9eb4652b15..f3c1a66e27 100644
--- a/src/main/scala/li/cil/oc/common/item/Memory.scala
+++ b/src/main/scala/li/cil/oc/common/item/Memory.scala
@@ -1,7 +1,12 @@
package li.cil.oc.common.item
-class Memory(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
- override protected def tooltipName = Option(super.unlocalizedName)
+class Memory(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
+
+ override protected def tooltipName = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/Microchip.scala b/src/main/scala/li/cil/oc/common/item/Microchip.scala
index 42fbc20ecf..cee66f9f10 100644
--- a/src/main/scala/li/cil/oc/common/item/Microchip.scala
+++ b/src/main/scala/li/cil/oc/common/item/Microchip.scala
@@ -1,12 +1,13 @@
package li.cil.oc.common.item
-import li.cil.oc.util.Rarity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
-class Microchip(val parent: Delegator, val tier: Int) extends traits.Delegate {
- override val unlocalizedName = super.unlocalizedName + tier
+class Microchip(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
-
- override def rarity(stack: ItemStack) = Rarity.byTier(tier)
+ override protected def tooltipName = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/MicrocontrollerCase.scala b/src/main/scala/li/cil/oc/common/item/MicrocontrollerCase.scala
index 70d092b68d..8483e67594 100644
--- a/src/main/scala/li/cil/oc/common/item/MicrocontrollerCase.scala
+++ b/src/main/scala/li/cil/oc/common/item/MicrocontrollerCase.scala
@@ -1,11 +1,15 @@
package li.cil.oc.common.item
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
-class MicrocontrollerCase(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class MicrocontrollerCase(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
override protected def tierFromDriver(stack: ItemStack) = tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/Nanomachines.scala b/src/main/scala/li/cil/oc/common/item/Nanomachines.scala
index f7e179bd8a..d4e132a4a7 100644
--- a/src/main/scala/li/cil/oc/common/item/Nanomachines.scala
+++ b/src/main/scala/li/cil/oc/common/item/Nanomachines.scala
@@ -7,45 +7,48 @@ import li.cil.oc.api
import li.cil.oc.common.item.data.NanomachineData
import li.cil.oc.common.nanomachines.ControllerImpl
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumAction
-import net.minecraft.item.EnumRarity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraft.item.Rarity
+import net.minecraft.item.UseAction
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.common.extensions.IForgeItem
-class Nanomachines(val parent: Delegator) extends traits.Delegate {
- override def rarity(stack: ItemStack): EnumRarity = EnumRarity.UNCOMMON
-
- @SideOnly(Side.CLIENT)
- override def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag): Unit = {
- super.tooltipLines(stack, world, tooltip, flag)
- if (stack.hasTagCompound) {
+class Nanomachines(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
+ if (stack.hasTag) {
val data = new NanomachineData(stack)
if (!Strings.isNullOrEmpty(data.uuid)) {
- tooltip.add("§8" + data.uuid.substring(0, 13) + "...§7")
+ tooltip.add(new StringTextComponent("§8" + data.uuid.substring(0, 13) + "...§7"))
}
}
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- player.setActiveHand(if (player.getHeldItemMainhand == stack) EnumHand.MAIN_HAND else EnumHand.OFF_HAND)
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ player.startUsingItem(if (player.getItemInHand(Hand.MAIN_HAND) == stack) Hand.MAIN_HAND else Hand.OFF_HAND)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
- override def getItemUseAction(stack: ItemStack): EnumAction = EnumAction.EAT
+ override def getUseAnimation(stack: ItemStack): UseAction = UseAction.EAT
- override def getMaxItemUseDuration(stack: ItemStack): Int = 32
+ override def getUseDuration(stack: ItemStack): Int = 32
- override def onItemUseFinish(stack: ItemStack, world: World, entity: EntityLivingBase): ItemStack = {
+ override def finishUsingItem(stack: ItemStack, world: World, entity: LivingEntity): ItemStack = {
entity match {
- case player: EntityPlayer =>
- if (!world.isRemote) {
+ case player: PlayerEntity =>
+ if (!world.isClientSide) {
val data = new NanomachineData(stack)
// Re-install to get new address, make sure we're configured.
@@ -57,7 +60,7 @@ class Nanomachines(val parent: Delegator) extends traits.Delegate {
if (!Strings.isNullOrEmpty(data.uuid)) {
controller.uuid = data.uuid
}
- controller.configuration.load(nbt)
+ controller.configuration.loadData(nbt)
case _ => controller.reconfigure()
}
case controller => controller.reconfigure() // Huh.
diff --git a/src/main/scala/li/cil/oc/common/item/NetworkCard.scala b/src/main/scala/li/cil/oc/common/item/NetworkCard.scala
index 89b64cf928..6fabdf6c28 100644
--- a/src/main/scala/li/cil/oc/common/item/NetworkCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/NetworkCard.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class NetworkCard(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class NetworkCard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/NumPad.scala b/src/main/scala/li/cil/oc/common/item/NumPad.scala
index 57d50028e1..775b312da5 100644
--- a/src/main/scala/li/cil/oc/common/item/NumPad.scala
+++ b/src/main/scala/li/cil/oc/common/item/NumPad.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class NumPad(val parent: Delegator) extends traits.Delegate
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class NumPad(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/Present.scala b/src/main/scala/li/cil/oc/common/item/Present.scala
index 62684d1c5f..5a612f8cd1 100644
--- a/src/main/scala/li/cil/oc/common/item/Present.scala
+++ b/src/main/scala/li/cil/oc/common/item/Present.scala
@@ -7,33 +7,42 @@ import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.init.SoundEvents
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
+import net.minecraft.item.crafting.RecipeManager
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.NonNullList
import net.minecraft.util.SoundCategory
+import net.minecraft.util.SoundEvents
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
import scala.collection.mutable
-class Present(val parent: Delegator) extends traits.Delegate {
- showInItemList = false
+class Present(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def fillItemCategory(tab: ItemGroup, list: NonNullList[ItemStack]) {}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
if (stack.getCount > 0) {
stack.shrink(1)
- if (!world.isRemote) {
- world.playSound(player, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_PLAYER_LEVELUP, SoundCategory.MASTER, 0.2f, 1f)
+ if (!world.isClientSide) {
+ world.playSound(player, player.getX, player.getY, player.getZ, SoundEvents.PLAYER_LEVELUP, SoundCategory.MASTER, 0.2f, 1f)
+ Present.recipeManager = world.getRecipeManager
val present = Present.nextPresent()
InventoryUtils.addToPlayerInventory(present, player)
}
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
}
object Present {
+ private var recipeManager: RecipeManager = null
+
private lazy val Presents = {
val result = mutable.ArrayBuffer.empty[ItemStack]
@@ -42,7 +51,7 @@ object Present {
if (item != null) {
val stack = item.createItemStack(1)
// Only if it can be crafted (wasn't disabled in the config).
- if (ItemUtils.getIngredients(stack).nonEmpty) {
+ if (ItemUtils.getIngredients(recipeManager, stack).nonEmpty) {
for (i <- 0 until weight) result += stack
}
}
@@ -134,5 +143,5 @@ object Present {
private val rng = new Random()
- def nextPresent(): ItemStack = Presents(rng.nextInt(Presents.length)).copy()
+ private def nextPresent(): ItemStack = Presents(rng.nextInt(Presents.length)).copy()
}
diff --git a/src/main/scala/li/cil/oc/common/item/PrintedCircuitBoard.scala b/src/main/scala/li/cil/oc/common/item/PrintedCircuitBoard.scala
index 37a0097b3c..d1d68e5ac7 100644
--- a/src/main/scala/li/cil/oc/common/item/PrintedCircuitBoard.scala
+++ b/src/main/scala/li/cil/oc/common/item/PrintedCircuitBoard.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class PrintedCircuitBoard(val parent: Delegator) extends traits.Delegate
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class PrintedCircuitBoard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
diff --git a/src/main/scala/li/cil/oc/common/item/RawCircuitBoard.scala b/src/main/scala/li/cil/oc/common/item/RawCircuitBoard.scala
index 5e52e7416e..b6d6483e31 100644
--- a/src/main/scala/li/cil/oc/common/item/RawCircuitBoard.scala
+++ b/src/main/scala/li/cil/oc/common/item/RawCircuitBoard.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class RawCircuitBoard(val parent: Delegator) extends traits.Delegate
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class RawCircuitBoard(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/RedstoneCard.scala b/src/main/scala/li/cil/oc/common/item/RedstoneCard.scala
index db8c0c34e6..69ee306719 100644
--- a/src/main/scala/li/cil/oc/common/item/RedstoneCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/RedstoneCard.scala
@@ -3,23 +3,21 @@ package li.cil.oc.common.item
import java.util
import li.cil.oc.common.Tier
+import li.cil.oc.integration.opencomputers.ModOpenComputers
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
+import net.minecraft.util.NonNullList
+import net.minecraftforge.common.extensions.IForgeItem
-class RedstoneCard(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class RedstoneCard(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
- // Note: T2 is enabled in mod integration, if it makes sense.
- showInItemList = tier == Tier.One
-
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
- super.tooltipExtended(stack, tooltip)
- if (tier == Tier.Two) {
- // TODO Generic system for redstone integration modules to register in a list of tooltip lines.
- // if (Mods.MOD_NAME.isAvailable) {
- // tooltip.addAll(Tooltip.get(super.unlocalizedName + ".MOD_NAME"))
- // }
- }
+ override def fillItemCategory(tab: ItemGroup, list: NonNullList[ItemStack]) {
+ if (tier == Tier.One || ModOpenComputers.hasRedstoneCardT2) super.fillItemCategory(tab, list)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/Server.scala b/src/main/scala/li/cil/oc/common/item/Server.scala
index 953fa1001d..64258a9fc3 100644
--- a/src/main/scala/li/cil/oc/common/item/Server.scala
+++ b/src/main/scala/li/cil/oc/common/item/Server.scala
@@ -4,61 +4,73 @@ import java.util
import li.cil.oc.OpenComputers
import li.cil.oc.client.KeyBindings
-import li.cil.oc.common.GuiType
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.inventory.ServerInventory
-import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumRarity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
import scala.collection.mutable
+import scala.collection.convert.ImplicitConversionsToScala._
-class Server(val parent: Delegator, val tier: Int) extends traits.Delegate {
- override val unlocalizedName: String = super.unlocalizedName + tier
+class Server(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
-
- override def rarity(stack: ItemStack): EnumRarity = Rarity.byTier(tier)
-
- override def maxStackSize = 1
+ override protected def tooltipName = Option(unlocalizedName)
private object HelperInventory extends ServerInventory {
var container = ItemStack.EMPTY
+
+ override def rackSlot = -1
}
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[ITextComponent]) {
super.tooltipExtended(stack, tooltip)
if (KeyBindings.showExtendedTooltips) {
HelperInventory.container = stack
HelperInventory.reinitialize()
val stacks = mutable.Map.empty[String, Int]
- for (aStack <- (0 until HelperInventory.getSizeInventory).map(HelperInventory.getStackInSlot) if !aStack.isEmpty) {
- val displayName = aStack.getDisplayName
+ for (aStack <- (0 until HelperInventory.getContainerSize).map(HelperInventory.getItem) if !aStack.isEmpty) {
+ val displayName = aStack.getHoverName.getString
stacks += displayName -> (if (stacks.contains(displayName)) stacks(displayName) + 1 else 1)
}
if (stacks.nonEmpty) {
- tooltip.addAll(Tooltip.get("server.Components"))
+ for (curr <- Tooltip.get("server.Components")) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
for (itemName <- stacks.keys.toArray.sorted) {
- tooltip.add("- " + stacks(itemName) + "x " + itemName)
+ tooltip.add(new StringTextComponent("- " + stacks(itemName) + "x " + itemName).setStyle(Tooltip.DefaultStyle))
}
}
}
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (!player.isSneaking) {
- // Open the GUI immediately on the client, too, to avoid the player
- // changing the current slot before it actually opens, which can lead to
- // desynchronization of the player inventory.
- player.openGui(OpenComputers, GuiType.Server.id, world, 0, 0, 0)
- player.swingArm(EnumHand.MAIN_HAND)
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (!player.isCrouching) {
+ if (!world.isClientSide) player match {
+ case srvPlr: ServerPlayerEntity => ContainerTypes.openServerGui(srvPlr, new ServerInventory {
+ override def container = stack
+
+ override def rackSlot = -1
+
+ override def stillValid(player: PlayerEntity) = player == srvPlr
+ }, -1)
+ case _ =>
+ }
+ player.swing(Hand.MAIN_HAND)
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/Tablet.scala b/src/main/scala/li/cil/oc/common/item/Tablet.scala
index fd690ae722..4e4a463588 100644
--- a/src/main/scala/li/cil/oc/common/item/Tablet.scala
+++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala
@@ -23,9 +23,11 @@ import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.{client, server}
import li.cil.oc.client.KeyBindings
-import li.cil.oc.common.GuiType
+import li.cil.oc.client.gui
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.item.data.TabletData
import li.cil.oc.integration.opencomputers.DriverScreen
@@ -37,61 +39,74 @@ import li.cil.oc.util.Rarity
import li.cil.oc.util.RotationHelper
import li.cil.oc.util.Tooltip
import net.minecraft.client.Minecraft
-import net.minecraft.client.renderer.block.model.ModelBakery
-import net.minecraft.client.renderer.block.model.ModelResourceLocation
+import net.minecraft.client.renderer.model.ModelBakery
+import net.minecraft.client.renderer.model.ModelResourceLocation
import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
-import net.minecraft.item.EnumRarity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.player.{PlayerEntity, PlayerInventory, ServerPlayerEntity}
+import net.minecraft.inventory.container.INamedContainerProvider
+import net.minecraft.item // Rarity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.server.integrated.IntegratedServer
-import net.minecraft.util._
+import net.minecraft.util.ActionResult
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
+import net.minecraft.util.NonNullList
+import net.minecraft.util.ResourceLocation
+import net.minecraft.util.Util
+import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.client.model.ModelLoader
+import net.minecraftforge.common.extensions.IForgeItem
import net.minecraftforge.event.world.WorldEvent
-import net.minecraftforge.fml.common.FMLCommonHandler
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.event.TickEvent.ClientTickEvent
+import net.minecraftforge.event.TickEvent.ServerTickEvent
+import net.minecraftforge.eventbus.api.SubscribeEvent
+import net.minecraftforge.fml.server.ServerLifecycleHooks
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
-class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel with traits.Chargeable {
+class Tablet(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with CustomModel with traits.Chargeable {
final val TimeToAnalyze = 10
- // Must be assembled to be usable so we hide it in the item list.
- showInItemList = false
-
- override def maxStackSize = 1
-
// ----------------------------------------------------------------------- //
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[ITextComponent]): Unit = {
if (KeyBindings.showExtendedTooltips) {
val info = new TabletData(stack)
// Ignore/hide the screen.
val components = info.items.drop(1)
if (components.length > 1) {
- tooltip.addAll(Tooltip.get("server.Components"))
+ for (curr <- Tooltip.get("server.Components")) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
components.collect {
- case component if !component.isEmpty => tooltip.add("- " + component.getDisplayName)
+ case component if !component.isEmpty => tooltip.add(new StringTextComponent("- " + component.getHoverName.getString).setStyle(Tooltip.DefaultStyle))
}
}
}
}
- override def rarity(stack: ItemStack): EnumRarity = {
+ override def getRarity(stack: ItemStack): item.Rarity = {
val data = new TabletData(stack)
Rarity.byTier(data.tier)
}
override def showDurabilityBar(stack: ItemStack) = true
- override def durability(stack: ItemStack): Double = {
- if (stack.hasTagCompound) {
+ override def getDurabilityForDisplay(stack: ItemStack): Double = {
+ if (stack.hasTag) {
val data = Tablet.Client.getWeak(stack) match {
case Some(wrapper) => wrapper.data
case _ => new TabletData(stack)
@@ -103,7 +118,7 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
private def modelLocationFromState(running: Option[Boolean]) = {
val suffix = running match {
case Some(state) => if (state) "_on" else "_off"
@@ -112,7 +127,7 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.ItemName.Tablet + suffix, "inventory")
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def getModelLocation(stack: ItemStack): ModelResourceLocation = {
modelLocationFromState(Tablet.Client.getWeak(stack) match {
case Some(tablet: TabletWrapper) => Some(tablet.data.isRunning)
@@ -120,11 +135,10 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
})
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def registerModelLocations(): Unit = {
for (state <- Seq(None, Some(true), Some(false))) {
- val location = modelLocationFromState(state)
- ModelBakery.registerItemVariants(parent, new ResourceLocation(location.getResourceDomain + ":" + location.getResourcePath))
+ ModelLoader.addSpecialModel(modelLocationFromState(state))
}
}
@@ -135,54 +149,56 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
val data = new TabletData(stack)
traits.Chargeable.applyCharge(amount, data.energy, data.maxEnergy, used => if (!simulate) {
data.energy += used
- data.save(stack)
+ data.saveData(stack)
})
}
// ----------------------------------------------------------------------- //
- override def update(stack: ItemStack, world: World, entity: Entity, slot: Int, selected: Boolean): Unit =
+ // Must be assembled to be usable so we hide it in the item list.
+ override def fillItemCategory(tab: ItemGroup, list: NonNullList[ItemStack]) {}
+
+ override def inventoryTick(stack: ItemStack, world: World, entity: Entity, slot: Int, selected: Boolean): Unit =
entity match {
- case player: EntityPlayer =>
+ case player: PlayerEntity =>
// Play an audio cue to let players know when they finished analyzing a block.
- if (world.isRemote && player.getItemInUseCount == TimeToAnalyze && api.Items.get(player.getActiveItemStack) == api.Items.get(Constants.ItemName.Tablet)) {
- Audio.play(player.posX.toFloat, player.posY.toFloat + 2, player.posZ.toFloat, ".")
+ if (world.isClientSide && player.getUseItemRemainingTicks == TimeToAnalyze && api.Items.get(player.getUseItem) == api.Items.get(Constants.ItemName.Tablet)) {
+ Audio.play(player.getX.toFloat, player.getY.toFloat + 2, player.getZ.toFloat, ".")
}
Tablet.get(stack, player).update(world, player, slot, selected)
case _ =>
}
- override def onItemUseFirst(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): EnumActionResult = {
- Tablet.currentlyAnalyzing = Some((position, side, hitX, hitY, hitZ))
- super.onItemUseFirst(stack, player, position, side, hitX, hitY, hitZ)
+ override def onItemUseFirst(stack: ItemStack, player: PlayerEntity, world: World, pos: BlockPos, side: Direction, hitX: Float, hitY: Float, hitZ: Float, hand: Hand): ActionResultType = {
+ Tablet.currentlyAnalyzing = Some((BlockPosition(pos, world), side, hitX, hitY, hitZ))
+ super.onItemUseFirst(stack, player, world, pos, side, hitX, hitY, hitZ, hand)
}
- override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- player.setActiveHand(if (player.getHeldItemMainhand == stack) EnumHand.MAIN_HAND else EnumHand.OFF_HAND)
+ override def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ player.startUsingItem(if (player.getItemInHand(Hand.MAIN_HAND) == stack) Hand.MAIN_HAND else Hand.OFF_HAND)
true
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- player.setActiveHand(if (player.getHeldItemMainhand == stack) EnumHand.MAIN_HAND else EnumHand.OFF_HAND)
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ player.startUsingItem(if (player.getItemInHand(Hand.MAIN_HAND) == stack) Hand.MAIN_HAND else Hand.OFF_HAND)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
- override def getMaxItemUseDuration(stack: ItemStack): Int = 72000
+ override def getUseDuration(stack: ItemStack): Int = 72000
- override def onPlayerStoppedUsing(stack: ItemStack, entity: EntityLivingBase, duration: Int): Unit = {
+ override def releaseUsing(stack: ItemStack, world: World, entity: LivingEntity, duration: Int): Unit = {
entity match {
- case player: EntityPlayer =>
- val world = player.getEntityWorld
- val didAnalyze = getMaxItemUseDuration(stack) - duration >= TimeToAnalyze
+ case player: PlayerEntity =>
+ val didAnalyze = getUseDuration(stack) - duration >= TimeToAnalyze
if (didAnalyze) {
- if (!world.isRemote) {
+ if (!world.isClientSide) {
Tablet.currentlyAnalyzing match {
case Some((position, side, hitX, hitY, hitZ)) => try {
val computer = Tablet.get(stack, player).machine
if (computer.isRunning) {
- val data = new NBTTagCompound()
+ val data = new CompoundNBT()
computer.node.sendToReachable("tablet.use", data, stack, player, position, side, Float.box(hitX), Float.box(hitY), Float.box(hitZ))
- if (!data.hasNoTags) {
+ if (!data.isEmpty) {
computer.signal("tablet_use", data)
}
}
@@ -195,26 +211,32 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
}
}
else {
- if (player.isSneaking) {
- if (!world.isRemote) {
+ if (player.isCrouching) {
+ if (!world.isClientSide) {
val tablet = Tablet.Server.get(stack, player)
tablet.machine.stop()
- if (tablet.data.tier > Tier.One) {
- player.openGui(OpenComputers, GuiType.TabletInner.id, world, 0, 0, 0)
+ if (tablet.data.tier > Tier.One) player match {
+ case srvPlr: ServerPlayerEntity => ContainerTypes.openTabletGui(srvPlr, Tablet.get(stack, player))
+ case _ =>
}
}
}
else {
- if (!world.isRemote) {
+ if (!world.isClientSide) {
val computer = Tablet.get(stack, player).machine
computer.start()
computer.lastError match {
- case message if message != null => player.sendMessage(Localization.Analyzer.LastError(message))
+ case message if message != null => player.sendMessage(Localization.Analyzer.LastError(message), Util.NIL_UUID)
case _ =>
}
}
else {
- player.openGui(OpenComputers, GuiType.Tablet.id, world, 0, 0, 0)
+ Tablet.get(stack, player).components.collect {
+ case Some(buffer: api.internal.TextBuffer) => buffer
+ }.headOption match {
+ case Some(buffer: api.internal.TextBuffer) => showGui(buffer)
+ case _ =>
+ }
}
}
}
@@ -222,6 +244,11 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
}
}
+ @OnlyIn(Dist.CLIENT)
+ private def showGui(buffer: api.internal.TextBuffer) {
+ Minecraft.getInstance.pushGuiLayer(new gui.Screen(buffer, true, () => true, () => buffer.isRenderingEnabled))
+ }
+
override def maxCharge(stack: ItemStack): Double = new TabletData(stack).maxEnergy
override def getCharge(stack: ItemStack): Double = new TabletData(stack).energy
@@ -229,24 +256,24 @@ class Tablet(val parent: Delegator) extends traits.Delegate with CustomModel wit
override def setCharge(stack: ItemStack, amount: Double): Unit = {
val data = new TabletData(stack)
data.energy = (0.0 max amount) min maxCharge(stack)
- data.save(stack)
+ data.saveData(stack)
}
}
-class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends ComponentInventory with MachineHost with internal.Tablet {
+class TabletWrapper(var stack: ItemStack, var player: PlayerEntity) extends ComponentInventory with MachineHost with internal.Tablet with INamedContainerProvider {
// Remember our *original* world, so we know which tablets to clear on dimension
// changes of players holding tablets - since the player entity instance may be
// kept the same and components are not required to properly handle world changes.
- val world: World = player.world
+ val world: World = player.level
- lazy val machine: api.machine.Machine = if (world.isRemote) null else Machine.create(this)
+ lazy val machine: api.machine.Machine = if (world.isClientSide) null else Machine.create(this)
val data = new TabletData()
- val tablet: component.Tablet = if (world.isRemote) null else new component.Tablet(this)
+ val tablet: component.Tablet = if (world.isClientSide) null else new component.Tablet(this)
//// Client side only
- private var isInitialized = !world.isRemote
+ private var isInitialized = !world.isClientSide
var timesChanged: Int = 0
@@ -263,48 +290,45 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
def items: Array[ItemStack] = data.items
- override def facing: EnumFacing = RotationHelper.fromYaw(player.rotationYaw)
+ override def facing: Direction = RotationHelper.fromYaw(player.yRot)
- override def toLocal(value: EnumFacing): EnumFacing =
- RotationHelper.toLocal(EnumFacing.NORTH, facing, value)
+ override def toLocal(value: Direction): Direction =
+ RotationHelper.toLocal(Direction.NORTH, facing, value)
- override def toGlobal(value: EnumFacing): EnumFacing =
- RotationHelper.toGlobal(EnumFacing.NORTH, facing, value)
+ override def toGlobal(value: Direction): Direction =
+ RotationHelper.toGlobal(Direction.NORTH, facing, value)
def readFromNBT() {
- if (stack.hasTagCompound) {
- val data = stack.getTagCompound
- load(data)
- if (!world.isRemote) {
- tablet.load(data.getCompoundTag(Settings.namespace + "component"))
- machine.load(data.getCompoundTag(Settings.namespace + "data"))
+ if (stack.hasTag) {
+ val data = stack.getTag
+ loadData(data)
+ if (!world.isClientSide) {
+ tablet.loadData(data.getCompound(Settings.namespace + "component"))
+ machine.loadData(data.getCompound(Settings.namespace + "data"))
}
}
}
def writeToNBT(clearState: Boolean = true) {
- if (!stack.hasTagCompound) {
- stack.setTagCompound(new NBTTagCompound())
- }
- val data = stack.getTagCompound
- if (!world.isRemote) {
- if (!data.hasKey(Settings.namespace + "data")) {
- data.setTag(Settings.namespace + "data", new NBTTagCompound())
+ val data = stack.getOrCreateTag
+ if (!world.isClientSide) {
+ if (!data.contains(Settings.namespace + "data")) {
+ data.put(Settings.namespace + "data", new CompoundNBT())
}
- data.setNewCompoundTag(Settings.namespace + "component", tablet.save)
- data.setNewCompoundTag(Settings.namespace + "data", machine.save)
+ data.setNewCompoundTag(Settings.namespace + "component", tablet.saveData(_))
+ data.setNewCompoundTag(Settings.namespace + "data", machine.saveData(_))
if (clearState) {
// Force tablets into stopped state to avoid errors when trying to
// load deleted machine states.
- data.getCompoundTag(Settings.namespace + "data").removeTag("state")
+ data.getCompound(Settings.namespace + "data").remove("state")
}
}
- save(data)
+ saveData(data)
}
readFromNBT()
- if (!world.isRemote) {
+ if (!world.isClientSide) {
api.Network.joinNewNetwork(machine.node)
val charge = Math.max(0, this.data.energy - tablet.node.globalBuffer)
tablet.node.changeBuffer(charge)
@@ -313,6 +337,13 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
// ----------------------------------------------------------------------- //
+ override def getDisplayName = getName
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Tablet(ContainerTypes.TABLET, id, playerInventory, stack, this, containerSlotType, containerSlotTier)
+
+ // ----------------------------------------------------------------------- //
+
override def onConnect(node: Node) {
if (node == this.node) {
connectComponents()
@@ -350,9 +381,9 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
override def host: TabletWrapper = this
- override def getSizeInventory: Int = items.length
+ override def getContainerSize: Int = items.length
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = slot == getSizeInventory - 1 && (Option(Driver.driverFor(stack, getClass)) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = slot == getContainerSize - 1 && (Option(Driver.driverFor(stack, getClass)) match {
case Some(driver) =>
// Same special cases, similar as in robot, but allow keyboards,
// because clip-on keyboards kinda seem to make sense, I guess.
@@ -362,20 +393,20 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
case _ => false
})
- override def isUsableByPlayer(player: EntityPlayer): Boolean = machine != null && machine.canInteract(player.getName)
+ override def stillValid(player: PlayerEntity): Boolean = machine != null && machine.canInteract(player.getName.getString)
- override def markDirty(): Unit = {
- data.save(stack)
- player.inventory.markDirty()
+ override def setChanged(): Unit = {
+ data.saveData(stack)
+ player.inventory.setChanged()
}
// ----------------------------------------------------------------------- //
- override def xPosition: Double = player.posX
+ override def xPosition: Double = player.getX
- override def yPosition: Double = player.posY + player.getEyeHeight
+ override def yPosition: Double = player.getY + player.getEyeHeight
- override def zPosition: Double = player.posZ
+ override def zPosition: Double = player.getZ
override def markChanged() {}
@@ -395,8 +426,8 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
case _ => Tier.None
}
- override def internalComponents(): Iterable[ItemStack] = (0 until getSizeInventory).collect {
- case slot if !getStackInSlot(slot).isEmpty && isComponentSlot(slot, getStackInSlot(slot)) => getStackInSlot(slot)
+ override def internalComponents(): Iterable[ItemStack] = (0 until getContainerSize).collect {
+ case slot if !getItem(slot).isEmpty && isComponentSlot(slot, getItem(slot)) => getItem(slot)
}
override def componentSlot(address: String): Int = components.indexWhere(_.exists(env => env.node != null && env.node.address == address))
@@ -411,7 +442,7 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
// ----------------------------------------------------------------------- //
- def update(world: World, player: EntityPlayer, slot: Int, selected: Boolean) {
+ def update(world: World, player: PlayerEntity, slot: Int, selected: Boolean) {
this.player = player
if (!isInitialized) {
isInitialized = true
@@ -428,8 +459,8 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
client.PacketSender.sendMachineItemStateRequest(stack)
}
- if (!world.isRemote) {
- if (isCreative && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (!world.isClientSide) {
+ if (isCreative && world.getGameTime % Settings.get.tickFrequency == 0) {
machine.node.asInstanceOf[Connector].changeBuffer(Double.PositiveInfinity)
}
machine.update()
@@ -440,10 +471,10 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
if (lastRunning != machine.isRunning) {
lastRunning = machine.isRunning
- markDirty()
+ setChanged()
player match {
- case mp: EntityPlayerMP => server.PacketSender.sendMachineItemState(mp, stack, machine.isRunning)
+ case mp: ServerPlayerEntity => server.PacketSender.sendMachineItemState(mp, stack, machine.isRunning)
case _ =>
}
@@ -459,53 +490,50 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
// ----------------------------------------------------------------------- //
- override def load(nbt: NBTTagCompound) {
- data.load(nbt)
+ override def loadData(nbt: CompoundNBT) {
+ data.loadData(nbt)
}
- override def save(nbt: NBTTagCompound) {
+ override def saveData(nbt: CompoundNBT) {
saveComponents()
- data.save(nbt)
+ data.saveData(nbt)
}
}
object Tablet {
// This is super-hacky, but since it's only used on the client we get away
// with storing context information for analyzing a block in the singleton.
- var currentlyAnalyzing: Option[(BlockPosition, EnumFacing, Float, Float, Float)] = None
+ var currentlyAnalyzing: Option[(BlockPosition, Direction, Float, Float, Float)] = None
def getId(stack: ItemStack): String = {
-
- if (!stack.hasTagCompound) {
- stack.setTagCompound(new NBTTagCompound())
- }
- if (!stack.getTagCompound.hasKey(Settings.namespace + "tablet")) {
- stack.getTagCompound.setString(Settings.namespace + "tablet", UUID.randomUUID().toString)
+ val data = stack.getOrCreateTag
+ if (!data.contains(Settings.namespace + "tablet")) {
+ data.putString(Settings.namespace + "tablet", UUID.randomUUID().toString)
}
- stack.getTagCompound.getString(Settings.namespace + "tablet")
+ data.getString(Settings.namespace + "tablet")
}
- def get(stack: ItemStack, holder: EntityPlayer): TabletWrapper = {
- if (holder.world.isRemote) Client.get(stack, holder)
+ def get(stack: ItemStack, holder: PlayerEntity): TabletWrapper = {
+ if (holder.level.isClientSide) Client.get(stack, holder)
else Server.get(stack, holder)
}
@SubscribeEvent
def onWorldSave(e: WorldEvent.Save) {
- Server.saveAll(e.getWorld)
+ Server.saveAll(e.getWorld.asInstanceOf[World])
}
@SubscribeEvent
def onWorldUnload(e: WorldEvent.Unload) {
- Client.clear(e.getWorld)
- Server.clear(e.getWorld)
+ Client.clear(e.getWorld.asInstanceOf[World])
+ Server.clear(e.getWorld.asInstanceOf[World])
}
@SubscribeEvent
def onClientTick(e: ClientTickEvent) {
Client.cleanUp()
- FMLCommonHandler.instance.getMinecraftServerInstance match {
- case integrated: IntegratedServer if Minecraft.getMinecraft.isGamePaused =>
+ ServerLifecycleHooks.getCurrentServer match {
+ case integrated: IntegratedServer if Minecraft.getInstance.isPaused =>
// While the game is paused, manually keep all tablets alive, to avoid
// them being cleared from the cache, causing them to stop.
Client.keepAlive()
@@ -531,16 +559,16 @@ object Tablet {
// To allow access in cache entry init.
private var currentStack: ItemStack = _
- private var currentHolder: EntityPlayer = _
+ private var currentHolder: PlayerEntity = _
- def get(stack: ItemStack, holder: EntityPlayer): TabletWrapper = {
+ def get(stack: ItemStack, holder: PlayerEntity): TabletWrapper = {
val id = getId(stack)
cache.synchronized {
currentStack = stack
currentHolder = holder
// if the item is still cached, we can detect if it is dirty (client side only)
- if (holder.world.isRemote) {
+ if (holder.level.isClientSide) {
Client.getWeak(stack) match {
case Some(weak) =>
val timesChanged = holder.inventory.getTimesChanged
@@ -559,7 +587,7 @@ object Tablet {
// Force re-load on world change, in case some components store a
// reference to the world object.
- if (holder.world != wrapper.world) {
+ if (holder.level != wrapper.world) {
wrapper.writeToNBT(clearState = false)
wrapper.autoSave = false
cache.invalidate(id)
@@ -590,7 +618,7 @@ object Tablet {
node.remove()
}
if (tablet.autoSave) tablet.writeToNBT()
- tablet.markDirty()
+ tablet.setChanged()
}
}
@@ -625,8 +653,8 @@ object Tablet {
}
def get(stack: ItemStack): Option[TabletWrapper] = {
- if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "tablet")) {
- val id = stack.getTagCompound.getString(Settings.namespace + "tablet")
+ if (stack.hasTag && stack.getTag.contains(Settings.namespace + "tablet")) {
+ val id = stack.getTag.getString(Settings.namespace + "tablet")
cache.synchronized(Option(cache.getIfPresent(id)))
}
else None
diff --git a/src/main/scala/li/cil/oc/common/item/TabletCase.scala b/src/main/scala/li/cil/oc/common/item/TabletCase.scala
index 7ac5dcd584..62264077a8 100644
--- a/src/main/scala/li/cil/oc/common/item/TabletCase.scala
+++ b/src/main/scala/li/cil/oc/common/item/TabletCase.scala
@@ -1,11 +1,15 @@
package li.cil.oc.common.item
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
-class TabletCase(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class TabletCase(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
override protected def tierFromDriver(stack: ItemStack) = tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
}
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/Terminal.scala b/src/main/scala/li/cil/oc/common/item/Terminal.scala
index 9f3b5410b0..07444bf7b7 100644
--- a/src/main/scala/li/cil/oc/common/item/Terminal.scala
+++ b/src/main/scala/li/cil/oc/common/item/Terminal.scala
@@ -2,65 +2,105 @@ package li.cil.oc.common.item
import java.util
+import com.google.common.base.Strings
import li.cil.oc.Constants
+import li.cil.oc.Localization
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
-import net.minecraft.client.renderer.block.model.ModelBakery
-import net.minecraft.client.renderer.block.model.ModelResourceLocation
+import li.cil.oc.api
+import li.cil.oc.client.gui
+import li.cil.oc.common.component
+import li.cil.oc.common.tileentity.traits.TileEntity
+import li.cil.oc.util.Tooltip
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.model.ModelBakery
+import net.minecraft.client.renderer.model.ModelResourceLocation
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.Hand
import net.minecraft.util.ResourceLocation
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.client.model.ModelLoader
+import net.minecraftforge.common.extensions.IForgeItem
-class Terminal(val parent: Delegator) extends traits.Delegate with CustomModel {
- override def maxStackSize = 1
+class Terminal(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with CustomModel {
+ def hasServer(stack: ItemStack) = stack.hasTag && stack.getTag.contains(Settings.namespace + "server")
- def hasServer(stack: ItemStack) = stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "server")
-
- @SideOnly(Side.CLIENT)
- override def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- super.tooltipLines(stack, world, tooltip, flag)
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
if (hasServer(stack)) {
- val server = stack.getTagCompound.getString(Settings.namespace + "server")
- tooltip.add("§8" + server.substring(0, 13) + "...§7")
+ val server = stack.getTag.getString(Settings.namespace + "server")
+ tooltip.add(new StringTextComponent("§8" + server.substring(0, 13) + "...§7"))
}
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
private def modelLocationFromState(running: Boolean) = {
new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.ItemName.Terminal + (if (running) "_on" else "_off"), "inventory")
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def getModelLocation(stack: ItemStack): ModelResourceLocation = {
modelLocationFromState(hasServer(stack))
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def registerModelLocations(): Unit = {
for (state <- Seq(true, false)) {
- val location = modelLocationFromState(state)
- ModelBakery.registerItemVariants(parent, new ResourceLocation(location.getResourceDomain + ":" + location.getResourcePath))
+ ModelLoader.addSpecialModel(modelLocationFromState(state))
}
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (!player.isSneaking && stack.hasTagCompound) {
- val key = stack.getTagCompound.getString(Settings.namespace + "key")
- val server = stack.getTagCompound.getString(Settings.namespace + "server")
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (!player.isCrouching && stack.hasTag) {
+ val key = stack.getTag.getString(Settings.namespace + "key")
+ val server = stack.getTag.getString(Settings.namespace + "server")
if (key != null && !key.isEmpty && server != null && !server.isEmpty) {
- if (world.isRemote) {
- player.openGui(OpenComputers, GuiType.Terminal.id, world, 0, 0, 0)
+ if (world.isClientSide) {
+ if (stack.hasTag) {
+ val address = stack.getTag.getString(Settings.namespace + "server")
+ val key = stack.getTag.getString(Settings.namespace + "key")
+ if (!Strings.isNullOrEmpty(key) && !Strings.isNullOrEmpty(address)) {
+ component.TerminalServer.loaded.find(address) match {
+ case Some(term) if term != null && term.rack != null => term.rack match {
+ case rack: TileEntity with api.internal.Rack => {
+ def inRange = player.isAlive && !rack.isRemoved && player.distanceToSqr(rack.x + 0.5, rack.y + 0.5, rack.z + 0.5) < term.range * term.range
+ if (inRange) {
+ if (term.sidedKeys.contains(key)) showGui(stack, key, term, () => inRange)
+ else player.displayClientMessage(Localization.Terminal.InvalidKey, true)
+ }
+ else player.displayClientMessage(Localization.Terminal.OutOfRange, true)
+ }
+ case _ => // Eh?
+ }
+ case _ => player.displayClientMessage(Localization.Terminal.OutOfRange, true)
+ }
+ }
+ }
}
- player.swingArm(EnumHand.MAIN_HAND)
+ player.swing(Hand.MAIN_HAND)
}
}
- super.onItemRightClick(stack, world, player)
+ super.use(stack, world, player)
+ }
+
+ @OnlyIn(Dist.CLIENT)
+ private def showGui(stack: ItemStack, key: String, term: component.TerminalServer, inRange: () => Boolean) {
+ Minecraft.getInstance.pushGuiLayer(new gui.Screen(term.buffer, true, () => true, () => {
+ // Check if someone else bound a term to our server.
+ if (stack.getTag.getString(Settings.namespace + "key") != key) Minecraft.getInstance.popGuiLayer
+ // Check whether we're still in range.
+ if (!inRange()) Minecraft.getInstance.popGuiLayer
+ true
+ }))
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/TerminalServer.scala b/src/main/scala/li/cil/oc/common/item/TerminalServer.scala
index 7fd58da8bd..86a4f07ab2 100644
--- a/src/main/scala/li/cil/oc/common/item/TerminalServer.scala
+++ b/src/main/scala/li/cil/oc/common/item/TerminalServer.scala
@@ -1,7 +1,10 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
-class TerminalServer(val parent: Delegator) extends traits.Delegate {
+class TerminalServer(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
override protected def tooltipData = Seq(Settings.get.terminalsPerServer)
}
diff --git a/src/main/scala/li/cil/oc/common/item/TexturePicker.scala b/src/main/scala/li/cil/oc/common/item/TexturePicker.scala
index fefc6e5597..936435d5b3 100644
--- a/src/main/scala/li/cil/oc/common/item/TexturePicker.scala
+++ b/src/main/scala/li/cil/oc/common/item/TexturePicker.scala
@@ -5,18 +5,25 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.block.Block
import net.minecraft.client.Minecraft
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
+import net.minecraft.util.Util
+import net.minecraftforge.client.model.ModelDataManager
+import net.minecraftforge.common.extensions.IForgeItem
-class TexturePicker(val parent: Delegator) extends traits.Delegate {
- override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
- player.getEntityWorld.getBlock(position) match {
+class TexturePicker(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem {
+ override def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ player.level.getBlock(position) match {
case block: Block =>
- if (player.getEntityWorld.isRemote) {
- val model = Minecraft.getMinecraft.getBlockRendererDispatcher.getModelForState(player.getEntityWorld.getBlockState(position.toBlockPos))
- if (model != null && model.getParticleTexture != null && model.getParticleTexture.getIconName != null) {
- player.sendMessage(Localization.Chat.TextureName(model.getParticleTexture.getIconName))
+ if (player.level.isClientSide) {
+ val pos = position.toBlockPos
+ val model = Minecraft.getInstance.getBlockRenderer.getBlockModel(player.level.getBlockState(pos))
+ val particle = if (model != null) model.getParticleTexture(ModelDataManager.getModelData(player.level, pos)) else null
+ if (particle != null && particle.getName != null) {
+ player.sendMessage(Localization.Chat.TextureName(particle.getName.toString), Util.NIL_UUID)
}
}
true
diff --git a/src/main/scala/li/cil/oc/common/item/Transistor.scala b/src/main/scala/li/cil/oc/common/item/Transistor.scala
index eb84cd8a60..5457754df2 100644
--- a/src/main/scala/li/cil/oc/common/item/Transistor.scala
+++ b/src/main/scala/li/cil/oc/common/item/Transistor.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class Transistor(val parent: Delegator) extends traits.Delegate
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class Transistor(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeAngel.scala b/src/main/scala/li/cil/oc/common/item/UpgradeAngel.scala
index ffb4e6da3a..4f65c741d8 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeAngel.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeAngel.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeAngel(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeAngel(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala b/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala
index aac2fb9b38..a5116eb79e 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala
@@ -3,18 +3,22 @@ package li.cil.oc.common.item
import li.cil.oc.Settings
import li.cil.oc.api.driver.item.Chargeable
import li.cil.oc.common.item.data.NodeData
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeBattery(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier with traits.Chargeable {
- override val unlocalizedName: String = super.unlocalizedName + tier
+class UpgradeBattery(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier with traits.Chargeable {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData = Seq(Settings.get.bufferCapacitorUpgrades(tier).toInt)
override def showDurabilityBar(stack: ItemStack) = true
- override def durability(stack: ItemStack): Double = {
+ override def getDurabilityForDisplay(stack: ItemStack): Double = {
val data = new NodeData(stack)
1 - data.buffer.getOrElse(0.0) / Settings.get.bufferCapacitorUpgrades(tier)
}
@@ -31,7 +35,7 @@ class UpgradeBattery(val parent: Delegator, val tier: Int) extends traits.Delega
}
traits.Chargeable.applyCharge(amount, buffer, Settings.get.bufferCapacitorUpgrades(tier), used => if (!simulate) {
data.buffer = Option(buffer + used)
- data.save(stack)
+ data.saveData(stack)
})
}
@@ -42,7 +46,7 @@ class UpgradeBattery(val parent: Delegator, val tier: Int) extends traits.Delega
override def setCharge(stack: ItemStack, amount: Double): Unit = {
val data = new NodeData(stack)
data.buffer = Option((0.0 max amount) min maxCharge(stack))
- data.save(stack)
+ data.saveData(stack)
}
override def canExtract(stack: ItemStack): Boolean = true
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeChunkloader.scala b/src/main/scala/li/cil/oc/common/item/UpgradeChunkloader.scala
index da2da9081c..786deef739 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeChunkloader.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeChunkloader.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeChunkloader(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeChunkloader(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeContainerCard.scala b/src/main/scala/li/cil/oc/common/item/UpgradeContainerCard.scala
index d2edec129a..a6eb7ee47b 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeContainerCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeContainerCard.scala
@@ -1,9 +1,14 @@
package li.cil.oc.common.item
-class UpgradeContainerCard(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
- override protected def tooltipName = Option(super.unlocalizedName)
+class UpgradeContainerCard(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
+
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData = Seq(tier + 1)
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeContainerUpgrade.scala b/src/main/scala/li/cil/oc/common/item/UpgradeContainerUpgrade.scala
index b118d5158b..a4e4267fa4 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeContainerUpgrade.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeContainerUpgrade.scala
@@ -1,9 +1,14 @@
package li.cil.oc.common.item
-class UpgradeContainerUpgrade(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
- override protected def tooltipName = Option(super.unlocalizedName)
+class UpgradeContainerUpgrade(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
+
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData = Seq(tier + 1)
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeCrafting.scala b/src/main/scala/li/cil/oc/common/item/UpgradeCrafting.scala
index e822f1e34c..b9f877faf7 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeCrafting.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeCrafting.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeCrafting(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeCrafting(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeDatabase.scala b/src/main/scala/li/cil/oc/common/item/UpgradeDatabase.scala
index dc0269aa92..20d6e404c0 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeDatabase.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeDatabase.scala
@@ -2,33 +2,43 @@ package li.cil.oc.common.item
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
-import li.cil.oc.util.Rarity
-import net.minecraft.entity.player.EntityPlayer
+import li.cil.oc.common.container.ContainerTypes
+import li.cil.oc.common.inventory.DatabaseInventory
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeDatabase(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class UpgradeDatabase(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData = Seq(Settings.get.databaseEntriesPerTier(tier))
- override def rarity(stack: ItemStack) = Rarity.byTier(tier)
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (!player.isCrouching) {
+ if (!world.isClientSide) player match {
+ case srvPlr: ServerPlayerEntity => ContainerTypes.openDatabaseGui(srvPlr, new DatabaseInventory {
+ override def container = stack
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (!player.isSneaking) {
- player.openGui(OpenComputers, GuiType.Database.id, world, 0, 0, 0)
- player.swingArm(EnumHand.MAIN_HAND)
+ override def stillValid(player: PlayerEntity) = player == srvPlr
+ })
+ case _ =>
+ }
+ player.swing(Hand.MAIN_HAND)
}
- else if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "items")) {
- stack.setTagCompound(null)
- player.swingArm(EnumHand.MAIN_HAND)
+ else {
+ stack.removeTagKey(Settings.namespace + "items")
+ player.swing(Hand.MAIN_HAND)
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeExperience.scala b/src/main/scala/li/cil/oc/common/item/UpgradeExperience.scala
index a105ea97b5..98b6e790d7 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeExperience.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeExperience.scala
@@ -2,24 +2,29 @@ package li.cil.oc.common.item
import java.util
-import li.cil.oc.util.UpgradeExperience
+import li.cil.oc.Localization
+import li.cil.oc.util.Tooltip
+import li.cil.oc.util.{UpgradeExperience => ExperienceUtil}
import net.minecraft.client.util.ITooltipFlag
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.{Side, SideOnly}
-import li.cil.oc.Localization;
+import net.minecraftforge.api.distmarker.{Dist, OnlyIn}
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeExperience(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
-
- @SideOnly(Side.CLIENT) override
- def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag): Unit = {
- if (stack.hasTagCompound) {
+class UpgradeExperience(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
+ if (stack.hasTag) {
val nbt = li.cil.oc.integration.opencomputers.Item.dataTag(stack)
- val experience = UpgradeExperience.getExperience(nbt)
- val level = UpgradeExperience.calculateLevelFromExperience(experience)
- val reportedLevel = UpgradeExperience.calculateExperienceLevel(level, experience)
- tooltip.add(Localization.Tooltip.ExperienceLevel(reportedLevel))
+ val experience = ExperienceUtil.getExperience(nbt)
+ val level = ExperienceUtil.calculateLevelFromExperience(experience)
+ val reportedLevel = ExperienceUtil.calculateExperienceLevel(level, experience)
+ tooltip.add(new StringTextComponent(Localization.Tooltip.ExperienceLevel(reportedLevel)).setStyle(Tooltip.DefaultStyle))
}
- super.tooltipLines(stack, world, tooltip, flag)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeGenerator.scala b/src/main/scala/li/cil/oc/common/item/UpgradeGenerator.scala
index 8dd2f3be4e..79be7fa62b 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeGenerator.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeGenerator.scala
@@ -1,7 +1,10 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeGenerator(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
+class UpgradeGenerator(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
override protected def tooltipData = Seq((Settings.get.generatorEfficiency * 100).toInt)
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeHover.scala b/src/main/scala/li/cil/oc/common/item/UpgradeHover.scala
index 3afd012221..ae56bdc64a 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeHover.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeHover.scala
@@ -1,11 +1,15 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeHover(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class UpgradeHover(props: Properties, val tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
override protected def tooltipData = Seq(Settings.get.upgradeFlightHeight(tier))
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeInventory.scala b/src/main/scala/li/cil/oc/common/item/UpgradeInventory.scala
index 5ac0ef7e8b..32026c51d6 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeInventory.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeInventory.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeInventory(val parent: Delegator) extends traits.Delegate with traits.ItemTier
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeInventory(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeInventoryController.scala b/src/main/scala/li/cil/oc/common/item/UpgradeInventoryController.scala
index 773458084f..c06f369bf4 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeInventoryController.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeInventoryController.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeInventoryController(val parent: Delegator) extends traits.Delegate with traits.ItemTier
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeInventoryController(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeLeash.scala b/src/main/scala/li/cil/oc/common/item/UpgradeLeash.scala
index 42f0633778..97a7cc4e03 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeLeash.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeLeash.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeLeash(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeLeash(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeMF.scala b/src/main/scala/li/cil/oc/common/item/UpgradeMF.scala
index be3d9fdefb..7d451b3cc8 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeMF.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeMF.scala
@@ -2,32 +2,39 @@ package li.cil.oc.common.item
import java.util
-import li.cil.oc.util.BlockPosition
import li.cil.oc.Localization
import li.cil.oc.Settings
-import net.minecraft.entity.player.EntityPlayer
+import li.cil.oc.util.BlockPosition
+import li.cil.oc.util.Tooltip
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
+import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeMF(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
- override def onItemUseFirst(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): EnumActionResult = {
- if (!player.world.isRemote && player.isSneaking) {
- if (!stack.hasTagCompound) {
- stack.setTagCompound(new NBTTagCompound())
- }
- val data = stack.getTagCompound
- data.setIntArray(Settings.namespace + "coord", Array(position.x, position.y, position.z, player.world.provider.getDimension, side.ordinal()))
- return EnumActionResult.SUCCESS
+class UpgradeMF(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ override def onItemUseFirst(stack: ItemStack, player: PlayerEntity, world: World, pos: BlockPos, side: Direction, hitX: Float, hitY: Float, hitZ: Float, hand: Hand): ActionResultType = {
+ if (!player.level.isClientSide && player.isCrouching) {
+ val data = stack.getOrCreateTag
+ data.putString(Settings.namespace + "dimension", world.dimension.location.toString)
+ data.putIntArray(Settings.namespace + "coord", Array(pos.getX, pos.getY, pos.getZ, side.ordinal()))
+ return ActionResultType.sidedSuccess(player.level.isClientSide)
}
- super.onItemUseFirst(stack, player, position, side, hitX, hitY, hitZ)
+ super.onItemUseFirst(stack, player, world, pos, side, hitX, hitY, hitZ, hand)
}
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
- tooltip.add(Localization.Tooltip.MFULinked(stack.getTagCompound match {
- case data: NBTTagCompound => data.hasKey(Settings.namespace + "coord")
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[ITextComponent]) {
+ tooltip.add(new StringTextComponent(Localization.Tooltip.MFULinked(stack.getTag match {
+ case data: CompoundNBT => data.contains(Settings.namespace + "coord")
case _ => false
- }))
+ })).setStyle(Tooltip.DefaultStyle))
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeNavigation.scala b/src/main/scala/li/cil/oc/common/item/UpgradeNavigation.scala
index 0c8ac4870c..d2e847e767 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeNavigation.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeNavigation.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeNavigation(val parent: Delegator) extends traits.Delegate with traits.ItemTier
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeNavigation(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradePiston.scala b/src/main/scala/li/cil/oc/common/item/UpgradePiston.scala
index 83f6f7cf3d..e8dff7e8fa 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradePiston.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradePiston.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradePiston(val parent: Delegator) extends traits.Delegate with traits.ItemTier
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradePiston(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeSign.scala b/src/main/scala/li/cil/oc/common/item/UpgradeSign.scala
index 56fa772c56..7ca4cb9635 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeSign.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeSign.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeSign(val parent: Delegator) extends traits.Delegate with traits.ItemTier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeSign(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeSolarGenerator.scala b/src/main/scala/li/cil/oc/common/item/UpgradeSolarGenerator.scala
index f0487450f0..f04fb24726 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeSolarGenerator.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeSolarGenerator.scala
@@ -1,7 +1,10 @@
package li.cil.oc.common.item
import li.cil.oc.Settings
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeSolarGenerator(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
+class UpgradeSolarGenerator(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
override protected def tooltipData = Seq((Settings.get.solarGeneratorEfficiency * 100).toInt)
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeStickyPiston.scala b/src/main/scala/li/cil/oc/common/item/UpgradeStickyPiston.scala
index befd47bc16..fbfaeb5cec 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeStickyPiston.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeStickyPiston.scala
@@ -1,6 +1,10 @@
package li.cil.oc.common.item
-class UpgradeStickyPiston(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
- override protected def tooltipName: Option[String] = Option(super.unlocalizedName)
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeStickyPiston(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ override protected def tooltipName: Option[String] = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeTank.scala b/src/main/scala/li/cil/oc/common/item/UpgradeTank.scala
index 00506d0945..7945cbd4b5 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeTank.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeTank.scala
@@ -3,24 +3,29 @@ package li.cil.oc.common.item
import java.util
import li.cil.oc.Settings
+import li.cil.oc.util.Tooltip
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
import net.minecraftforge.fluids.FluidStack
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.common.extensions.IForgeItem
-class UpgradeTank(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
- @SideOnly(Side.CLIENT) override
- def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag): Unit = {
- if (stack.hasTagCompound) {
- FluidStack.loadFluidStackFromNBT(stack.getTagCompound.getCompoundTag(Settings.namespace + "data")) match {
+class UpgradeTank(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
+ if (stack.hasTag) {
+ FluidStack.loadFluidStackFromNBT(stack.getTag.getCompound(Settings.namespace + "data")) match {
case stack: FluidStack =>
- tooltip.add(stack.getFluid.getLocalizedName(stack) + ": " + stack.amount + "/16000")
+ tooltip.add(new StringTextComponent(stack.getFluid.getAttributes.getDisplayName(stack).getString + ": " + stack.getAmount + "/16000").setStyle(Tooltip.DefaultStyle))
case _ =>
}
}
- super.tooltipLines(stack, world, tooltip, flag)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeTankController.scala b/src/main/scala/li/cil/oc/common/item/UpgradeTankController.scala
index ff0d347341..7968768509 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeTankController.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeTankController.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeTankController(val parent: Delegator) extends traits.Delegate with traits.ItemTier
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeTankController(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeTractorBeam.scala b/src/main/scala/li/cil/oc/common/item/UpgradeTractorBeam.scala
index e9dba02c85..eec70e8dfe 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeTractorBeam.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeTractorBeam.scala
@@ -1,3 +1,7 @@
package li.cil.oc.common.item
-class UpgradeTractorBeam(val parent: Delegator) extends traits.Delegate with traits.ItemTier
\ No newline at end of file
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeTractorBeam(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala b/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala
index 30806741d2..7762236a61 100644
--- a/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala
+++ b/src/main/scala/li/cil/oc/common/item/UpgradeTrading.scala
@@ -1,5 +1,9 @@
package li.cil.oc.common.item
-class UpgradeTrading(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
- override protected def tooltipName: Option[String] = Option(super.unlocalizedName)
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
+
+class UpgradeTrading(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ override protected def tooltipName: Option[String] = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/WirelessNetworkCard.scala b/src/main/scala/li/cil/oc/common/item/WirelessNetworkCard.scala
index 6356d87711..acbed73313 100644
--- a/src/main/scala/li/cil/oc/common/item/WirelessNetworkCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/WirelessNetworkCard.scala
@@ -1,9 +1,12 @@
package li.cil.oc.common.item
-import li.cil.oc.common.Tier
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
+import net.minecraftforge.common.extensions.IForgeItem
-class WirelessNetworkCard(val parent: Delegator, var tier: Int) extends traits.Delegate with traits.ItemTier {
- override val unlocalizedName = super.unlocalizedName + tier
+class WirelessNetworkCard(props: Properties, var tier: Int) extends Item(props) with IForgeItem with traits.SimpleItem with traits.ItemTier {
+ @Deprecated
+ override def getDescriptionId = super.getDescriptionId + tier
- override protected def tooltipName = Option(super.unlocalizedName)
+ override protected def tooltipName = Option(unlocalizedName)
}
diff --git a/src/main/scala/li/cil/oc/common/item/Wrench.scala b/src/main/scala/li/cil/oc/common/item/Wrench.scala
index d2741a32e8..9820d28a50 100644
--- a/src/main/scala/li/cil/oc/common/item/Wrench.scala
+++ b/src/main/scala/li/cil/oc/common/item/Wrench.scala
@@ -1,45 +1,48 @@
package li.cil.oc.common.item
import li.cil.oc.api
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.integration.Mods
+import li.cil.oc.common.block.SimpleBlock
import net.minecraft.block.Block
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.init.Blocks
+import net.minecraft.block.Blocks
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
+import net.minecraft.util.Rotation
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.world.IWorldReader
import net.minecraft.world.World
+import net.minecraftforge.common.extensions.IForgeItem
-@Injectable.InterfaceList(Array(
- new Injectable.Interface(value = "ic2.api.item.IBoxable", modid = Mods.IDs.IndustrialCraft2)
-))
-class Wrench extends traits.SimpleItem with api.internal.Wrench {
- setHarvestLevel("wrench", 1)
- setMaxStackSize(1)
+class Wrench(props: Properties) extends Item(props) with IForgeItem with traits.SimpleItem with api.internal.Wrench {
+ override def doesSneakBypassUse(stack: ItemStack, world: IWorldReader, pos: BlockPos, player: PlayerEntity): Boolean = true
- override def doesSneakBypassUse(stack: ItemStack, world: IBlockAccess, pos: BlockPos, player: EntityPlayer): Boolean = true
-
- override def onItemUseFirst(player: EntityPlayer, world: World, pos: BlockPos, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, hand: EnumHand): EnumActionResult = {
- if (world.isBlockLoaded(pos) && world.isBlockModifiable(player, pos)) world.getBlockState(pos).getBlock match {
- case block: Block if block.rotateBlock(world, pos, side) =>
- block.neighborChanged(world.getBlockState(pos), world, pos, Blocks.AIR, pos)
- player.swingArm(hand)
- if (!world.isRemote) EnumActionResult.SUCCESS else EnumActionResult.PASS
- case _ =>
- super.onItemUseFirst(player, world, pos, side, hitX, hitY, hitZ, hand)
+ override def onItemUseFirst(stack: ItemStack, player: PlayerEntity, world: World, pos: BlockPos, side: Direction, hitX: Float, hitY: Float, hitZ: Float, hand: Hand): ActionResultType = {
+ if (world.isLoaded(pos) && world.mayInteract(player, pos)) {
+ val state = world.getBlockState(pos)
+ state.getBlock match {
+ case block: SimpleBlock if block.rotateBlock(world, pos, side) =>
+ state.neighborChanged(world, pos, Blocks.AIR, pos, false)
+ player.swing(hand)
+ if (!world.isClientSide) ActionResultType.sidedSuccess(world.isClientSide) else ActionResultType.PASS
+ case _ =>
+ val updated = state.rotate(world, pos, Rotation.CLOCKWISE_90)
+ if (updated != state) {
+ world.setBlock(pos, updated, 3)
+ player.swing(hand)
+ if (!world.isClientSide) ActionResultType.sidedSuccess(world.isClientSide) else ActionResultType.PASS
+ }
+ else super.onItemUseFirst(stack, player, world, pos, side, hitX, hitY, hitZ, hand)
+ }
}
- else super.onItemUseFirst(player, world, pos, side, hitX, hitY, hitZ, hand)
+ else super.onItemUseFirst(stack, player, world, pos, side, hitX, hitY, hitZ, hand)
}
- def useWrenchOnBlock(player: EntityPlayer, world: World, pos: BlockPos, simulate: Boolean): Boolean = {
- if (!simulate) player.swingArm(EnumHand.MAIN_HAND)
+ def useWrenchOnBlock(player: PlayerEntity, world: World, pos: BlockPos, simulate: Boolean): Boolean = {
+ if (!simulate) player.swing(Hand.MAIN_HAND)
true
}
-
- // IndustrialCraft 2
- def canBeStoredInToolbox(stack: ItemStack): Boolean = true
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala b/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala
index b27ef3925a..6673fe12b6 100644
--- a/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala
@@ -1,35 +1,35 @@
package li.cil.oc.common.item.data
-import li.cil.oc.server.component.DebugCard.AccessContext
import li.cil.oc.Constants
import li.cil.oc.Settings
+import li.cil.oc.server.component.DebugCard.AccessContext
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
class DebugCardData extends ItemData(Constants.ItemName.DebugCard) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var access: Option[AccessContext] = None
private final val DataTag = Settings.namespace + "data"
- override def load(nbt: NBTTagCompound): Unit = {
- access = AccessContext.load(dataTag(nbt))
+ override def loadData(nbt: CompoundNBT): Unit = {
+ access = AccessContext.loadData(dataTag(nbt))
}
- override def save(nbt: NBTTagCompound): Unit = {
+ override def saveData(nbt: CompoundNBT): Unit = {
val tag = dataTag(nbt)
AccessContext.remove(tag)
- access.foreach(_.save(tag))
+ access.foreach(_.saveData(tag))
}
- private def dataTag(nbt: NBTTagCompound) = {
- if (!nbt.hasKey(DataTag)) {
- nbt.setTag(DataTag, new NBTTagCompound())
+ private def dataTag(nbt: CompoundNBT) = {
+ if (!nbt.contains(DataTag)) {
+ nbt.put(DataTag, new CompoundNBT())
}
- nbt.getCompoundTag(DataTag)
+ nbt.getCompound(DataTag)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/DriveData.scala b/src/main/scala/li/cil/oc/common/item/data/DriveData.scala
index 0e4b81fffa..52190f9f20 100644
--- a/src/main/scala/li/cil/oc/common/item/data/DriveData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/DriveData.scala
@@ -2,14 +2,14 @@ package li.cil.oc.common.item.data
import li.cil.oc.Settings
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import li.cil.oc.server.fs
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
class DriveData extends ItemData(null) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var isUnmanaged = false
@@ -22,29 +22,29 @@ class DriveData extends ItemData(null) {
private final val UnmanagedTag = Settings.namespace + "unmanaged"
private val LockTag = Settings.namespace + "lock"
- override def load(nbt: NBTTagCompound) {
+ override def loadData(nbt: CompoundNBT) {
isUnmanaged = nbt.getBoolean(UnmanagedTag)
- lockInfo = if (nbt.hasKey(LockTag)) {
+ lockInfo = if (nbt.contains(LockTag)) {
nbt.getString(LockTag)
} else ""
}
- override def save(nbt: NBTTagCompound) {
- nbt.setBoolean(UnmanagedTag, isUnmanaged)
- nbt.setString(LockTag, lockInfo)
+ override def saveData(nbt: CompoundNBT) {
+ nbt.putBoolean(UnmanagedTag, isUnmanaged)
+ nbt.putString(LockTag, lockInfo)
}
}
object DriveData {
- def lock(stack: ItemStack, player: EntityPlayer): Unit = {
- val key = player.getName
+ def lock(stack: ItemStack, player: PlayerEntity): Unit = {
+ val key = player.getName.getString
val data = new DriveData(stack)
if (!data.isLocked) {
data.lockInfo = key match {
case name: String if name != null && name.nonEmpty => name
case _ => "notch" // meaning: "unknown"
}
- data.save(stack)
+ data.saveData(stack)
}
}
@@ -55,6 +55,6 @@ object DriveData {
data.lockInfo = ""
}
data.isUnmanaged = unmanaged
- data.save(stack)
+ data.saveData(stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/DroneData.scala b/src/main/scala/li/cil/oc/common/item/data/DroneData.scala
index ac7e2f6fc0..481a998c28 100644
--- a/src/main/scala/li/cil/oc/common/item/data/DroneData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/DroneData.scala
@@ -4,26 +4,26 @@ import com.google.common.base.Strings
import li.cil.oc.Constants
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
class DroneData extends MicrocontrollerData(Constants.ItemName.Drone) {
def this(stack: ItemStack) = {
this()
- load(stack)
+ loadData(stack)
}
var name = ""
- override def load(nbt: NBTTagCompound): Unit = {
- super.load(nbt)
+ override def loadData(nbt: CompoundNBT): Unit = {
+ super.loadData(nbt)
name = ItemUtils.getDisplayName(nbt).getOrElse("")
if (Strings.isNullOrEmpty(name)) {
name = RobotData.randomName
}
}
- override def save(nbt: NBTTagCompound): Unit = {
- super.save(nbt)
+ override def saveData(nbt: CompoundNBT): Unit = {
+ super.saveData(nbt)
if (!Strings.isNullOrEmpty(name)) {
ItemUtils.setDisplayName(nbt, name)
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/HoverBootsData.scala b/src/main/scala/li/cil/oc/common/item/data/HoverBootsData.scala
index b092b8e8aa..9b0b70a0ba 100644
--- a/src/main/scala/li/cil/oc/common/item/data/HoverBootsData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/HoverBootsData.scala
@@ -3,23 +3,23 @@ package li.cil.oc.common.item.data
import li.cil.oc.Constants
import li.cil.oc.Settings
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
class HoverBootsData extends ItemData(Constants.ItemName.HoverBoots) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var charge = 0.0
private final val ChargeTag = Settings.namespace + "charge"
- override def load(nbt: NBTTagCompound) {
+ override def loadData(nbt: CompoundNBT) {
charge = nbt.getDouble(ChargeTag)
}
- override def save(nbt: NBTTagCompound) {
- nbt.setDouble(ChargeTag, charge)
+ override def saveData(nbt: CompoundNBT) {
+ nbt.putDouble(ChargeTag, charge)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/ItemData.scala b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala
index 4fa2a58f56..82e7d5ef73 100644
--- a/src/main/scala/li/cil/oc/common/item/data/ItemData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala
@@ -3,29 +3,26 @@ package li.cil.oc.common.item.data
import li.cil.oc.api
import li.cil.oc.api.Persistable
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
abstract class ItemData(val itemName: String) extends Persistable {
- def load(stack: ItemStack) {
- if (stack.hasTagCompound) {
+ def loadData(stack: ItemStack) {
+ if (stack.hasTag) {
// Because ItemStack's load function doesn't copy the compound tag,
// but keeps it as is, leading to oh so fun bugs!
- load(stack.getTagCompound.copy().asInstanceOf[NBTTagCompound])
+ loadData(stack.getTag.copy().asInstanceOf[CompoundNBT])
}
}
- def save(stack: ItemStack) {
- if (!stack.hasTagCompound) {
- stack.setTagCompound(new NBTTagCompound())
- }
- save(stack.getTagCompound)
+ def saveData(stack: ItemStack) {
+ saveData(stack.getOrCreateTag)
}
def createItemStack() = {
if (itemName == null) ItemStack.EMPTY
else {
val stack = api.Items.get(itemName).createItemStack(1)
- save(stack)
+ saveData(stack)
stack
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala
index 9d1f470365..33ec629e93 100644
--- a/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala
@@ -6,13 +6,13 @@ import li.cil.oc.api
import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraftforge.common.util.Constants.NBT
class MicrocontrollerData(itemName: String = Constants.BlockName.Microcontroller) extends ItemData(itemName) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var tier = Tier.One
@@ -25,11 +25,11 @@ class MicrocontrollerData(itemName: String = Constants.BlockName.Microcontroller
private final val ComponentsTag = Settings.namespace + "components"
private final val StoredEnergyTag = Settings.namespace + "storedEnergy"
- override def load(nbt: NBTTagCompound) {
+ override def loadData(nbt: CompoundNBT) {
tier = nbt.getByte(TierTag)
- components = nbt.getTagList(ComponentsTag, NBT.TAG_COMPOUND).
- toArray[NBTTagCompound].map(new ItemStack(_)).filter(!_.isEmpty)
- storedEnergy = nbt.getInteger(StoredEnergyTag)
+ components = nbt.getList(ComponentsTag, NBT.TAG_COMPOUND).
+ toTagArray[CompoundNBT].map(ItemStack.of(_)).filter(!_.isEmpty)
+ storedEnergy = nbt.getInt(StoredEnergyTag)
// Reserve slot for EEPROM if necessary, avoids having to resize the
// components array in the MCU tile entity, which isn't possible currently.
@@ -38,16 +38,16 @@ class MicrocontrollerData(itemName: String = Constants.BlockName.Microcontroller
}
}
- override def save(nbt: NBTTagCompound) {
- nbt.setByte(TierTag, tier.toByte)
+ override def saveData(nbt: CompoundNBT) {
+ nbt.putByte(TierTag, tier.toByte)
nbt.setNewTagList(ComponentsTag, components.filter(!_.isEmpty).toIterable)
- nbt.setInteger(StoredEnergyTag, storedEnergy)
+ nbt.putInt(StoredEnergyTag, storedEnergy)
}
def copyItemStack(): ItemStack = {
val stack = createItemStack()
val newInfo = new MicrocontrollerData(stack)
- newInfo.save(stack)
+ newInfo.saveData(stack)
stack
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/NanomachineData.scala b/src/main/scala/li/cil/oc/common/item/data/NanomachineData.scala
index 949786d0db..e17463505d 100644
--- a/src/main/scala/li/cil/oc/common/item/data/NanomachineData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/NanomachineData.scala
@@ -4,40 +4,40 @@ import li.cil.oc.common.nanomachines.ControllerImpl
import li.cil.oc.Constants
import li.cil.oc.Settings
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
class NanomachineData extends ItemData(Constants.ItemName.Nanomachines) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
def this(controller: ControllerImpl) {
this()
uuid = controller.uuid
- val nbt = new NBTTagCompound()
- controller.configuration.save(nbt, forItem = true)
+ val nbt = new CompoundNBT()
+ controller.configuration.saveData(nbt, forItem = true)
configuration = Option(nbt)
}
var uuid = ""
- var configuration: Option[NBTTagCompound] = None
+ var configuration: Option[CompoundNBT] = None
private final val UUIDTag = Settings.namespace + "uuid"
private final val ConfigurationTag = Settings.namespace + "configuration"
- override def load(nbt: NBTTagCompound): Unit = {
+ override def loadData(nbt: CompoundNBT): Unit = {
uuid = nbt.getString(UUIDTag)
- if (nbt.hasKey(ConfigurationTag)) {
- configuration = Option(nbt.getCompoundTag(ConfigurationTag))
+ if (nbt.contains(ConfigurationTag)) {
+ configuration = Option(nbt.getCompound(ConfigurationTag))
}
else {
configuration = None
}
}
- override def save(nbt: NBTTagCompound): Unit = {
- nbt.setString(UUIDTag, uuid)
- configuration.foreach(nbt.setTag(ConfigurationTag, _))
+ override def saveData(nbt: CompoundNBT): Unit = {
+ nbt.putString(UUIDTag, uuid)
+ configuration.foreach(nbt.put(ConfigurationTag, _))
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala b/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala
index 2d2cd36245..be8c95af20 100644
--- a/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala
@@ -3,20 +3,20 @@ package li.cil.oc.common.item.data
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.item.ItemMap
+import net.minecraft.item.FilledMapItem
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.world.World
class NavigationUpgradeData extends ItemData(Constants.ItemName.NavigationUpgrade) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
- var map = new ItemStack(net.minecraft.init.Items.FILLED_MAP)
+ var map = new ItemStack(net.minecraft.item.Items.FILLED_MAP)
- def mapData(world: World) = try map.getItem.asInstanceOf[ItemMap].getMapData(map, world) catch {
+ def mapData(world: World) = try FilledMapItem.getSavedData(map, world) catch {
case _: Throwable => throw new Exception("invalid map")
}
@@ -28,28 +28,25 @@ class NavigationUpgradeData extends ItemData(Constants.ItemName.NavigationUpgrad
private final val DataTag = Settings.namespace + "data"
private final val MapTag = Settings.namespace + "map"
- override def load(stack: ItemStack) {
- if (stack.hasTagCompound) {
- load(stack.getTagCompound.getCompoundTag(DataTag))
+ override def loadData(stack: ItemStack) {
+ if (stack.hasTag) {
+ loadData(stack.getTag.getCompound(DataTag))
}
}
- override def save(stack: ItemStack) {
- if (!stack.hasTagCompound) {
- stack.setTagCompound(new NBTTagCompound())
- }
- save(stack.getCompoundTag(DataTag))
+ override def saveData(stack: ItemStack) {
+ saveData(stack.getOrCreateTagElement(DataTag))
}
- override def load(nbt: NBTTagCompound) {
- if (nbt.hasKey(MapTag)) {
- map = new ItemStack(nbt.getCompoundTag(MapTag))
+ override def loadData(nbt: CompoundNBT) {
+ if (nbt.contains(MapTag)) {
+ map = ItemStack.of(nbt.getCompound(MapTag))
}
}
- override def save(nbt: NBTTagCompound) {
+ override def saveData(nbt: CompoundNBT) {
if (map != null) {
- nbt.setNewCompoundTag(MapTag, map.writeToNBT)
+ nbt.setNewCompoundTag(MapTag, map.save)
}
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/NodeData.scala b/src/main/scala/li/cil/oc/common/item/data/NodeData.scala
index 472eeba24c..ca7a44d3ad 100644
--- a/src/main/scala/li/cil/oc/common/item/data/NodeData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/NodeData.scala
@@ -3,13 +3,13 @@ package li.cil.oc.common.item.data
import li.cil.oc.Settings
import li.cil.oc.api.network.Visibility
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
// Generic one for items that are used as components; gets the items node info.
class NodeData extends ItemData(null) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var address: Option[String] = None
@@ -18,31 +18,31 @@ class NodeData extends ItemData(null) {
private final val DataTag = Settings.namespace + "data"
- override def load(nbt: NBTTagCompound): Unit = {
- val nodeNbt = nbt.getCompoundTag(DataTag).getCompoundTag(NodeData.NodeTag)
- if (nodeNbt.hasKey(NodeData.AddressTag)) {
+ override def loadData(nbt: CompoundNBT): Unit = {
+ val nodeNbt = nbt.getCompound(DataTag).getCompound(NodeData.NodeTag)
+ if (nodeNbt.contains(NodeData.AddressTag)) {
address = Option(nodeNbt.getString(NodeData.AddressTag))
}
- if (nodeNbt.hasKey(NodeData.BufferTag)) {
+ if (nodeNbt.contains(NodeData.BufferTag)) {
buffer = Option(nodeNbt.getDouble(NodeData.BufferTag))
}
- if (nodeNbt.hasKey(NodeData.VisibilityTag)) {
- visibility = Option(Visibility.values()(nodeNbt.getInteger(NodeData.VisibilityTag)))
+ if (nodeNbt.contains(NodeData.VisibilityTag)) {
+ visibility = Option(Visibility.values()(nodeNbt.getInt(NodeData.VisibilityTag)))
}
}
- override def save(nbt: NBTTagCompound): Unit = {
- if (!nbt.hasKey(DataTag)) {
- nbt.setTag(DataTag, new NBTTagCompound())
+ override def saveData(nbt: CompoundNBT): Unit = {
+ if (!nbt.contains(DataTag)) {
+ nbt.put(DataTag, new CompoundNBT())
}
- val dataNbt = nbt.getCompoundTag(DataTag)
- if (!dataNbt.hasKey(NodeData.NodeTag)) {
- dataNbt.setTag(NodeData.NodeTag, new NBTTagCompound())
+ val dataNbt = nbt.getCompound(DataTag)
+ if (!dataNbt.contains(NodeData.NodeTag)) {
+ dataNbt.put(NodeData.NodeTag, new CompoundNBT())
}
- val nodeNbt = dataNbt.getCompoundTag(NodeData.NodeTag)
- address.foreach(nodeNbt.setString(NodeData.AddressTag, _))
- buffer.foreach(nodeNbt.setDouble(NodeData.BufferTag, _))
- visibility.map(_.ordinal()).foreach(nodeNbt.setInteger(NodeData.VisibilityTag, _))
+ val nodeNbt = dataNbt.getCompound(NodeData.NodeTag)
+ address.foreach(nodeNbt.putString(NodeData.AddressTag, _))
+ buffer.foreach(nodeNbt.putDouble(NodeData.BufferTag, _))
+ visibility.map(_.ordinal()).foreach(nodeNbt.putInt(NodeData.VisibilityTag, _))
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala
index 3f1ac731ea..9644d0edd6 100644
--- a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala
@@ -9,7 +9,7 @@ import li.cil.oc.common.IMC
import li.cil.oc.util.ExtendedAABB._
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.util.math.AxisAlignedBB
import net.minecraftforge.common.util.Constants.NBT
@@ -18,7 +18,7 @@ import scala.collection.mutable
class PrintData extends ItemData(Constants.BlockName.Print) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var label: Option[String] = None
@@ -72,17 +72,17 @@ class PrintData extends ItemData(Constants.BlockName.Print) {
private final val NoclipOffTag = "noclipOff"
private final val NoclipOnTag = "noclipOn"
- override def load(nbt: NBTTagCompound): Unit = {
- if (nbt.hasKey(LabelTag)) label = Option(nbt.getString(LabelTag)) else label = None
- if (nbt.hasKey(TooltipTag)) tooltip = Option(nbt.getString(TooltipTag)) else tooltip = None
+ override def loadData(nbt: CompoundNBT): Unit = {
+ if (nbt.contains(LabelTag)) label = Option(nbt.getString(LabelTag)) else label = None
+ if (nbt.contains(TooltipTag)) tooltip = Option(nbt.getString(TooltipTag)) else tooltip = None
isButtonMode = nbt.getBoolean(IsButtonModeTag)
- redstoneLevel = nbt.getInteger(RedstoneLevelTag) max 0 min 15
+ redstoneLevel = nbt.getInt(RedstoneLevelTag) max 0 min 15
if (nbt.getBoolean(RedstoneLevelTagCompat)) redstoneLevel = 15
pressurePlate = nbt.getBoolean(PressurePlateTag)
stateOff.clear()
- stateOff ++= nbt.getTagList(StateOffTag, NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
+ stateOff ++= nbt.getList(StateOffTag, NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
stateOn.clear()
- stateOn ++= nbt.getTagList(StateOnTag, NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
+ stateOn ++= nbt.getList(StateOnTag, NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
isBeaconBase = nbt.getBoolean(IsBeaconBaseTag)
lightLevel = (nbt.getByte(LightLevelTag) & 0xFF) max 0 min 15
noclipOff = nbt.getBoolean(NoclipOffTag)
@@ -91,18 +91,18 @@ class PrintData extends ItemData(Constants.BlockName.Print) {
opacityDirty = true
}
- override def save(nbt: NBTTagCompound): Unit = {
- label.foreach(nbt.setString(LabelTag, _))
- tooltip.foreach(nbt.setString(TooltipTag, _))
- nbt.setBoolean(IsButtonModeTag, isButtonMode)
- nbt.setInteger(RedstoneLevelTag, redstoneLevel)
- nbt.setBoolean(PressurePlateTag, pressurePlate)
+ override def saveData(nbt: CompoundNBT): Unit = {
+ label.foreach(nbt.putString(LabelTag, _))
+ tooltip.foreach(nbt.putString(TooltipTag, _))
+ nbt.putBoolean(IsButtonModeTag, isButtonMode)
+ nbt.putInt(RedstoneLevelTag, redstoneLevel)
+ nbt.putBoolean(PressurePlateTag, pressurePlate)
nbt.setNewTagList(StateOffTag, stateOff.map(PrintData.shapeToNBT))
nbt.setNewTagList(StateOnTag, stateOn.map(PrintData.shapeToNBT))
- nbt.setBoolean(IsBeaconBaseTag, isBeaconBase)
- nbt.setByte(LightLevelTag, lightLevel.toByte)
- nbt.setBoolean(NoclipOffTag, noclipOff)
- nbt.setBoolean(NoclipOnTag, noclipOn)
+ nbt.putBoolean(IsBeaconBaseTag, isBeaconBase)
+ nbt.putByte(LightLevelTag, lightLevel.toByte)
+ nbt.putBoolean(NoclipOffTag, noclipOff)
+ nbt.putBoolean(NoclipOnTag, noclipOn)
}
}
@@ -179,9 +179,9 @@ object PrintData {
0
}
- def nbtToShape(nbt: NBTTagCompound): Shape = {
+ def nbtToShape(nbt: CompoundNBT): Shape = {
val aabb =
- if (nbt.hasKey("minX")) {
+ if (nbt.contains("minX")) {
// Compatibility with shapes created with earlier dev-builds.
val minX = nbt.getByte("minX") / 16f
val minY = nbt.getByte("minY") / 16f
@@ -202,13 +202,13 @@ object PrintData {
new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ)
}
val texture = nbt.getString("texture")
- val tint = if (nbt.hasKey("tint")) Option(nbt.getInteger("tint")) else None
+ val tint = if (nbt.contains("tint")) Option(nbt.getInt("tint")) else None
new Shape(aabb, texture, tint)
}
- def shapeToNBT(shape: Shape): NBTTagCompound = {
- val nbt = new NBTTagCompound()
- nbt.setByteArray("bounds", Array(
+ def shapeToNBT(shape: Shape): CompoundNBT = {
+ val nbt = new CompoundNBT()
+ nbt.putByteArray("bounds", Array(
(shape.bounds.minX * 16).round.toByte,
(shape.bounds.minY * 16).round.toByte,
(shape.bounds.minZ * 16).round.toByte,
@@ -216,8 +216,8 @@ object PrintData {
(shape.bounds.maxY * 16).round.toByte,
(shape.bounds.maxZ * 16).round.toByte
))
- nbt.setString("texture", shape.texture)
- shape.tint.foreach(nbt.setInteger("tint", _))
+ nbt.putString("texture", shape.texture)
+ shape.tint.foreach(nbt.putInt("tint", _))
nbt
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/RaidData.scala b/src/main/scala/li/cil/oc/common/item/data/RaidData.scala
index 1b6b045d75..19f5191579 100644
--- a/src/main/scala/li/cil/oc/common/item/data/RaidData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/RaidData.scala
@@ -4,18 +4,18 @@ import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraftforge.common.util.Constants.NBT
class RaidData extends ItemData(Constants.BlockName.Raid) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var disks = Array.empty[ItemStack]
- var filesystem = new NBTTagCompound()
+ var filesystem = new CompoundNBT()
var label: Option[String] = None
@@ -23,18 +23,18 @@ class RaidData extends ItemData(Constants.BlockName.Raid) {
private final val FileSystemTag = Settings.namespace + "filesystem"
private final val LabelTag = Settings.namespace + "label"
- override def load(nbt: NBTTagCompound): Unit = {
- disks = nbt.getTagList(DisksTag, NBT.TAG_COMPOUND).
- toArray[NBTTagCompound].map(new ItemStack(_))
- filesystem = nbt.getCompoundTag(FileSystemTag)
- if (nbt.hasKey(LabelTag)) {
+ override def loadData(nbt: CompoundNBT): Unit = {
+ disks = nbt.getList(DisksTag, NBT.TAG_COMPOUND).
+ toTagArray[CompoundNBT].map(ItemStack.of(_))
+ filesystem = nbt.getCompound(FileSystemTag)
+ if (nbt.contains(LabelTag)) {
label = Option(nbt.getString(LabelTag))
}
}
- override def save(nbt: NBTTagCompound): Unit = {
+ override def saveData(nbt: CompoundNBT): Unit = {
nbt.setNewTagList(DisksTag, disks.toIterable)
- nbt.setTag(FileSystemTag, filesystem)
- label.foreach(nbt.setString(LabelTag, _))
+ nbt.put(FileSystemTag, filesystem)
+ label.foreach(nbt.putString(LabelTag, _))
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/RobotData.scala b/src/main/scala/li/cil/oc/common/item/data/RobotData.scala
index 3cafcc9452..4e339295e7 100644
--- a/src/main/scala/li/cil/oc/common/item/data/RobotData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/RobotData.scala
@@ -10,7 +10,7 @@ import li.cil.oc.integration.opencomputers.DriverScreen
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraftforge.common.util.Constants.NBT
import scala.io.Source
@@ -33,7 +33,7 @@ object RobotData {
class RobotData extends ItemData(Constants.BlockName.Robot) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var name = ""
@@ -59,33 +59,33 @@ class RobotData extends ItemData(Constants.BlockName.Robot) {
private final val ContainersTag = Settings.namespace + "containers"
private final val LightColorTag = Settings.namespace + "lightColor"
- override def load(nbt: NBTTagCompound) {
+ override def loadData(nbt: CompoundNBT) {
name = ItemUtils.getDisplayName(nbt).getOrElse("")
if (Strings.isNullOrEmpty(name)) {
name = RobotData.randomName
}
- totalEnergy = nbt.getInteger(StoredEnergyTag)
- robotEnergy = nbt.getInteger(RobotEnergyTag)
- tier = nbt.getInteger(TierTag)
- components = nbt.getTagList(ComponentsTag, NBT.TAG_COMPOUND).
- toArray[NBTTagCompound].map(new ItemStack(_))
- containers = nbt.getTagList(ContainersTag, NBT.TAG_COMPOUND).
- toArray[NBTTagCompound].map(new ItemStack(_))
- if (nbt.hasKey(LightColorTag)) {
- lightColor = nbt.getInteger(LightColorTag)
+ totalEnergy = nbt.getInt(StoredEnergyTag)
+ robotEnergy = nbt.getInt(RobotEnergyTag)
+ tier = nbt.getInt(TierTag)
+ components = nbt.getList(ComponentsTag, NBT.TAG_COMPOUND).
+ toTagArray[CompoundNBT].map(ItemStack.of(_))
+ containers = nbt.getList(ContainersTag, NBT.TAG_COMPOUND).
+ toTagArray[CompoundNBT].map(ItemStack.of(_))
+ if (nbt.contains(LightColorTag)) {
+ lightColor = nbt.getInt(LightColorTag)
}
}
- override def save(nbt: NBTTagCompound) {
+ override def saveData(nbt: CompoundNBT) {
if (!Strings.isNullOrEmpty(name)) {
ItemUtils.setDisplayName(nbt, name)
}
- nbt.setInteger(StoredEnergyTag, totalEnergy)
- nbt.setInteger(RobotEnergyTag, robotEnergy)
- nbt.setInteger(TierTag, tier)
+ nbt.putInt(StoredEnergyTag, totalEnergy)
+ nbt.putInt(RobotEnergyTag, robotEnergy)
+ nbt.putInt(TierTag, tier)
nbt.setNewTagList(ComponentsTag, components.toIterable)
nbt.setNewTagList(ContainersTag, containers.toIterable)
- nbt.setInteger(LightColorTag, lightColor)
+ nbt.putInt(LightColorTag, lightColor)
}
def copyItemStack() = {
@@ -96,8 +96,8 @@ class RobotData extends ItemData(Constants.BlockName.Robot) {
newInfo.components.foreach(cs => Option(api.Driver.driverFor(cs)) match {
case Some(driver) if driver == DriverScreen =>
val nbt = driver.dataTag(cs)
- for (tagName <- nbt.getKeySet.toArray) {
- nbt.removeTag(tagName.asInstanceOf[String])
+ for (tagName <- nbt.getAllKeys.toArray) {
+ nbt.remove(tagName.asInstanceOf[String])
}
case _ =>
})
@@ -105,7 +105,7 @@ class RobotData extends ItemData(Constants.BlockName.Robot) {
// internal buffer. This is for creative use only, anyway.
newInfo.totalEnergy = 0
newInfo.robotEnergy = 50000
- newInfo.save(stack)
+ newInfo.saveData(stack)
stack
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/TabletData.scala b/src/main/scala/li/cil/oc/common/item/data/TabletData.scala
index 7830d0a438..953c2237cd 100644
--- a/src/main/scala/li/cil/oc/common/item/data/TabletData.scala
+++ b/src/main/scala/li/cil/oc/common/item/data/TabletData.scala
@@ -5,13 +5,13 @@ import li.cil.oc.Settings
import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraftforge.common.util.Constants.NBT
class TabletData extends ItemData(Constants.ItemName.Tablet) {
def this(stack: ItemStack) {
this()
- load(stack)
+ loadData(stack)
}
var items = Array.fill[ItemStack](32)(ItemStack.EMPTY)
@@ -30,36 +30,36 @@ class TabletData extends ItemData(Constants.ItemName.Tablet) {
private final val TierTag = Settings.namespace + "tier"
private final val ContainerTag = Settings.namespace + "container"
- override def load(nbt: NBTTagCompound) {
- nbt.getTagList(ItemsTag, NBT.TAG_COMPOUND).foreach((slotNbt: NBTTagCompound) => {
+ override def loadData(nbt: CompoundNBT) {
+ nbt.getList(ItemsTag, NBT.TAG_COMPOUND).foreach((slotNbt: CompoundNBT) => {
val slot = slotNbt.getByte(SlotTag)
if (slot >= 0 && slot < items.length) {
- items(slot) = new ItemStack(slotNbt.getCompoundTag(ItemTag))
+ items(slot) = ItemStack.of(slotNbt.getCompound(ItemTag))
}
})
isRunning = nbt.getBoolean(IsRunningTag)
energy = nbt.getDouble(EnergyTag)
maxEnergy = nbt.getDouble(MaxEnergyTag)
- tier = nbt.getInteger(TierTag)
- if (nbt.hasKey(ContainerTag)) {
- container = new ItemStack(nbt.getCompoundTag(ContainerTag))
+ tier = nbt.getInt(TierTag)
+ if (nbt.contains(ContainerTag)) {
+ container = ItemStack.of(nbt.getCompound(ContainerTag))
}
}
- override def save(nbt: NBTTagCompound) {
+ override def saveData(nbt: CompoundNBT) {
nbt.setNewTagList(ItemsTag,
items.zipWithIndex collect {
case (stack, slot) if !stack.isEmpty => (stack, slot)
} map {
case (stack, slot) =>
- val slotNbt = new NBTTagCompound()
- slotNbt.setByte(SlotTag, slot.toByte)
- slotNbt.setNewCompoundTag(ItemTag, stack.writeToNBT)
+ val slotNbt = new CompoundNBT()
+ slotNbt.putByte(SlotTag, slot.toByte)
+ slotNbt.setNewCompoundTag(ItemTag, stack.save)
})
- nbt.setBoolean(IsRunningTag, isRunning)
- nbt.setDouble(EnergyTag, energy)
- nbt.setDouble(MaxEnergyTag, maxEnergy)
- nbt.setInteger(TierTag, tier)
- if (!container.isEmpty) nbt.setNewCompoundTag(ContainerTag, container.writeToNBT)
+ nbt.putBoolean(IsRunningTag, isRunning)
+ nbt.putDouble(EnergyTag, energy)
+ nbt.putDouble(MaxEnergyTag, maxEnergy)
+ nbt.putInt(TierTag, tier)
+ if (!container.isEmpty) nbt.setNewCompoundTag(ContainerTag, container.save)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/traits/CPULike.scala b/src/main/scala/li/cil/oc/common/item/traits/CPULike.scala
index 61b7245437..0ae5fda690 100644
--- a/src/main/scala/li/cil/oc/common/item/traits/CPULike.scala
+++ b/src/main/scala/li/cil/oc/common/item/traits/CPULike.scala
@@ -7,29 +7,34 @@ import li.cil.oc.api
import li.cil.oc.api.driver.item.MutableProcessor
import li.cil.oc.integration.opencomputers.DriverCPU
import li.cil.oc.util.Tooltip
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
-import net.minecraft.util.text.TextComponentTranslation
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
+import net.minecraft.util.Util
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.util.text.TranslationTextComponent
import net.minecraft.world.World
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.language.existentials
-trait CPULike extends Delegate {
+trait CPULike extends SimpleItem {
def cpuTier: Int
override protected def tooltipData: Seq[Any] = Seq(Settings.get.cpuComponentSupport(cpuTier))
- override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
- tooltip.addAll(Tooltip.get("cpu.Architecture", api.Machine.getArchitectureName(DriverCPU.architecture(stack))))
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[ITextComponent]) {
+ for (curr <- Tooltip.get("cpu.Architecture", api.Machine.getArchitectureName(DriverCPU.architecture(stack)))) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (player.isSneaking) {
- if (!world.isRemote) {
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (player.isCrouching) {
+ if (!world.isClientSide) {
api.Driver.driverFor(stack) match {
case driver: MutableProcessor =>
val architectures = driver.allArchitectures.toList
@@ -39,13 +44,13 @@ trait CPULike extends Delegate {
val archClass = architectures(newIndex)
val archName = api.Machine.getArchitectureName(archClass)
driver.setArchitecture(stack, archClass)
- player.sendMessage(new TextComponentTranslation(Settings.namespace + "tooltip.cpu.Architecture", archName))
+ player.sendMessage(new TranslationTextComponent(Settings.namespace + "tooltip.cpu.Architecture", archName), Util.NIL_UUID)
}
- player.swingArm(EnumHand.MAIN_HAND)
+ player.swing(Hand.MAIN_HAND)
case _ => // No known driver for this processor.
}
}
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala b/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala
index c32f1c5aa1..f9dad6ab46 100644
--- a/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala
+++ b/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala
@@ -1,21 +1,16 @@
package li.cil.oc.common.item.traits
-import ic2.api.item.IElectricItemManager
import li.cil.oc.{Settings, api}
-import li.cil.oc.common.asm.Injectable
import li.cil.oc.integration.Mods
-import li.cil.oc.integration.ic2.ElectricItemManager
import li.cil.oc.integration.opencomputers.ModOpenComputers
-import net.minecraft.util.{EnumFacing, ResourceLocation}
-import net.minecraftforge.fml.common.Optional
+import net.minecraft.util.{Direction, ResourceLocation}
import net.minecraft.item.ItemStack
import net.minecraftforge.common.capabilities.{Capability, ICapabilityProvider}
import net.minecraftforge.energy.{CapabilityEnergy, IEnergyStorage}
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
// TODO Forge power capabilities.
-@Injectable.InterfaceList(Array(
- new Injectable.Interface(value = "ic2.api.item.ISpecialElectricItem", modid = Mods.IDs.IndustrialCraft2)
-))
trait Chargeable extends api.driver.item.Chargeable {
def maxCharge(stack: ItemStack): Double
@@ -25,9 +20,6 @@ trait Chargeable extends api.driver.item.Chargeable {
def setCharge(stack: ItemStack, amount: Double): Unit
def canExtract(stack: ItemStack): Boolean = false
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- def getManager(stack: ItemStack): IElectricItemManager = ElectricItemManager
}
object Chargeable {
@@ -48,14 +40,16 @@ object Chargeable {
unused
}
- class Provider(stack: ItemStack, item: li.cil.oc.common.item.traits.Chargeable) extends ICapabilityProvider with IEnergyStorage {
- override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
- capability == CapabilityEnergy.ENERGY
- }
+ class Provider(stack: ItemStack, item: li.cil.oc.common.item.traits.Chargeable) extends ICapabilityProvider with NonNullSupplier[Provider] with IEnergyStorage {
+ private val wrapper = LazyOptional.of(this)
+
+ def get = this
+
+ def invalidate() = wrapper.invalidate
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
- if (hasCapability(capability, facing)) this.asInstanceOf[T]
- else null.asInstanceOf[T]
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
+ if (capability == CapabilityEnergy.ENERGY) wrapper.cast[T]
+ else LazyOptional.empty[T]
}
def receiveEnergy(maxReceive: Int, simulate: Boolean): Int =
diff --git a/src/main/scala/li/cil/oc/common/item/traits/Delegate.scala b/src/main/scala/li/cil/oc/common/item/traits/Delegate.scala
deleted file mode 100644
index ce6bb9b06a..0000000000
--- a/src/main/scala/li/cil/oc/common/item/traits/Delegate.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package li.cil.oc.common.item.traits
-
-import java.util
-
-import li.cil.oc.Settings
-import li.cil.oc.api
-import li.cil.oc.api.driver.DriverItem
-import li.cil.oc.common.item.Delegator
-import li.cil.oc.util.BlockPosition
-import li.cil.oc.util.Rarity
-import li.cil.oc.util.Tooltip
-import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.item.EnumAction
-import net.minecraft.item.EnumRarity
-import net.minecraft.item.ItemStack
-import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
-import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-trait Delegate {
- def parent: Delegator
-
- def unlocalizedName: String = getClass.getSimpleName.toLowerCase
-
- protected def tooltipName = Option(unlocalizedName)
-
- protected def tooltipData = Seq.empty[Any]
-
- var showInItemList = true
-
- val itemId: Int = parent.add(this)
-
- def maxStackSize = 64
-
- def createItemStack(amount: Int = 1) = new ItemStack(parent, amount, itemId)
-
- // ----------------------------------------------------------------------- //
-
- def doesSneakBypassUse(world: IBlockAccess, pos: BlockPos, player: EntityPlayer) = false
-
- def onItemUseFirst(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): EnumActionResult = EnumActionResult.PASS
-
- def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = false
-
- def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = ActionResult.newResult(EnumActionResult.PASS, stack)
-
- def getItemUseAction(stack: ItemStack): EnumAction = EnumAction.NONE
-
- def getMaxItemUseDuration(stack: ItemStack) = 0
-
- def onItemUseFinish(stack: ItemStack, world: World, player: EntityLivingBase): ItemStack = stack
-
- def onPlayerStoppedUsing(stack: ItemStack, player: EntityLivingBase, duration: Int) {}
-
- def update(stack: ItemStack, world: World, player: Entity, slot: Int, selected: Boolean) {}
-
- // ----------------------------------------------------------------------- //
-
- def rarity(stack: ItemStack): EnumRarity = Rarity.byTier(tierFromDriver(stack))
-
- protected def tierFromDriver(stack: ItemStack): Int =
- api.Driver.driverFor(stack) match {
- case driver: DriverItem => driver.tier(stack)
- case _ => 0
- }
-
- def color(stack: ItemStack, pass: Int) = 0xFFFFFF
-
- def getContainerItem(stack: ItemStack): ItemStack = ItemStack.EMPTY
-
- def hasContainerItem(stack: ItemStack): Boolean = false
-
- def displayName(stack: ItemStack): Option[String] = None
-
- @SideOnly(Side.CLIENT)
- def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- if (tooltipName.isDefined) {
- tooltip.addAll(Tooltip.get(tooltipName.get, tooltipData: _*))
- tooltipExtended(stack, tooltip)
- }
- tooltipCosts(stack, tooltip)
- }
-
- // For stuff that goes to the normal 'extended' tooltip, before the costs.
- protected def tooltipExtended(stack: ItemStack, tooltip: java.util.List[String]) {}
-
- protected def tooltipCosts(stack: ItemStack, tooltip: java.util.List[String]) {
- if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "data")) {
- val data = stack.getTagCompound.getCompoundTag(Settings.namespace + "data")
- if (data.hasKey("node") && data.getCompoundTag("node").hasKey("address")) {
- tooltip.add("§8" + data.getCompoundTag("node").getString("address").substring(0, 13) + "...§7")
- }
- }
- }
-
- def showDurabilityBar(stack: ItemStack) = false
-
- def durability(stack: ItemStack) = 0.0
-}
diff --git a/src/main/scala/li/cil/oc/common/item/traits/FileSystemLike.scala b/src/main/scala/li/cil/oc/common/item/traits/FileSystemLike.scala
index c4fd815d66..b07e363ac9 100644
--- a/src/main/scala/li/cil/oc/common/item/traits/FileSystemLike.scala
+++ b/src/main/scala/li/cil/oc/common/item/traits/FileSystemLike.scala
@@ -5,49 +5,61 @@ import java.util
import li.cil.oc.Localization
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
-import li.cil.oc.common.GuiType
-import net.minecraft.client.util.ITooltipFlag
+import li.cil.oc.client.gui
import li.cil.oc.common.item.data.DriveData
-import net.minecraft.entity.player.EntityPlayer
+import li.cil.oc.util.Tooltip
+import net.minecraft.client.Minecraft
+import net.minecraft.client.util.ITooltipFlag
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
-import net.minecraft.util.EnumActionResult
-import net.minecraft.util.EnumHand
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Hand
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-trait FileSystemLike extends Delegate {
+trait FileSystemLike extends SimpleItem {
override protected def tooltipName = None
def kiloBytes: Int
- override def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag): Unit = {
- if (stack.hasTagCompound) {
- val nbt = stack.getTagCompound
- if (nbt.hasKey(Settings.namespace + "data")) {
- val data = nbt.getCompoundTag(Settings.namespace + "data")
- if (data.hasKey(Settings.namespace + "fs.label")) {
- tooltip.add(data.getString(Settings.namespace + "fs.label"))
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
+ if (stack.hasTag) {
+ val nbt = stack.getTag
+ if (nbt.contains(Settings.namespace + "data")) {
+ val data = nbt.getCompound(Settings.namespace + "data")
+ if (data.contains(Settings.namespace + "fs.label")) {
+ tooltip.add(new StringTextComponent(data.getString(Settings.namespace + "fs.label")).setStyle(Tooltip.DefaultStyle))
}
- if (flag.isAdvanced && data.hasKey("fs")) {
- val fsNbt = data.getCompoundTag("fs")
- if (fsNbt.hasKey("capacity.used")) {
+ if (flag.isAdvanced && data.contains("fs")) {
+ val fsNbt = data.getCompound("fs")
+ if (fsNbt.contains("capacity.used")) {
val used = fsNbt.getLong("capacity.used")
- tooltip.add(Localization.Tooltip.DiskUsage(used, kiloBytes * 1024))
+ tooltip.add(new StringTextComponent(Localization.Tooltip.DiskUsage(used, kiloBytes * 1024)).setStyle(Tooltip.DefaultStyle))
}
}
}
val data = new DriveData(stack)
- tooltip.add(Localization.Tooltip.DiskMode(data.isUnmanaged))
- tooltip.add(Localization.Tooltip.DiskLock(data.lockInfo))
+ tooltip.add(new StringTextComponent(Localization.Tooltip.DiskMode(data.isUnmanaged)).setStyle(Tooltip.DefaultStyle))
+ tooltip.add(new StringTextComponent(Localization.Tooltip.DiskLock(data.lockInfo)).setStyle(Tooltip.DefaultStyle))
}
- super.tooltipLines(stack, world, tooltip, flag)
}
- override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ActionResult[ItemStack] = {
- if (!player.isSneaking && (!stack.hasTagCompound || !stack.getTagCompound.hasKey(Settings.namespace + "lootFactory"))) {
- player.openGui(OpenComputers, GuiType.Drive.id, world, 0, 0, 0)
- player.swingArm(EnumHand.MAIN_HAND)
+ override def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = {
+ if (!player.isCrouching && (!stack.hasTag || !stack.getTag.contains(Settings.namespace + "lootFactory"))) {
+ if (world.isClientSide) showGui(stack, player)
+ player.swing(Hand.MAIN_HAND)
}
- ActionResult.newResult(EnumActionResult.SUCCESS, stack)
+ new ActionResult(ActionResultType.sidedSuccess(world.isClientSide), stack)
+ }
+
+ @OnlyIn(Dist.CLIENT)
+ private def showGui(stack: ItemStack, player: PlayerEntity) {
+ Minecraft.getInstance.pushGuiLayer(new gui.Drive(player.inventory, () => stack))
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/traits/GPULike.scala b/src/main/scala/li/cil/oc/common/item/traits/GPULike.scala
index ffd255ef6d..73f2ec3c6c 100644
--- a/src/main/scala/li/cil/oc/common/item/traits/GPULike.scala
+++ b/src/main/scala/li/cil/oc/common/item/traits/GPULike.scala
@@ -3,7 +3,7 @@ package li.cil.oc.common.item.traits
import li.cil.oc.Settings
import li.cil.oc.util.PackedColor
-trait GPULike extends Delegate {
+trait GPULike extends SimpleItem {
def gpuTier: Int
override protected def tooltipData: Seq[Any] = {
diff --git a/src/main/scala/li/cil/oc/common/item/traits/ItemTier.scala b/src/main/scala/li/cil/oc/common/item/traits/ItemTier.scala
index f499f96775..74c63c681e 100644
--- a/src/main/scala/li/cil/oc/common/item/traits/ItemTier.scala
+++ b/src/main/scala/li/cil/oc/common/item/traits/ItemTier.scala
@@ -3,20 +3,22 @@ package li.cil.oc.common.item.traits
import java.util
import li.cil.oc.Localization
+import li.cil.oc.util.Tooltip
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-trait ItemTier extends Delegate {
- self: Delegate =>
- @SideOnly(Side.CLIENT)
- override def tooltipLines(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- super.tooltipLines(stack, world, tooltip, flag)
+trait ItemTier extends SimpleItem {
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ super.appendHoverText(stack, world, tooltip, flag)
if (flag.isAdvanced) {
- tooltip.add(Localization.Tooltip.Tier(tierFromDriver(stack) + 1))
+ tooltip.add(new StringTextComponent(Localization.Tooltip.Tier(tierFromDriver(stack) + 1)).setStyle(Tooltip.DefaultStyle))
}
}
}
diff --git a/src/main/scala/li/cil/oc/common/item/traits/SimpleItem.scala b/src/main/scala/li/cil/oc/common/item/traits/SimpleItem.scala
index 2c85eafa62..0e6ca4b855 100644
--- a/src/main/scala/li/cil/oc/common/item/traits/SimpleItem.scala
+++ b/src/main/scala/li/cil/oc/common/item/traits/SimpleItem.scala
@@ -2,43 +2,133 @@ package li.cil.oc.common.item.traits
import java.util
-import li.cil.oc.CreativeTab
+import com.mojang.blaze3d.matrix.MatrixStack
import li.cil.oc.Settings
+import li.cil.oc.api
+import li.cil.oc.api.event.RobotRenderEvent.MountPoint
+import li.cil.oc.api.internal.Robot
+import li.cil.oc.client.renderer.item.UpgradeRenderer
import li.cil.oc.common.tileentity
+import li.cil.oc.integration.opencomputers.{Item => OpenComputersItem}
+import li.cil.oc.util.BlockPosition
import li.cil.oc.util.Tooltip
+import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.util.ITooltipFlag
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.item.BlockItemUseContext
import net.minecraft.item.Item
+import net.minecraft.item.Item.Properties
import net.minecraft.item.ItemStack
+import net.minecraft.item.ItemUseContext
+import net.minecraft.util.ActionResult
+import net.minecraft.util.ActionResultType
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
-import net.minecraft.world.IBlockAccess
+import net.minecraft.util.text.ITextComponent
+import net.minecraft.util.text.StringTextComponent
+import net.minecraft.world.IWorldReader
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-trait SimpleItem extends Item {
- setCreativeTab(CreativeTab)
+import scala.collection.convert.ImplicitConversionsToScala._
+trait SimpleItem extends Item with api.driver.item.UpgradeRenderer {
def createItemStack(amount: Int = 1) = new ItemStack(this, amount)
- override def isBookEnchantable(stack: ItemStack, book: ItemStack) = false
+ @Deprecated
+ protected var unlocalizedName = getClass.getSimpleName.toLowerCase
- override def doesSneakBypassUse(stack: ItemStack, world: IBlockAccess, pos: BlockPos, player: EntityPlayer): Boolean = {
- world.getTileEntity(pos) match {
+ @Deprecated
+ override def getDescriptionId = "item.oc." + unlocalizedName
+
+ override def doesSneakBypassUse(stack: ItemStack, world: IWorldReader, pos: BlockPos, player: PlayerEntity): Boolean = {
+ world.getBlockEntity(pos) match {
case drive: tileentity.DiskDrive => true
case _ => super.doesSneakBypassUse(stack, world, pos, player)
}
}
- @SideOnly(Side.CLIENT)
- override def addInformation(stack: ItemStack, world: World, tooltip: util.List[String], flag: ITooltipFlag) {
- tooltip.addAll(Tooltip.get(getClass.getSimpleName.toLowerCase))
+ @Deprecated
+ override def onItemUseFirst(stack: ItemStack, ctx: ItemUseContext): ActionResultType = {
+ val pos = ctx.getClickedPos
+ val hitPos = ctx.getClickLocation
+ onItemUseFirst(stack, ctx.getPlayer, ctx.getPlayer.level, pos, ctx.getClickedFace,
+ (hitPos.x - pos.getX).toFloat, (hitPos.y - pos.getY).toFloat, (hitPos.z - pos.getZ).toFloat, ctx.getHand)
+ }
+
+ @Deprecated
+ def onItemUseFirst(stack: ItemStack, player: PlayerEntity, world: World, pos: BlockPos, side: Direction, hitX: Float, hitY: Float, hitZ: Float, hand: Hand): ActionResultType = ActionResultType.PASS
+
+ @Deprecated
+ override def useOn(ctx: ItemUseContext): ActionResultType =
+ ctx.getItemInHand match {
+ case stack: ItemStack => {
+ val world = ctx.getLevel
+ val pos = BlockPosition(ctx.getClickedPos, world)
+ val hitPos = ctx.getClickLocation
+ val success = onItemUse(stack, ctx.getPlayer, pos, ctx.getClickedFace,
+ (hitPos.x - pos.x).toFloat, (hitPos.y - pos.y).toFloat, (hitPos.z - pos.z).toFloat)
+ if (success) ActionResultType.sidedSuccess(world.isClientSide) else ActionResultType.PASS
+ }
+ case _ => super.useOn(ctx)
+ }
+
+ @Deprecated
+ def onItemUse(stack: ItemStack, player: PlayerEntity, position: BlockPosition, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Boolean = false
+
+ @Deprecated
+ override def use(world: World, player: PlayerEntity, hand: Hand): ActionResult[ItemStack] =
+ player.getItemInHand(hand) match {
+ case stack: ItemStack => use(stack, world, player)
+ case _ => super.use(world, player, hand)
+ }
+
+ @Deprecated
+ def use(stack: ItemStack, world: World, player: PlayerEntity): ActionResult[ItemStack] = new ActionResult(ActionResultType.PASS, stack)
+
+ protected def tierFromDriver(stack: ItemStack): Int =
+ api.Driver.driverFor(stack) match {
+ case driver: api.driver.DriverItem => driver.tier(stack)
+ case _ => 0
+ }
+
+ protected def tooltipName = Option(unlocalizedName)
+
+ protected def tooltipData = Seq.empty[Any]
+
+ @OnlyIn(Dist.CLIENT)
+ override def appendHoverText(stack: ItemStack, world: World, tooltip: util.List[ITextComponent], flag: ITooltipFlag) {
+ if (tooltipName.isDefined) {
+ for (curr <- Tooltip.get(tooltipName.get, tooltipData: _*)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
+ tooltipExtended(stack, tooltip)
+ }
+ else {
+ for (curr <- Tooltip.get(getClass.getSimpleName.toLowerCase)) {
+ tooltip.add(new StringTextComponent(curr).setStyle(Tooltip.DefaultStyle))
+ }
+ }
+ tooltipCosts(stack, tooltip)
+ }
+
+ // For stuff that goes to the normal 'extended' tooltip, before the costs.
+ protected def tooltipExtended(stack: ItemStack, tooltip: java.util.List[ITextComponent]) {}
- if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "data")) {
- val data = stack.getTagCompound.getCompoundTag(Settings.namespace + "data")
- if (data.hasKey("node") && data.getCompoundTag("node").hasKey("address")) {
- tooltip.add("§8" + data.getCompoundTag("node").getString("address").substring(0, 13) + "...§7")
+ protected def tooltipCosts(stack: ItemStack, tooltip: java.util.List[ITextComponent]) {
+ if (stack.hasTag && stack.getTag.contains(Settings.namespace + "data")) {
+ val data = stack.getTag.getCompound(Settings.namespace + "data")
+ if (data.contains("node") && data.getCompound("node").contains("address")) {
+ tooltip.add(new StringTextComponent("§8" + data.getCompound("node").getString("address").substring(0, 13) + "...§7"))
}
}
}
+
+ // ----------------------------------------------------------------------- //
+
+ override def computePreferredMountPoint(stack: ItemStack, robot: Robot, availableMountPoints: util.Set[String]): String = UpgradeRenderer.preferredMountPoint(stack, availableMountPoints)
+
+ override def render(matrix: MatrixStack, buffer: IRenderTypeBuffer, stack: ItemStack, mountPoint: MountPoint, robot: Robot, pt: Float): Unit = UpgradeRenderer.render(matrix, buffer, stack, mountPoint)
}
diff --git a/src/main/scala/li/cil/oc/common/launch/CoreModContainer.scala b/src/main/scala/li/cil/oc/common/launch/CoreModContainer.scala
deleted file mode 100644
index afab110fd9..0000000000
--- a/src/main/scala/li/cil/oc/common/launch/CoreModContainer.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package li.cil.oc.common.launch
-
-import com.google.common.eventbus.EventBus
-import net.minecraftforge.fml.common.DummyModContainer
-import net.minecraftforge.fml.common.LoadController
-import net.minecraftforge.fml.common.ModMetadata
-
-class CoreModContainer extends DummyModContainer({
- val md = new ModMetadata()
- md.authorList.add("Sangar")
- md.modId = "opencomputers|core"
- md.version = "@VERSION@"
- md.name = "OpenComputers (Core)"
- md.url = "https://oc.cil.li/"
- md.description = "OC core mod used for class transformer and as API owner to avoid cyclic dependencies."
- md
-}) {
- override def registerBus(bus: EventBus, controller: LoadController) = true
-}
diff --git a/src/main/scala/li/cil/oc/common/launch/TransformerLoader.scala b/src/main/scala/li/cil/oc/common/launch/TransformerLoader.scala
deleted file mode 100644
index 1b27f4a649..0000000000
--- a/src/main/scala/li/cil/oc/common/launch/TransformerLoader.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package li.cil.oc.common.launch
-
-import java.util
-
-import li.cil.oc.common.asm.ClassTransformer
-import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin
-import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.{SortingIndex, TransformerExclusions}
-
-@SortingIndex(1001)
-@TransformerExclusions(Array("li.cil.oc.common.asm"))
-class TransformerLoader extends IFMLLoadingPlugin {
- val instance = this
-
- override def getModContainerClass = "li.cil.oc.common.launch.CoreModContainer"
-
- override def getASMTransformerClass = Array(classOf[ClassTransformer].getName)
-
- override def getAccessTransformerClass = null
-
- override def getSetupClass = null
-
- override def injectData(data: util.Map[String, AnyRef]) {}
-}
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/ControllerImpl.scala b/src/main/scala/li/cil/oc/common/nanomachines/ControllerImpl.scala
index c419650c9d..b881c78a6c 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/ControllerImpl.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/ControllerImpl.scala
@@ -21,29 +21,30 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.PlayerUtils
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.potion.Potion
-import net.minecraft.potion.PotionEffect
-import net.minecraft.util.EnumParticleTypes
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.particles.ParticleTypes
+import net.minecraft.potion.Effect
+import net.minecraft.potion.Effects
+import net.minecraft.potion.EffectInstance
import net.minecraft.util.ResourceLocation
import net.minecraft.world.World
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
-class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessEndpoint {
+class ControllerImpl(val player: PlayerEntity) extends Controller with WirelessEndpoint {
if (isServer) api.Network.joinWirelessNetwork(this)
- var previousDimension = player.world.provider.getDimension
+ var previousDimension = player.level.dimension
lazy val CommandRange = Settings.get.nanomachinesCommandRange * Settings.get.nanomachinesCommandRange
final val FullSyncInterval = 20 * 60
final val OverloadDamage = new DamageSourceWithRandomCause("oc.nanomachinesOverload", 3).
- setDamageBypassesArmor().
- setDamageIsAbsolute()
+ bypassArmor().
+ bypassMagic()
var uuid = UUID.randomUUID.toString
var responsePort = 0
@@ -56,7 +57,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
var activeBehaviorsDirty = true
var hasSentConfiguration = false
- override def world: World = player.getEntityWorld
+ override def world: World = player.level
override def x: Int = BlockPosition(player).x
@@ -65,8 +66,8 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
override def z: Int = BlockPosition(player).z
override def receivePacket(packet: Packet, sender: WirelessEndpoint): Unit = {
- if (getLocalBuffer > 0 && commandDelay < 1 && !player.isDead) {
- val (dx, dy, dz) = ((sender.x + 0.5) - player.posX, (sender.y + 0.5) - player.posY, (sender.z + 0.5) - player.posZ)
+ if (getLocalBuffer > 0 && commandDelay < 1 && player.isAlive) {
+ val (dx, dy, dz) = ((sender.x + 0.5) - player.getX, (sender.y + 0.5) - player.getY, (sender.z + 0.5) - player.getZ)
val dSquared = Math.sqrt(dx * dx + dy * dy + dz * dz)
if (dSquared <= CommandRange) packet.data.headOption match {
case Some(header: Array[Byte]) if new String(header, Charsets.UTF_8) == "nanomachines" =>
@@ -83,11 +84,11 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
case Array("saveConfiguration") =>
val nanomachines = api.Items.get(Constants.ItemName.Nanomachines)
try {
- val index = player.inventory.mainInventory.indexWhere(stack => api.Items.get(stack) == nanomachines && new NanomachineData(stack).configuration.isEmpty)
+ val index = player.inventory.items.indexWhere(stack => api.Items.get(stack) == nanomachines && new NanomachineData(stack).configuration.isEmpty)
if (index >= 0) {
- val stack = player.inventory.decrStackSize(index, 1)
- new NanomachineData(this).save(stack)
- player.inventory.addItemStackToInventory(stack)
+ val stack = player.inventory.removeItem(index, 1)
+ new NanomachineData(this).saveData(stack)
+ player.inventory.add(stack)
InventoryUtils.spawnStackInWorld(BlockPosition(player), stack)
respond(sender, "saved", true)
}
@@ -100,11 +101,11 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
case Array("getHealth") =>
respond(sender, "health", player.getHealth, player.getMaxHealth)
case Array("getHunger") =>
- respond(sender, "hunger", player.getFoodStats.getFoodLevel, player.getFoodStats.getSaturationLevel)
+ respond(sender, "hunger", player.getFoodData.getFoodLevel, player.getFoodData.getSaturationLevel)
case Array("getAge") =>
- respond(sender, "age", (player.getIdleTime / 20f).toInt)
+ respond(sender, "age", (player.getNoActionTime / 20f).toInt)
case Array("getName") =>
- respond(sender, "name", player.getDisplayName.getUnformattedComponentText)
+ respond(sender, "name", player.getDisplayName.getString)
case Array("getExperience") =>
respond(sender, "experience", player.experienceLevel)
@@ -171,10 +172,10 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
activeBehaviorsDirty = true
player match {
- case playerMP: EntityPlayerMP if playerMP.connection != null =>
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("blindness"), 100))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("poison"), 150))
- player.addPotionEffect(new PotionEffect(Potion.getPotionFromResourceLocation("slowness"), 200))
+ case playerMP: ServerPlayerEntity if playerMP.connection != null =>
+ player.addEffect(new EffectInstance(Effects.BLINDNESS, 100))
+ player.addEffect(new EffectInstance(Effects.POISON, 150))
+ player.addEffect(new EffectInstance(Effects.MOVEMENT_SLOWDOWN, 200))
changeBuffer(-Settings.get.nanomachineReconfigureCost)
hasSentConfiguration = false
@@ -217,7 +218,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
override def changeBuffer(delta: Double): Double = {
if (isClient) delta
- else if (delta < 0 && (Settings.get.ignorePower || player.capabilities.isCreativeMode)) 0.0
+ else if (delta < 0 && (Settings.get.ignorePower || player.isCreative)) 0.0
else {
val newValue = storedEnergy + delta
storedEnergy = math.min(math.max(newValue, 0), getLocalBufferSize)
@@ -228,7 +229,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
// ----------------------------------------------------------------------- //
def update(): Unit = {
- if (player.isDead) {
+ if (!player.isAlive) {
return
}
@@ -245,10 +246,10 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
// load is called while the world is still set to the overworld, but
// no dimension change event is fired if the player actually logged
// out in another dimension... yay)
- if (player.world.provider.getDimension != previousDimension) {
+ if (player.level.dimension != previousDimension) {
api.Network.leaveWirelessNetwork(this, previousDimension)
api.Network.joinWirelessNetwork(this)
- previousDimension = player.world.provider.getDimension
+ previousDimension = player.level.dimension
}
else {
api.Network.updateWirelessNetwork(this)
@@ -271,14 +272,14 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
active.foreach(_.update())
if (isServer) {
- if (player.getEntityWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (player.level.getGameTime % Settings.get.tickFrequency == 0) {
changeBuffer(-Settings.get.nanomachineCost * Settings.get.tickFrequency * (activeInputs + 0.5))
PacketSender.sendNanomachinePower(player)
}
val overload = activeInputs - getSafeActiveInputs
- if (!player.capabilities.isCreativeMode && overload > 0 && player.getEntityWorld.getTotalWorldTime % 20 == 0) {
- player.attackEntityFrom(OverloadDamage, overload)
+ if (!player.isCreative && overload > 0 && player.level.getGameTime % 20 == 0) {
+ player.hurt(OverloadDamage, overload)
}
}
@@ -286,7 +287,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
val energyRatio = getLocalBuffer / (getLocalBufferSize + 1)
val triggerRatio = activeInputs / (configuration.triggers.length + 1)
val intensity = (energyRatio + triggerRatio) * 0.25
- PlayerUtils.spawnParticleAround(player, EnumParticleTypes.PORTAL, intensity)
+ PlayerUtils.spawnParticleAround(player, ParticleTypes.PORTAL, intensity)
}
}
@@ -299,7 +300,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
// Send a full sync every now and then, e.g. for other players coming
// closer that weren't there to get the initial info for an enabled
// input.
- if (!hasSentConfiguration || player.getEntityWorld.getTotalWorldTime % FullSyncInterval == 0) {
+ if (!hasSentConfiguration || player.level.getGameTime % FullSyncInterval == 0) {
hasSentConfiguration = true
PacketSender.sendNanomachineConfiguration(player)
}
@@ -340,24 +341,24 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
// ----------------------------------------------------------------------- //
- def save(nbt: NBTTagCompound): Unit = configuration.synchronized {
- nbt.setString("uuid", uuid)
- nbt.setInteger("port", responsePort)
- nbt.setDouble("energy", storedEnergy)
- nbt.setNewCompoundTag("configuration", configuration.save)
+ def saveData(nbt: CompoundNBT): Unit = configuration.synchronized {
+ nbt.putString("uuid", uuid)
+ nbt.putInt("port", responsePort)
+ nbt.putDouble("energy", storedEnergy)
+ nbt.setNewCompoundTag("configuration", configuration.saveData)
}
- def load(nbt: NBTTagCompound): Unit = configuration.synchronized {
+ def loadData(nbt: CompoundNBT): Unit = configuration.synchronized {
uuid = nbt.getString("uuid")
- responsePort = nbt.getInteger("port")
+ responsePort = nbt.getInt("port")
storedEnergy = nbt.getDouble("energy")
- configuration.load(nbt.getCompoundTag("configuration"))
+ configuration.loadData(nbt.getCompound("configuration"))
activeBehaviorsDirty = true
}
// ----------------------------------------------------------------------- //
- private def isClient = world.isRemote
+ private def isClient = world.isClientSide
private def isServer = !isClient
@@ -365,8 +366,8 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
if (activeBehaviorsDirty) {
configuration.synchronized(if (activeBehaviorsDirty) {
val newBehaviors = configuration.behaviors.filter(_.isActive).map(_.behavior)
- val addedBehaviors = newBehaviors -- activeBehaviors
- val removedBehaviors = activeBehaviors -- newBehaviors
+ val addedBehaviors = newBehaviors.clone --= activeBehaviors
+ val removedBehaviors = activeBehaviors.clone --= newBehaviors
activeBehaviors.clear()
activeBehaviors ++= newBehaviors
activeBehaviorsDirty = false
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/Nanomachines.scala b/src/main/scala/li/cil/oc/common/nanomachines/Nanomachines.scala
index c166b696a0..c05ad7fb77 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/Nanomachines.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/Nanomachines.scala
@@ -6,46 +6,46 @@ import li.cil.oc.api.nanomachines.BehaviorProvider
import li.cil.oc.api.nanomachines.Controller
import li.cil.oc.server.PacketSender
import li.cil.oc.util.PlayerUtils
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
object Nanomachines extends api.detail.NanomachinesAPI {
val providers = mutable.Set.empty[BehaviorProvider]
- val serverControllers: mutable.WeakHashMap[EntityPlayer, ControllerImpl] = mutable.WeakHashMap.empty[EntityPlayer, ControllerImpl]
- val clientControllers: mutable.WeakHashMap[EntityPlayer, ControllerImpl] = mutable.WeakHashMap.empty[EntityPlayer, ControllerImpl]
+ val serverControllers: mutable.WeakHashMap[PlayerEntity, ControllerImpl] = mutable.WeakHashMap.empty[PlayerEntity, ControllerImpl]
+ val clientControllers: mutable.WeakHashMap[PlayerEntity, ControllerImpl] = mutable.WeakHashMap.empty[PlayerEntity, ControllerImpl]
- def controllers(player: EntityPlayer): mutable.WeakHashMap[EntityPlayer, ControllerImpl] = if (player.getEntityWorld.isRemote) clientControllers else serverControllers
+ def controllers(player: PlayerEntity): mutable.WeakHashMap[PlayerEntity, ControllerImpl] = if (player.level.isClientSide) clientControllers else serverControllers
override def addProvider(provider: BehaviorProvider): Unit = providers += provider
override def getProviders: java.lang.Iterable[BehaviorProvider] = providers
- def getController(player: EntityPlayer): Controller = {
+ def getController(player: PlayerEntity): Controller = {
if (hasController(player)) controllers(player).getOrElseUpdate(player, new ControllerImpl(player))
else null
}
- def hasController(player: EntityPlayer): Boolean = {
+ def hasController(player: PlayerEntity): Boolean = {
PlayerUtils.persistedData(player).getBoolean(Settings.namespace + "hasNanomachines")
}
- def installController(player: EntityPlayer): Controller = {
+ def installController(player: PlayerEntity): Controller = {
if (!hasController(player)) {
- PlayerUtils.persistedData(player).setBoolean(Settings.namespace + "hasNanomachines", true)
+ PlayerUtils.persistedData(player).putBoolean(Settings.namespace + "hasNanomachines", true)
}
getController(player) // Initialize controller instance.
}
- override def uninstallController(player: EntityPlayer): Unit = {
+ override def uninstallController(player: PlayerEntity): Unit = {
getController(player) match {
case controller: ControllerImpl =>
controller.dispose()
controllers(player) -= player
- PlayerUtils.persistedData(player).removeTag(Settings.namespace + "hasNanomachines")
- if (!player.getEntityWorld.isRemote) {
+ PlayerUtils.persistedData(player).remove(Settings.namespace + "hasNanomachines")
+ if (!player.level.isClientSide) {
PacketSender.sendNanomachineConfiguration(player)
}
case _ => // Doesn't have one anyway.
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/NeuralNetwork.scala b/src/main/scala/li/cil/oc/common/nanomachines/NeuralNetwork.scala
index a172acd030..6d85d834e2 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/NeuralNetwork.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/NeuralNetwork.scala
@@ -8,14 +8,15 @@ import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.BehaviorProvider
import li.cil.oc.server.PacketSender
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.text.TextComponentString
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Util
+import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TextFormatting
import net.minecraftforge.common.util.Constants.NBT
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
import scala.util.Random
@@ -58,7 +59,7 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
}
// Build connections.
- val rng = new Random(controller.player.getEntityWorld.rand.nextInt())
+ val rng = new Random(controller.player.level.random.nextInt())
def connect[Sink <: ConnectorNeuron, Source <: Neuron](sinks: Iterable[Sink], sources: mutable.ArrayBuffer[Source]): Unit = {
// Shuffle sink list to give each entry the same chance.
@@ -99,10 +100,10 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
// Enter debug configuration, one input -> one behavior, and list mapping in console.
def debug(): Unit = {
val log = controller.player match {
- case playerMP: EntityPlayerMP => (s: String) => PacketSender.sendClientLog(s, playerMP)
+ case playerMP: ServerPlayerEntity => (s: String) => PacketSender.sendClientLog(s, playerMP)
case _ => (s: String) => OpenComputers.log.info(s)
}
- log(s"Creating debug configuration for nanomachines in player ${controller.player.getDisplayName}.")
+ log(s"Creating debug configuration for nanomachines in player ${controller.player.getDisplayName.getString}.")
behaviors.clear()
behaviors ++= api.Nanomachines.getProviders.
@@ -123,7 +124,7 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
}
}
- def print(player: EntityPlayer): Unit = {
+ def print(player: PlayerEntity): Unit = {
val sb = StringBuilder.newBuilder
def colored(value: Any, enabled: Boolean) = {
if (enabled) sb.append(TextFormatting.GREEN)
@@ -153,13 +154,13 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
}
}
sb.append(")")
- player.sendMessage(new TextComponentString(sb.toString()))
+ player.sendMessage(new StringTextComponent(sb.toString()), Util.NIL_UUID)
sb.clear()
}
}
- override def save(nbt: NBTTagCompound): Unit = {
- save(nbt, forItem = false)
+ override def saveData(nbt: CompoundNBT): Unit = {
+ saveData(nbt, forItem = false)
}
private final val TriggersTag = "triggers"
@@ -170,46 +171,46 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
private final val TriggerInputsTag = "triggerInputs"
private final val ConnectorInputsTag = "connectorInputs"
- def save(nbt: NBTTagCompound, forItem: Boolean): Unit = {
+ def saveData(nbt: CompoundNBT, forItem: Boolean): Unit = {
nbt.setNewTagList(TriggersTag, triggers.map(t => {
- val nbt = new NBTTagCompound()
- nbt.setBoolean(IsActiveTag, t.isActive && !forItem)
+ val nbt = new CompoundNBT()
+ nbt.putBoolean(IsActiveTag, t.isActive && !forItem)
nbt
}))
nbt.setNewTagList(ConnectorsTag, connectors.map(c => {
- val nbt = new NBTTagCompound()
- nbt.setIntArray(TriggerInputsTag, c.inputs.map(triggers.indexOf(_)).filter(_ >= 0).toArray)
+ val nbt = new CompoundNBT()
+ nbt.putIntArray(TriggerInputsTag, c.inputs.map(triggers.indexOf(_)).filter(_ >= 0).toArray)
nbt
}))
nbt.setNewTagList(BehaviorsTag, behaviors.map(b => {
- val nbt = new NBTTagCompound()
- nbt.setIntArray(TriggerInputsTag, b.inputs.map(triggers.indexOf(_)).filter(_ >= 0).toArray)
- nbt.setIntArray(ConnectorInputsTag, b.inputs.map(connectors.indexOf(_)).filter(_ >= 0).toArray)
- nbt.setTag(BehaviorTag, b.provider.writeToNBT(b.behavior))
+ val nbt = new CompoundNBT()
+ nbt.putIntArray(TriggerInputsTag, b.inputs.map(triggers.indexOf(_)).filter(_ >= 0).toArray)
+ nbt.putIntArray(ConnectorInputsTag, b.inputs.map(connectors.indexOf(_)).filter(_ >= 0).toArray)
+ nbt.put(BehaviorTag, b.provider.save(b.behavior))
nbt
}))
}
- override def load(nbt: NBTTagCompound): Unit = {
+ override def loadData(nbt: CompoundNBT): Unit = {
triggers.clear()
- nbt.getTagList(TriggersTag, NBT.TAG_COMPOUND).foreach((t: NBTTagCompound) => {
+ nbt.getList(TriggersTag, NBT.TAG_COMPOUND).foreach((t: CompoundNBT) => {
val neuron = new TriggerNeuron()
neuron.isActive = t.getBoolean(IsActiveTag)
triggers += neuron
})
connectors.clear()
- nbt.getTagList(ConnectorsTag, NBT.TAG_COMPOUND).foreach((t: NBTTagCompound) => {
+ nbt.getList(ConnectorsTag, NBT.TAG_COMPOUND).foreach((t: CompoundNBT) => {
val neuron = new ConnectorNeuron()
neuron.inputs ++= t.getIntArray(TriggerInputsTag).map(triggers.apply)
connectors += neuron
})
behaviors.clear()
- nbt.getTagList(BehaviorsTag, NBT.TAG_COMPOUND).foreach((t: NBTTagCompound) => {
- api.Nanomachines.getProviders.find(p => p.readFromNBT(controller.player, t.getCompoundTag(BehaviorTag)) match {
+ nbt.getList(BehaviorsTag, NBT.TAG_COMPOUND).foreach((t: CompoundNBT) => {
+ api.Nanomachines.getProviders.find(p => p.load(controller.player, t.getCompound(BehaviorTag)) match {
case b: Behavior =>
val neuron = new BehaviorNeuron(p, b)
neuron.inputs ++= t.getIntArray(TriggerInputsTag).map(triggers.apply)
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
index 691d879d7c..7f93526519 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
@@ -9,33 +9,35 @@ import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
import net.minecraft.block.Block
-import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.player.EntityPlayerMP
+import net.minecraft.block.BlockState
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.ServerPlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
+import net.minecraft.util.Hand
import net.minecraft.world.World
+import net.minecraft.world.storage.IServerWorldInfo
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.event.entity.player.PlayerInteractEvent
-import net.minecraftforge.fml.common.eventhandler.Event
+import net.minecraftforge.eventbus.api.Event
import scala.collection.mutable
object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b1bddcdfe7") {
- override def createScalaBehaviors(player: EntityPlayer) = Iterable(new DisintegrationBehavior(player))
+ override def createScalaBehaviors(player: PlayerEntity) = Iterable(new DisintegrationBehavior(player))
- override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = new DisintegrationBehavior(player)
+ override def readBehaviorFromNBT(player: PlayerEntity, nbt: CompoundNBT) = new DisintegrationBehavior(player)
- class DisintegrationBehavior(p: EntityPlayer) extends AbstractBehavior(p) {
+ class DisintegrationBehavior(p: PlayerEntity) extends AbstractBehavior(p) {
var breakingMap = mutable.Map.empty[BlockPosition, SlowBreakInfo]
var breakingMapNew = mutable.Map.empty[BlockPosition, SlowBreakInfo]
// Note: intentionally not overriding getNameHint. Gotta find this one manually!
override def onDisable(reason: DisableReason): Unit = {
- val world = player.getEntityWorld
+ val world = player.level
for (pos <- breakingMap.keys) {
world.destroyBlockInWorldPartially(pos.hashCode(), pos, -1)
}
@@ -43,11 +45,11 @@ object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b
}
override def update(): Unit = {
- val world = player.getEntityWorld
- if (!world.isRemote) player match {
+ val world = player.level
+ if (!world.isClientSide) player match {
case _: FakePlayer => // Nope
- case playerMP: EntityPlayerMP =>
- val now = world.getTotalWorldTime
+ case playerMP: ServerPlayerEntity =>
+ val now = world.getGameTime
// Check blocks in range.
val blockPos = BlockPosition(player)
@@ -59,17 +61,21 @@ object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b
breakingMapNew += pos -> info
info.update(world, player, now)
case None =>
- val event = new PlayerInteractEvent.LeftClickBlock(player, pos.toBlockPos, player.getHorizontalFacing, null)
+ val event = new PlayerInteractEvent.LeftClickBlock(player, pos.toBlockPos, player.getDirection)
MinecraftForge.EVENT_BUS.post(event)
val allowed = !event.isCanceled && event.getUseBlock != Event.Result.DENY && event.getUseItem != Event.Result.DENY
- val adventureOk = !world.getWorldInfo.getGameType.hasLimitedInteractions || player.canPlayerEdit(pos.toBlockPos, null, player.getHeldItemMainhand)
+ val placingRestricted = world.getLevelData match {
+ case srvInfo: IServerWorldInfo => srvInfo.getGameType.isBlockPlacingRestricted
+ case _ => true // Means it's not a server world (somehow).
+ }
+ val adventureOk = !placingRestricted || player.mayUseItemAt(pos.toBlockPos, null, player.getItemInHand(Hand.MAIN_HAND))
if (allowed && adventureOk && !world.isAirBlock(pos)) {
val blockState = world.getBlockState(pos.toBlockPos)
- val hardness = blockState.getBlock.getPlayerRelativeBlockHardness(world.getBlockState(pos.toBlockPos), player, world, pos.toBlockPos)
+ val hardness = blockState.getDestroyProgress(player, world, pos.toBlockPos)
if (hardness > 0) {
val timeToBreak = (1 / hardness).toInt
if (timeToBreak < 20 * 30) {
- val info = new SlowBreakInfo(now, now + timeToBreak, pos, StackOption(player.getHeldItemMainhand).map(_.copy()), blockState)
+ val info = new SlowBreakInfo(now, now + timeToBreak, pos, StackOption(player.getItemInHand(Hand.MAIN_HAND)).map(_.copy()), blockState)
world.destroyBlockInWorldPartially(pos.hashCode(), pos, 0)
breakingMapNew += pos -> info
}
@@ -101,19 +107,19 @@ object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b
}
}
- class SlowBreakInfo(val timeStarted: Long, val timeBroken: Long, val pos: BlockPosition, val originalTool: StackOption, val blockState: IBlockState) {
+ class SlowBreakInfo(val timeStarted: Long, val timeBroken: Long, val pos: BlockPosition, val originalTool: StackOption, val blockState: BlockState) {
var lastDamageSent = 0
- def checkTool(player: EntityPlayer): Boolean = {
- val currentTool = StackOption(player.getHeldItemMainhand).map(_.copy())
+ def checkTool(player: PlayerEntity): Boolean = {
+ val currentTool = StackOption(player.getItemInHand(Hand.MAIN_HAND)).map(_.copy())
(currentTool, originalTool) match {
- case (SomeStack(stackA), SomeStack(stackB)) => stackA.getItem == stackB.getItem && (stackA.isItemStackDamageable || stackA.getItemDamage == stackB.getItemDamage)
+ case (SomeStack(stackA), SomeStack(stackB)) => stackA.getItem == stackB.getItem && (stackA.isDamageableItem || stackA.getDamageValue == stackB.getDamageValue)
case (EmptyStack, EmptyStack) => true
case _ => false
}
}
- def update(world: World, player: EntityPlayer, now: Long): Unit = {
+ def update(world: World, player: PlayerEntity, now: Long): Unit = {
val timeTotal = timeBroken - timeStarted
if (timeTotal > 0) {
val timeTaken = now - timeStarted
@@ -125,12 +131,12 @@ object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b
}
}
- def finish(world: World, player: EntityPlayerMP): Unit = {
+ def finish(world: World, player: ServerPlayerEntity): Unit = {
val sameBlock = world.getBlockState(pos.toBlockPos) == blockState
if (sameBlock) {
world.destroyBlockInWorldPartially(pos.hashCode(), pos, -1)
- if (player.interactionManager.tryHarvestBlock(pos.toBlockPos)) {
- world.playAuxSFX(2001, pos, Block.getIdFromBlock(blockState.getBlock) + (blockState.getBlock.getMetaFromState(blockState) << 12))
+ if (player.gameMode.destroyBlock(pos.toBlockPos)) {
+ world.playAuxSFX(2001, pos, Block.getId(blockState))
}
}
}
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/HungryProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/HungryProvider.scala
index 29a4bd2e18..4ff389a19f 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/HungryProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/HungryProvider.scala
@@ -6,24 +6,24 @@ import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.DisableReason
import li.cil.oc.api.prefab.AbstractBehavior
import li.cil.oc.integration.util.DamageSourceWithRandomCause
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
object HungryProvider extends ScalaProvider("d697c24a-014c-4773-a288-23084a59e9e8") {
final val FillCount = 10 // Create a bunch of these to have a higher chance of one being picked / available.
final val HungryDamage = new DamageSourceWithRandomCause("oc.nanomachinesHungry", 3).
- setDamageBypassesArmor().
- setDamageIsAbsolute()
+ bypassArmor().
+ bypassMagic()
- override def createScalaBehaviors(player: EntityPlayer): Iterable[Behavior] = Iterable.fill(FillCount)(new HungryBehavior(player))
+ override def createScalaBehaviors(player: PlayerEntity): Iterable[Behavior] = Iterable.fill(FillCount)(new HungryBehavior(player))
- override protected def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior = new HungryBehavior(player)
+ override protected def readBehaviorFromNBT(player: PlayerEntity, nbt: CompoundNBT): Behavior = new HungryBehavior(player)
- class HungryBehavior(player: EntityPlayer) extends AbstractBehavior(player) {
+ class HungryBehavior(player: PlayerEntity) extends AbstractBehavior(player) {
override def onDisable(reason: DisableReason): Unit = {
if (reason == DisableReason.OutOfEnergy) {
- player.attackEntityFrom(HungryDamage, Settings.get.nanomachinesHungryDamage)
+ player.hurt(HungryDamage, Settings.get.nanomachinesHungryDamage)
api.Nanomachines.getController(player).changeBuffer(Settings.get.nanomachinesHungryEnergyRestored)
}
}
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/MagnetProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/MagnetProvider.scala
index 49a0f966dd..6060551903 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/MagnetProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/MagnetProvider.scala
@@ -3,33 +3,33 @@ package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.prefab.AbstractBehavior
-import net.minecraft.entity.item.EntityItem
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.math.Vec3d
+import net.minecraft.entity.item.ItemEntity
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.math.vector.Vector3d
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object MagnetProvider extends ScalaProvider("9324d5ec-71f1-41c2-b51c-406e527668fc") {
- override def createScalaBehaviors(player: EntityPlayer) = Iterable(new MagnetBehavior(player))
+ override def createScalaBehaviors(player: PlayerEntity) = Iterable(new MagnetBehavior(player))
- override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = new MagnetBehavior(player)
+ override def readBehaviorFromNBT(player: PlayerEntity, nbt: CompoundNBT) = new MagnetBehavior(player)
- class MagnetBehavior(player: EntityPlayer) extends AbstractBehavior(player) {
+ class MagnetBehavior(player: PlayerEntity) extends AbstractBehavior(player) {
override def getNameHint = "magnet"
override def update(): Unit = {
- val world = player.getEntityWorld
- if (!world.isRemote) {
+ val world = player.level
+ if (!world.isClientSide) {
val actualRange = Settings.get.nanomachineMagnetRange * api.Nanomachines.getController(player).getInputCount(this)
- val items = world.getEntitiesWithinAABB(classOf[EntityItem], player.getEntityBoundingBox.grow(actualRange, actualRange, actualRange))
+ val items = world.getEntitiesOfClass(classOf[ItemEntity], player.getBoundingBox.inflate(actualRange, actualRange, actualRange))
items.collect {
- case item: EntityItem if !item.cannotPickup && !item.getItem.isEmpty && player.inventory.mainInventory.exists(stack => stack.isEmpty || stack.getCount < stack.getMaxStackSize && stack.isItemEqual(item.getItem)) =>
- val dx = player.posX - item.posX
- val dy = player.posY - item.posY
- val dz = player.posZ - item.posZ
- val delta = new Vec3d(dx, dy, dz).normalize()
- item.addVelocity(delta.x * 0.1, delta.y * 0.1, delta.z * 0.1)
+ case item: ItemEntity if !item.hasPickUpDelay && !item.getItem.isEmpty && player.inventory.items.exists(stack => stack.isEmpty || stack.getCount < stack.getMaxStackSize && stack.sameItem(item.getItem)) =>
+ val dx = player.getX - item.getX
+ val dy = player.getY - item.getY
+ val dz = player.getZ - item.getZ
+ val delta = new Vector3d(dx, dy, dz).normalize()
+ item.push(delta.x * 0.1, delta.y * 0.1, delta.z * 0.1)
}
}
}
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/ParticleProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/ParticleProvider.scala
index 2aaa72b51c..2cad56597b 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/ParticleProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/ParticleProvider.scala
@@ -5,48 +5,50 @@ import li.cil.oc.api
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.prefab.AbstractBehavior
import li.cil.oc.util.PlayerUtils
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumParticleTypes
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.particles.BasicParticleType
+import net.minecraft.particles.ParticleType
+import net.minecraft.particles.ParticleTypes
+import net.minecraftforge.registries.ForgeRegistries
+import net.minecraftforge.registries.ForgeRegistry
object ParticleProvider extends ScalaProvider("b48c4bbd-51bb-4915-9367-16cff3220e4b") {
- final val ParticleTypes = Array(
- EnumParticleTypes.FIREWORKS_SPARK,
- EnumParticleTypes.TOWN_AURA,
- EnumParticleTypes.SMOKE_NORMAL,
- EnumParticleTypes.SPELL_WITCH,
- EnumParticleTypes.NOTE,
- EnumParticleTypes.ENCHANTMENT_TABLE,
- EnumParticleTypes.FLAME,
- EnumParticleTypes.LAVA,
- EnumParticleTypes.WATER_SPLASH,
- EnumParticleTypes.REDSTONE,
- EnumParticleTypes.SLIME,
- EnumParticleTypes.HEART,
- EnumParticleTypes.VILLAGER_HAPPY
+ final val ParticleTypeList: Array[BasicParticleType] = Array(
+ ParticleTypes.FIREWORK,
+ ParticleTypes.SMOKE,
+ ParticleTypes.WITCH,
+ ParticleTypes.NOTE,
+ ParticleTypes.ENCHANT,
+ ParticleTypes.FLAME,
+ ParticleTypes.LAVA,
+ ParticleTypes.SPLASH,
+ ParticleTypes.ITEM_SLIME,
+ ParticleTypes.HEART,
+ ParticleTypes.HAPPY_VILLAGER
)
- override def createScalaBehaviors(player: EntityPlayer): Iterable[Behavior] = ParticleTypes.map(new ParticleBehavior(_, player))
+ override def createScalaBehaviors(player: PlayerEntity): Iterable[Behavior] = ParticleTypeList.map(new ParticleBehavior(_, player))
- override def writeBehaviorToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {
+ override def writeBehaviorToNBT(behavior: Behavior, nbt: CompoundNBT): Unit = {
behavior match {
case particles: ParticleBehavior =>
- nbt.setInteger("effectName", particles.effectType.getParticleID)
+ nbt.putInt("effectName", ForgeRegistries.PARTICLE_TYPES.asInstanceOf[ForgeRegistry[ParticleType[_]]].getID(particles.effectType))
case _ => // Wat.
}
}
- override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior = {
- val effectType = EnumParticleTypes.getParticleFromId(nbt.getInteger("effectName"))
- new ParticleBehavior(effectType, player)
+ override def readBehaviorFromNBT(player: PlayerEntity, nbt: CompoundNBT): Behavior = {
+ val effectType = ForgeRegistries.PARTICLE_TYPES.asInstanceOf[ForgeRegistry[ParticleType[_]]].getValue(nbt.getInt("effectName"))
+ new ParticleBehavior(effectType.asInstanceOf[BasicParticleType], player)
}
- class ParticleBehavior(var effectType: EnumParticleTypes, player: EntityPlayer) extends AbstractBehavior(player) {
- override def getNameHint = "particles." + effectType.getParticleName
+ class ParticleBehavior(var effectType: BasicParticleType, player: PlayerEntity) extends AbstractBehavior(player) {
+ override def getNameHint = "particles." + effectType.getRegistryName.getPath
override def update(): Unit = {
- val world = player.getEntityWorld
- if (world.isRemote && Settings.get.enableNanomachinePfx) {
+ val world = player.level
+ if (world.isClientSide && Settings.get.enableNanomachinePfx) {
PlayerUtils.spawnParticleAround(player, effectType, api.Nanomachines.getController(player).getInputCount(this) * 0.25)
}
}
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/PotionProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/PotionProvider.scala
index 548d1751b2..987c341541 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/PotionProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/PotionProvider.scala
@@ -5,12 +5,14 @@ import li.cil.oc.api
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.DisableReason
import li.cil.oc.api.prefab.AbstractBehavior
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.potion.Potion
-import net.minecraft.potion.PotionEffect
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.potion.Effect
+import net.minecraft.potion.EffectInstance
+import net.minecraft.util.ResourceLocation
+import net.minecraftforge.registries.ForgeRegistries
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object PotionProvider extends ScalaProvider("c29e4eec-5a46-479a-9b3d-ad0f06da784a") {
// Lazy to give other mods a chance to register their potions.
@@ -18,46 +20,47 @@ object PotionProvider extends ScalaProvider("c29e4eec-5a46-479a-9b3d-ad0f06da784
def filterPotions[T](list: Iterable[T]) = {
list.map {
- case name: String => Option(Potion.getPotionFromResourceLocation(name))
- case id: java.lang.Number => Option(Potion.getPotionById(id.intValue()))
+ case name: String => Option(ForgeRegistries.POTIONS.getValue(new ResourceLocation(name)))
+ case loc: ResourceLocation => Option(ForgeRegistries.POTIONS.getValue(loc))
+ case id: java.lang.Number => Option(Effect.byId(id.intValue()))
case _ => None
}.collect {
case Some(potion) => potion
}.toSet
}
- def isPotionEligible(potion: Potion) = potion != null && PotionWhitelist.contains(potion)
+ def isPotionEligible(potion: Effect) = potion != null && PotionWhitelist.contains(potion)
- override def createScalaBehaviors(player: EntityPlayer) = {
- Potion.REGISTRY.filter(isPotionEligible).map(new PotionBehavior(_, player))
+ override def createScalaBehaviors(player: PlayerEntity) = {
+ ForgeRegistries.POTIONS.getValues.filter(isPotionEligible).map(new PotionBehavior(_, player))
}
- override def writeBehaviorToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {
+ override def writeBehaviorToNBT(behavior: Behavior, nbt: CompoundNBT): Unit = {
behavior match {
case potionBehavior: PotionBehavior =>
- nbt.setString("potionId", Potion.REGISTRY.getNameForObject(potionBehavior.potion).toString)
+ nbt.putString("potionId", potionBehavior.potion.getRegistryName.toString)
case _ => // Shouldn't happen, ever.
}
}
- override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = {
+ override def readBehaviorFromNBT(player: PlayerEntity, nbt: CompoundNBT) = {
val potionId = nbt.getString("potionId")
- new PotionBehavior(Potion.getPotionFromResourceLocation(potionId), player)
+ new PotionBehavior(ForgeRegistries.POTIONS.getValue(new ResourceLocation(potionId)), player)
}
- class PotionBehavior(val potion: Potion, player: EntityPlayer) extends AbstractBehavior(player) {
+ class PotionBehavior(val potion: Effect, player: PlayerEntity) extends AbstractBehavior(player) {
final val Duration = 600
- def amplifier(player: EntityPlayer) = api.Nanomachines.getController(player).getInputCount(this) - 1
+ def amplifier(player: PlayerEntity) = api.Nanomachines.getController(player).getInputCount(this) - 1
- override def getNameHint: String = potion.getName.stripPrefix("potion.")
+ override def getNameHint: String = potion.getDescriptionId.stripPrefix("effect.")
override def onDisable(reason: DisableReason): Unit = {
- player.removePotionEffect(potion)
+ player.removeEffect(potion)
}
override def update(): Unit = {
- player.addPotionEffect(new PotionEffect(potion, Duration, amplifier(player), true, Settings.get.enableNanomachinePfx))
+ player.addEffect(new EffectInstance(potion, Duration, amplifier(player), true, Settings.get.enableNanomachinePfx))
}
}
diff --git a/src/main/scala/li/cil/oc/common/nanomachines/provider/ScalaProvider.scala b/src/main/scala/li/cil/oc/common/nanomachines/provider/ScalaProvider.scala
index 93285282a4..849b763b78 100644
--- a/src/main/scala/li/cil/oc/common/nanomachines/provider/ScalaProvider.scala
+++ b/src/main/scala/li/cil/oc/common/nanomachines/provider/ScalaProvider.scala
@@ -2,12 +2,13 @@ package li.cil.oc.common.nanomachines.provider
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.prefab.AbstractProvider
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
abstract class ScalaProvider(id: String) extends AbstractProvider(id) {
- def createScalaBehaviors(player: EntityPlayer): Iterable[Behavior]
+ def createScalaBehaviors(player: PlayerEntity): Iterable[Behavior]
- override def createBehaviors(player: EntityPlayer): java.lang.Iterable[Behavior] = asJavaIterable(createScalaBehaviors(player))
+ override def createBehaviors(player: PlayerEntity): java.lang.Iterable[Behavior] = asJavaIterable(createScalaBehaviors(player))
}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala
index a746a58d71..b5c1fc05df 100644
--- a/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala
@@ -3,38 +3,35 @@ package li.cil.oc.common.recipe
import li.cil.oc.util.Color
import li.cil.oc.util.ItemColorizer
import li.cil.oc.util.StackOption
-import net.minecraft.block.Block
-import net.minecraft.inventory.InventoryCrafting
+import net.minecraft.inventory.CraftingInventory
+import net.minecraft.item.crafting.SpecialRecipe
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
+import net.minecraft.util.IItemProvider
+import net.minecraft.util.ResourceLocation
import net.minecraft.world.World
/**
* @author asie, Vexatos
*/
-class ColorizeRecipe(target: Item, source: Array[Item] = null) extends ContainerItemAwareRecipe {
- def this(target: Block, source: Array[Item]) = this(Item.getItemFromBlock(target), source)
- def this(target: Block) = this(target, null)
+class ColorizeRecipe(id: ResourceLocation, target: IItemProvider) extends SpecialRecipe(id) {
+ val targetItem: Item = target.asItem()
- val targetItem: Item = target
- val sourceItems: Array[Item] = if (source != null) source else Array(targetItem)
-
- override def matches(crafting: InventoryCrafting, world: World): Boolean = {
- val stacks = (0 until crafting.getSizeInventory).flatMap(i => StackOption(crafting.getStackInSlot(i)))
- val targets = stacks.filter(stack => sourceItems.contains(stack.getItem) || stack.getItem == targetItem)
+ override def matches(crafting: CraftingInventory, world: World): Boolean = {
+ val stacks = (0 until crafting.getContainerSize).flatMap(i => StackOption(crafting.getItem(i)))
+ val targets = stacks.filter(stack => stack.getItem == targetItem)
val other = stacks.filterNot(targets.contains(_))
targets.size == 1 && other.nonEmpty && other.forall(Color.isDye)
}
- override def getCraftingResult(crafting: InventoryCrafting): ItemStack = {
+ override def assemble(crafting: CraftingInventory): ItemStack = {
var targetStack: ItemStack = ItemStack.EMPTY
val color = Array[Int](0, 0, 0)
var colorCount = 0
var maximum = 0
- (0 until crafting.getSizeInventory).flatMap(i => StackOption(crafting.getStackInSlot(i))).foreach { stack =>
- if (sourceItems.contains(stack.getItem)
- || stack.getItem == targetItem) {
+ (0 until crafting.getContainerSize).flatMap(i => StackOption(crafting.getItem(i))).foreach { stack =>
+ if (stack.getItem == targetItem) {
targetStack = stack.copy()
targetStack.setCount(1)
} else {
@@ -42,7 +39,7 @@ class ColorizeRecipe(target: Item, source: Array[Item] = null) extends Container
if (dye.isEmpty)
return ItemStack.EMPTY
- val itemColor = Color.byOreName(dye.get).getColorComponentValues
+ val itemColor = Color.byTag(dye.get).getTextureDiffuseColors
val red = (itemColor(0) * 255.0F).toInt
val green = (itemColor(1) * 255.0F).toInt
val blue = (itemColor(2) * 255.0F).toInt
@@ -68,8 +65,6 @@ class ColorizeRecipe(target: Item, source: Array[Item] = null) extends Container
color(2) = (color(2).toFloat + blue * 255.0F).toInt
colorCount = colorCount + 1
}
- } else if (sourceItems.contains(targetStack.getItem)) {
- targetStack = new ItemStack(targetItem, targetStack.getCount, targetStack.getItemDamage)
}
var red = color(0) / colorCount
@@ -84,7 +79,7 @@ class ColorizeRecipe(target: Item, source: Array[Item] = null) extends Container
targetStack
}
- override def getMinimumRecipeSize = 2
+ override def canCraftInDimensions(width: Int, height: Int): Boolean = width * height >= 2
- override def getRecipeOutput = ItemStack.EMPTY
+ override def getSerializer = RecipeSerializers.CRAFTING_COLORIZE
}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ContainerItemAwareRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ContainerItemAwareRecipe.scala
deleted file mode 100644
index 69f38488ba..0000000000
--- a/src/main/scala/li/cil/oc/common/recipe/ContainerItemAwareRecipe.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package li.cil.oc.common.recipe
-
-import net.minecraft.inventory.InventoryCrafting
-import net.minecraft.item.crafting.IRecipe
-import net.minecraftforge.common.ForgeHooks
-import net.minecraftforge.registries.IForgeRegistryEntry
-
-trait ContainerItemAwareRecipe extends IForgeRegistryEntry.Impl[IRecipe] with IRecipe {
- override def getRemainingItems(inv: InventoryCrafting) = ForgeHooks.defaultRecipeGetRemainingItems(inv)
-
- def getMinimumRecipeSize: Int
-
- override def canFit(width: Int, height: Int): Boolean = width * height >= getMinimumRecipeSize
-}
diff --git a/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala
index 7ec676235e..0486b98b49 100644
--- a/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala
@@ -3,31 +3,32 @@ package li.cil.oc.common.recipe
import li.cil.oc.util.ItemColorizer
import li.cil.oc.util.StackOption
import net.minecraft.block.Block
-import net.minecraft.init.Items
-import net.minecraft.inventory.InventoryCrafting
+import net.minecraft.inventory.CraftingInventory
+import net.minecraft.item.crafting.SpecialRecipe
import net.minecraft.item.Item
+import net.minecraft.item.Items
import net.minecraft.item.ItemStack
+import net.minecraft.util.IItemProvider
+import net.minecraft.util.ResourceLocation
import net.minecraft.world.World
/**
* @author Vexatos
*/
-class DecolorizeRecipe(target: Item) extends ContainerItemAwareRecipe {
- def this(target: Block) = this(Item.getItemFromBlock(target))
+class DecolorizeRecipe(id: ResourceLocation, target: IItemProvider) extends SpecialRecipe(id) {
+ val targetItem: Item = target.asItem()
- val targetItem: Item = target
-
- override def matches(crafting: InventoryCrafting, world: World): Boolean = {
- val stacks = (0 until crafting.getSizeInventory).flatMap(i => StackOption(crafting.getStackInSlot(i)))
+ override def matches(crafting: CraftingInventory, world: World): Boolean = {
+ val stacks = (0 until crafting.getContainerSize).flatMap(i => StackOption(crafting.getItem(i)))
val targets = stacks.filter(stack => stack.getItem == targetItem)
val other = stacks.filterNot(targets.contains)
targets.size == 1 && other.size == 1 && other.forall(_.getItem == Items.WATER_BUCKET)
}
- override def getCraftingResult(crafting: InventoryCrafting): ItemStack = {
+ override def assemble(crafting: CraftingInventory): ItemStack = {
var targetStack: ItemStack = ItemStack.EMPTY
- (0 until crafting.getSizeInventory).flatMap(i => StackOption(crafting.getStackInSlot(i))).foreach { stack =>
+ (0 until crafting.getContainerSize).flatMap(i => StackOption(crafting.getItem(i))).foreach { stack =>
if (stack.getItem == targetItem) {
targetStack = stack.copy()
targetStack.setCount(1)
@@ -42,7 +43,7 @@ class DecolorizeRecipe(target: Item) extends ContainerItemAwareRecipe {
targetStack
}
- override def getMinimumRecipeSize = 2
+ override def canCraftInDimensions(width: Int, height: Int): Boolean = width * height >= 2
- override def getRecipeOutput = ItemStack.EMPTY
+ override def getSerializer = RecipeSerializers.CRAFTING_DECOLORIZE
}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedFuzzyShapelessRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedFuzzyShapelessRecipe.scala
deleted file mode 100644
index 6232b9e577..0000000000
--- a/src/main/scala/li/cil/oc/common/recipe/ExtendedFuzzyShapelessRecipe.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package li.cil.oc.common.recipe
-
-import net.minecraft.inventory.InventoryCrafting
-import net.minecraft.item.ItemStack
-import net.minecraftforge.oredict.ShapelessOreRecipe
-
-import scala.collection.mutable.ListBuffer
-
-class ExtendedFuzzyShapelessRecipe(result: ItemStack, ingredients: AnyRef*) extends ExtendedShapelessOreRecipe(result, ingredients: _*) {
- override def matches(inv: net.minecraft.inventory.InventoryCrafting, world: net.minecraft.world.World): Boolean = {
- val requiredItems = ingredients.map(any => any.asInstanceOf[ItemStack]).toList.to[ListBuffer]
- //.groupBy{ case s: ItemStack => s.getItem }.mapValues(_.size).toSeq: _*)
- for (i <- 0 until inv.getSizeInventory) {
- val itemStack = inv.getStackInSlot(i)
- if (!itemStack.isEmpty) {
- val index = requiredItems.indexWhere(req => {
- if (req.getItem != itemStack.getItem) return false
- req.getItemDamage == itemStack.getItemDamage
- })
- if (index >= 0) {
- requiredItems.remove(index)
- }
- }
- }
- requiredItems.isEmpty
- }
-}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
index 46bec34d3f..328d760fb4 100644
--- a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
@@ -12,16 +12,18 @@ import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.item.data.TabletData
import li.cil.oc.server.machine.luac.LuaStateFactory
-import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.SideTracker
-import net.minecraft.init.Blocks
-import net.minecraft.inventory.InventoryCrafting
+import net.minecraft.block.Blocks
+import net.minecraft.inventory.CraftingInventory
+import net.minecraft.item.DyeColor
+import net.minecraft.item.Items
import net.minecraft.item.ItemStack
import net.minecraft.item.crafting.IRecipe
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tags.ItemTags
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.util.control.Breaks._
object ExtendedRecipe {
@@ -47,24 +49,18 @@ object ExtendedRecipe {
private lazy val robot = api.Items.get(Constants.BlockName.Robot)
private lazy val tablet = api.Items.get(Constants.ItemName.Tablet)
private lazy val print = api.Items.get(Constants.BlockName.Print)
- private lazy val disabled = {
- val stack = new ItemStack(Blocks.DIRT)
- val tag = new NBTTagCompound()
- tag.setNewCompoundTag("display", _.setNewTagList("Lore", "Autocrafting of this item is disabled to avoid exploits."))
- stack.setTagCompound(tag)
- stack
- }
+ private val beaconBlocks = ItemTags.bind("forge:beacon_base_blocks")
- def addNBTToResult(recipe: IRecipe, craftedStack: ItemStack, inventory: InventoryCrafting): ItemStack = {
+ def addNBTToResult(recipe: IRecipe[_], craftedStack: ItemStack, inventory: CraftingInventory): ItemStack = {
val craftedItemName = api.Items.get(craftedStack)
if (craftedItemName == navigationUpgrade) {
Option(api.Driver.driverFor(craftedStack)).foreach(driver =>
for (stack <- getItems(inventory)) {
- if (stack.getItem == net.minecraft.init.Items.FILLED_MAP) {
+ if (stack.getItem == Items.FILLED_MAP) {
// Store information of the map used for crafting in the result.
val nbt = driver.dataTag(craftedStack)
- nbt.setNewCompoundTag(Settings.namespace + "map", stack.writeToNBT)
+ nbt.setNewCompoundTag(Settings.namespace + "map", stack.save)
}
})
}
@@ -73,7 +69,7 @@ object ExtendedRecipe {
if (SideTracker.isServer) {
Option(api.Driver.driverFor(craftedStack)).foreach(driver => {
val nbt = driver.dataTag(craftedStack)
- nbt.setString(Settings.namespace + "tunnel", UUID.randomUUID().toString)
+ nbt.putString(Settings.namespace + "tunnel", UUID.randomUUID().toString)
})
}
}
@@ -83,32 +79,29 @@ object ExtendedRecipe {
}
if (craftedItemName == floppy || hdds.contains(craftedItemName)) {
- if (!craftedStack.hasTagCompound) {
- craftedStack.setTagCompound(new NBTTagCompound())
- }
- val nbt = craftedStack.getTagCompound
- if (recipe.canFit(1, 1)) {
+ val nbt = craftedStack.getOrCreateTag
+ if (recipe.canCraftInDimensions(1, 1)) {
// Formatting / loot to normal disk conversion, only keep coloring.
val colorKey = Settings.namespace + "color"
for (stack <- getItems(inventory)) {
- if (api.Items.get(stack) != null && (api.Items.get(stack) == floppy || api.Items.get(stack).name == "lootDisk") && stack.hasTagCompound) {
- val oldData = stack.getTagCompound
- if (oldData.hasKey(colorKey) && oldData.getInteger(colorKey) != Color.dyes.indexOf("lightGray")) {
- nbt.setTag(colorKey, oldData.getTag(colorKey).copy())
+ if (api.Items.get(stack) != null && (api.Items.get(stack) == floppy || api.Items.get(stack).name == "lootDisk") && stack.hasTag) {
+ val oldData = stack.getTag
+ if (oldData.contains(colorKey) && oldData.getInt(colorKey) != DyeColor.LIGHT_GRAY.getId) {
+ nbt.put(colorKey, oldData.get(colorKey).copy())
}
}
}
- if (nbt.hasNoTags) {
- craftedStack.setTagCompound(null)
+ if (nbt.isEmpty) {
+ craftedStack.setTag(null)
}
}
else if (getItems(inventory).forall(api.Items.get(_) == floppy)) {
// Copy operation.
for (stack <- getItems(inventory)) {
- if (api.Items.get(stack) == floppy && stack.hasTagCompound) {
- val oldData = stack.getTagCompound
- for (oldTagName <- oldData.getKeySet.map(_.asInstanceOf[String]) if !nbt.hasKey(oldTagName)) {
- nbt.setTag(oldTagName, oldData.getTag(oldTagName).copy())
+ if (api.Items.get(stack) == floppy && stack.hasTag) {
+ val oldData = stack.getTag
+ for (oldTagName <- oldData.getAllKeys.map(_.asInstanceOf[String]) if !nbt.contains(oldTagName)) {
+ nbt.put(oldTagName, oldData.get(oldTagName).copy())
}
}
}
@@ -116,43 +109,35 @@ object ExtendedRecipe {
}
if (craftedItemName == print &&
- recipe.isInstanceOf[ExtendedShapelessOreRecipe] &&
- recipe.asInstanceOf[ExtendedShapelessOreRecipe].getIngredients.size == 2) {
+ recipe.getIngredients.size == 2) {
// First, copy old data.
val data = new PrintData(craftedStack)
val inputs = getItems(inventory)
for (stack <- inputs) {
if (api.Items.get(stack) == print) {
- data.load(stack)
+ data.loadData(stack)
}
}
// Then apply new data.
- val beaconBlocks = Array(
- new ItemStack(net.minecraft.init.Blocks.IRON_BLOCK),
- new ItemStack(net.minecraft.init.Blocks.GOLD_BLOCK),
- new ItemStack(net.minecraft.init.Blocks.EMERALD_BLOCK),
- new ItemStack(net.minecraft.init.Blocks.DIAMOND_BLOCK)
- )
-
- val glowstoneDust = new ItemStack(net.minecraft.init.Items.GLOWSTONE_DUST)
- val glowstone = new ItemStack(net.minecraft.init.Blocks.GLOWSTONE)
+ val glowstoneDust = new ItemStack(Items.GLOWSTONE_DUST)
+ val glowstone = new ItemStack(Blocks.GLOWSTONE)
for (stack <- inputs) {
- if (beaconBlocks.exists(_.isItemEqual(stack))) {
+ if (stack.getItem.is(beaconBlocks)) {
if (data.isBeaconBase) {
// Crafting wouldn't change anything, prevent accidental resource loss.
return ItemStack.EMPTY
}
data.isBeaconBase = true
}
- if (glowstoneDust.isItemEqual(stack)) {
+ if (glowstoneDust.sameItem(stack)) {
if (data.lightLevel == 15) {
// Crafting wouldn't change anything, prevent accidental resource loss.
return ItemStack.EMPTY
}
data.lightLevel = math.min(15, data.lightLevel + 1)
}
- if (glowstone.isItemEqual(stack)) {
+ if (glowstone.sameItem(stack)) {
if (data.lightLevel == 15) {
// Crafting wouldn't change anything, prevent accidental resource loss.
return ItemStack.EMPTY
@@ -162,20 +147,19 @@ object ExtendedRecipe {
}
// Finally apply modified data.
- data.save(craftedStack)
+ data.saveData(craftedStack)
}
// EEPROM copying.
if (craftedItemName == eeprom &&
craftedStack.getCount == 2 &&
- recipe.isInstanceOf[ExtendedShapelessOreRecipe] &&
- recipe.asInstanceOf[ExtendedShapelessOreRecipe].getIngredients.size == 2) breakable {
+ recipe.getIngredients.size == 2) breakable {
for (stack <- getItems(inventory)) {
- if (api.Items.get(stack) == eeprom && stack.hasTagCompound) {
- val copy = stack.getTagCompound.copy.asInstanceOf[NBTTagCompound]
+ if (api.Items.get(stack) == eeprom && stack.hasTag) {
+ val copy = stack.getTag.copy.asInstanceOf[CompoundNBT]
// Erase node address, just in case.
- copy.getCompoundTag(Settings.namespace + "data").getCompoundTag("node").removeTag("address")
- craftedStack.setTagCompound(copy)
+ copy.getCompound(Settings.namespace + "data").getCompound("node").remove("address")
+ craftedStack.setTag(copy)
break()
}
}
@@ -190,9 +174,9 @@ object ExtendedRecipe {
craftedStack
}
- private def getItems(inventory: InventoryCrafting) = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot).filter(!_.isEmpty)
+ private def getItems(inventory: CraftingInventory) = (0 until inventory.getContainerSize).map(inventory.getItem).filter(!_.isEmpty)
- private def recraft(craftedStack: ItemStack, inventory: InventoryCrafting, descriptor: ItemInfo, dataFactory: (ItemStack) => ItemDataWrapper) {
+ private def recraft(craftedStack: ItemStack, inventory: CraftingInventory, descriptor: ItemInfo, dataFactory: (ItemStack) => ItemDataWrapper) {
if (api.Items.get(craftedStack) == descriptor) {
// Find old Microcontroller.
getItems(inventory).find(api.Items.get(_) == descriptor) match {
@@ -206,7 +190,7 @@ object ExtendedRecipe {
// Insert new EEPROM.
for (stack <- getItems(inventory)) {
if (api.Items.get(stack) == eeprom) {
- data.components :+= stack.copy.splitStack(1)
+ data.components :+= stack.copy.split(1)
}
}
@@ -231,7 +215,7 @@ object ExtendedRecipe {
override def components_=(value: Array[ItemStack]): Unit = data.components = value
- override def save(stack: ItemStack): Unit = data.save(stack)
+ override def save(stack: ItemStack): Unit = data.saveData(stack)
}
private class DroneDataWrapper(val stack: ItemStack) extends ItemDataWrapper {
@@ -241,7 +225,7 @@ object ExtendedRecipe {
override def components_=(value: Array[ItemStack]): Unit = data.components = value
- override def save(stack: ItemStack): Unit = data.save(stack)
+ override def save(stack: ItemStack): Unit = data.saveData(stack)
}
private class RobotDataWrapper(val stack: ItemStack) extends ItemDataWrapper {
@@ -251,7 +235,7 @@ object ExtendedRecipe {
override def components_=(value: Array[ItemStack]): Unit = data.components = value
- override def save(stack: ItemStack): Unit = data.save(stack)
+ override def save(stack: ItemStack): Unit = data.saveData(stack)
}
private class TabletDataWrapper(val stack: ItemStack) extends ItemDataWrapper {
@@ -261,7 +245,7 @@ object ExtendedRecipe {
override def save(stack: ItemStack): Unit = {
data.items = components.clone()
- data.save(stack)
+ data.saveData(stack)
}
}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedShapedOreRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedShapedOreRecipe.scala
deleted file mode 100644
index 0dc472b3e0..0000000000
--- a/src/main/scala/li/cil/oc/common/recipe/ExtendedShapedOreRecipe.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package li.cil.oc.common.recipe
-
-import net.minecraft.inventory.InventoryCrafting
-import net.minecraft.item.ItemStack
-import net.minecraft.util.ResourceLocation
-import net.minecraftforge.oredict.ShapedOreRecipe
-
-class ExtendedShapedOreRecipe(result: ItemStack, ingredients: AnyRef*) extends ShapedOreRecipe(null, result, ingredients: _*) {
- override def getCraftingResult(inventory: InventoryCrafting) =
- ExtendedRecipe.addNBTToResult(this, super.getCraftingResult(inventory), inventory)
-}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedShapedRecipe.java b/src/main/scala/li/cil/oc/common/recipe/ExtendedShapedRecipe.java
new file mode 100644
index 0000000000..cd0af03135
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/recipe/ExtendedShapedRecipe.java
@@ -0,0 +1,101 @@
+package li.cil.oc.common.recipe;
+
+import com.google.gson.JsonObject;
+import net.minecraft.inventory.CraftingInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.crafting.ICraftingRecipe;
+import net.minecraft.item.crafting.Ingredient;
+import net.minecraft.item.crafting.IRecipeSerializer;
+import net.minecraft.item.crafting.ShapedRecipe;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.NonNullList;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.World;
+import net.minecraftforge.common.crafting.IShapedRecipe;
+import net.minecraftforge.registries.ForgeRegistryEntry;
+
+public class ExtendedShapedRecipe implements ICraftingRecipe, IShapedRecipe {
+ private ShapedRecipe wrapped;
+
+ public ExtendedShapedRecipe(ShapedRecipe wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public boolean matches(CraftingInventory inv, World world) {
+ return wrapped.matches(inv, world);
+ }
+
+ @Override
+ public ItemStack assemble(CraftingInventory inv) {
+ return ExtendedRecipe.addNBTToResult(this, wrapped.assemble(inv), inv);
+ }
+
+ @Override
+ public boolean canCraftInDimensions(int w, int h) {
+ return wrapped.canCraftInDimensions(w, h);
+ }
+
+ @Override
+ public ItemStack getResultItem() {
+ return wrapped.getResultItem();
+ }
+
+ @Override
+ public NonNullList getRemainingItems(CraftingInventory inv) {
+ return wrapped.getRemainingItems(inv);
+ }
+
+ @Override
+ public NonNullList getIngredients() {
+ return wrapped.getIngredients();
+ }
+
+ @Override
+ public ResourceLocation getId() {
+ return wrapped.getId();
+ }
+
+ @Override
+ public IRecipeSerializer> getSerializer() {
+ return RecipeSerializers.CRAFTING_SHAPED_EXTENDED;
+ }
+
+ @Override
+ public String getGroup() {
+ return wrapped.getGroup();
+ }
+
+ @Override
+ public int getRecipeWidth() {
+ return wrapped.getRecipeWidth();
+ }
+
+ @Override
+ public int getRecipeHeight() {
+ return wrapped.getRecipeHeight();
+ }
+
+ public static final class Serializer extends ForgeRegistryEntry>
+ implements IRecipeSerializer {
+
+ @Override
+ public ExtendedShapedRecipe fromJson(ResourceLocation recipeId, JsonObject json) {
+ ShapedRecipe wrapped = IRecipeSerializer.SHAPED_RECIPE.fromJson(recipeId, json);
+ return new ExtendedShapedRecipe(wrapped);
+ }
+
+ @Override
+ public ExtendedShapedRecipe fromNetwork(ResourceLocation recipeId, PacketBuffer buff) {
+ ShapedRecipe wrapped = IRecipeSerializer.SHAPED_RECIPE.fromNetwork(recipeId, buff);
+ return new ExtendedShapedRecipe(wrapped);
+ }
+
+ @Override
+ public void toNetwork(PacketBuffer buff, ExtendedShapedRecipe recipe) {
+ IRecipeSerializer serializer =
+ (IRecipeSerializer) recipe.wrapped.getSerializer();
+ serializer.toNetwork(buff, recipe.wrapped);
+ }
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedShapelessOreRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedShapelessOreRecipe.scala
deleted file mode 100644
index 1c9c9ce6b2..0000000000
--- a/src/main/scala/li/cil/oc/common/recipe/ExtendedShapelessOreRecipe.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package li.cil.oc.common.recipe
-
-import net.minecraft.inventory.InventoryCrafting
-import net.minecraft.item.ItemStack
-import net.minecraftforge.oredict.ShapelessOreRecipe
-
-class ExtendedShapelessOreRecipe(result: ItemStack, ingredients: AnyRef*) extends ShapelessOreRecipe(null, result, ingredients: _*) {
- override def getCraftingResult(inventory: InventoryCrafting): ItemStack =
- ExtendedRecipe.addNBTToResult(this, super.getCraftingResult(inventory), inventory)
-}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedShapelessRecipe.java b/src/main/scala/li/cil/oc/common/recipe/ExtendedShapelessRecipe.java
new file mode 100644
index 0000000000..be68905ded
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/recipe/ExtendedShapelessRecipe.java
@@ -0,0 +1,90 @@
+package li.cil.oc.common.recipe;
+
+import com.google.gson.JsonObject;
+import net.minecraft.inventory.CraftingInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.crafting.ICraftingRecipe;
+import net.minecraft.item.crafting.Ingredient;
+import net.minecraft.item.crafting.IRecipeSerializer;
+import net.minecraft.item.crafting.ShapelessRecipe;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.NonNullList;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.World;
+import net.minecraftforge.registries.ForgeRegistryEntry;
+
+public class ExtendedShapelessRecipe implements ICraftingRecipe {
+ private ShapelessRecipe wrapped;
+
+ public ExtendedShapelessRecipe(ShapelessRecipe wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public boolean matches(CraftingInventory inv, World world) {
+ return wrapped.matches(inv, world);
+ }
+
+ @Override
+ public ItemStack assemble(CraftingInventory inv) {
+ return ExtendedRecipe.addNBTToResult(this, wrapped.assemble(inv), inv);
+ }
+
+ @Override
+ public boolean canCraftInDimensions(int w, int h) {
+ return wrapped.canCraftInDimensions(w, h);
+ }
+
+ @Override
+ public ItemStack getResultItem() {
+ return wrapped.getResultItem();
+ }
+
+ @Override
+ public NonNullList getRemainingItems(CraftingInventory inv) {
+ return wrapped.getRemainingItems(inv);
+ }
+
+ @Override
+ public NonNullList getIngredients() {
+ return wrapped.getIngredients();
+ }
+
+ @Override
+ public ResourceLocation getId() {
+ return wrapped.getId();
+ }
+
+ @Override
+ public IRecipeSerializer> getSerializer() {
+ return RecipeSerializers.CRAFTING_SHAPELESS_EXTENDED;
+ }
+
+ @Override
+ public String getGroup() {
+ return wrapped.getGroup();
+ }
+
+ public static final class Serializer extends ForgeRegistryEntry>
+ implements IRecipeSerializer {
+
+ @Override
+ public ExtendedShapelessRecipe fromJson(ResourceLocation recipeId, JsonObject json) {
+ ShapelessRecipe wrapped = IRecipeSerializer.SHAPELESS_RECIPE.fromJson(recipeId, json);
+ return new ExtendedShapelessRecipe(wrapped);
+ }
+
+ @Override
+ public ExtendedShapelessRecipe fromNetwork(ResourceLocation recipeId, PacketBuffer buff) {
+ ShapelessRecipe wrapped = IRecipeSerializer.SHAPELESS_RECIPE.fromNetwork(recipeId, buff);
+ return new ExtendedShapelessRecipe(wrapped);
+ }
+
+ @Override
+ public void toNetwork(PacketBuffer buff, ExtendedShapelessRecipe recipe) {
+ IRecipeSerializer serializer =
+ (IRecipeSerializer) recipe.wrapped.getSerializer();
+ serializer.toNetwork(buff, recipe.wrapped);
+ }
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ItemSpecialSerializer.java b/src/main/scala/li/cil/oc/common/recipe/ItemSpecialSerializer.java
new file mode 100644
index 0000000000..ec4e1335b6
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/recipe/ItemSpecialSerializer.java
@@ -0,0 +1,47 @@
+package li.cil.oc.common.recipe;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import net.minecraft.item.Item;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.item.crafting.IRecipeSerializer;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.IItemProvider;
+import net.minecraft.util.JSONUtils;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.registries.ForgeRegistries;
+import net.minecraftforge.registries.ForgeRegistryEntry;
+
+public class ItemSpecialSerializer> extends ForgeRegistryEntry>
+ implements IRecipeSerializer {
+
+ private BiFunction ctor;
+ private Function getter;
+
+ public ItemSpecialSerializer(BiFunction ctor, Function getter) {
+ this.ctor = ctor;
+ this.getter = getter;
+ }
+
+ @Override
+ public T fromJson(ResourceLocation recipeId, JsonObject json) {
+ ResourceLocation loc = new ResourceLocation(JSONUtils.getAsString(json, "item"));
+ if (!ForgeRegistries.ITEMS.containsKey(loc)) {
+ throw new JsonSyntaxException("Unknown item '" + loc + "'");
+ }
+ return ctor.apply(recipeId, ForgeRegistries.ITEMS.getValue(loc));
+ }
+
+ @Override
+ public T fromNetwork(ResourceLocation recipeId, PacketBuffer buff) {
+ return ctor.apply(recipeId, buff.readRegistryIdUnsafe(ForgeRegistries.ITEMS));
+ }
+
+ @Override
+ public void toNetwork(PacketBuffer buff, T recipe) {
+ buff.writeRegistryIdUnsafe(ForgeRegistries.ITEMS, getter.apply(recipe));
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/recipe/LootDiskCyclingRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/LootDiskCyclingRecipe.scala
index 2743649551..0116ac06a0 100644
--- a/src/main/scala/li/cil/oc/common/recipe/LootDiskCyclingRecipe.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/LootDiskCyclingRecipe.scala
@@ -1,25 +1,33 @@
package li.cil.oc.common.recipe
+import li.cil.oc.Constants
import li.cil.oc.Settings
+import li.cil.oc.api
import li.cil.oc.common.Loot
import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.StackOption
-import net.minecraft.inventory.InventoryCrafting
+import net.minecraft.inventory.CraftingInventory
import net.minecraft.item.ItemStack
-import net.minecraft.item.crafting.IRecipe
+import net.minecraft.item.crafting.Ingredient
+import net.minecraft.item.crafting.ICraftingRecipe
import net.minecraft.util.NonNullList
+import net.minecraft.util.ResourceLocation
import net.minecraft.world.World
-import net.minecraftforge.registries.IForgeRegistryEntry
+import scala.collection.JavaConverters
import scala.collection.immutable
-class LootDiskCyclingRecipe extends IForgeRegistryEntry.Impl[IRecipe] with IRecipe {
- override def matches(crafting: InventoryCrafting, world: World): Boolean = {
+class LootDiskCyclingRecipe(val getId: ResourceLocation) extends ICraftingRecipe {
+ val ingredients = NonNullList.create[Ingredient]
+ ingredients.add(Ingredient.of(Loot.disksForCycling.toArray: _*))
+ ingredients.add(Ingredient.of(api.Items.get(Constants.ItemName.Wrench).createItemStack(1)))
+
+ override def matches(crafting: CraftingInventory, world: World): Boolean = {
val stacks = collectStacks(crafting).toArray
stacks.length == 2 && stacks.exists(Loot.isLootDisk) && stacks.exists(Wrench.isWrench)
}
- override def getCraftingResult(crafting: InventoryCrafting): ItemStack = {
+ override def assemble(crafting: CraftingInventory): ItemStack = {
val lootDiskStacks = Loot.disksForCycling
collectStacks(crafting).find(Loot.isLootDisk) match {
case Some(lootDisk) if lootDiskStacks.nonEmpty =>
@@ -31,18 +39,21 @@ class LootDiskCyclingRecipe extends IForgeRegistryEntry.Impl[IRecipe] with IReci
}
}
- def getLootFactoryName(stack: ItemStack): String = stack.getTagCompound.getString(Settings.namespace + "lootFactory")
+ def getLootFactoryName(stack: ItemStack): String = stack.getTag.getString(Settings.namespace + "lootFactory")
- def collectStacks(crafting: InventoryCrafting): immutable.IndexedSeq[ItemStack] = (0 until crafting.getSizeInventory).flatMap(i => StackOption(crafting.getStackInSlot(i)))
+ def collectStacks(crafting: CraftingInventory): immutable.IndexedSeq[ItemStack] = (0 until crafting.getContainerSize).flatMap(i => StackOption(crafting.getItem(i)))
- override def canFit(width: Int, height: Int): Boolean = width * height >= 2
+ override def canCraftInDimensions(width: Int, height: Int): Boolean = width * height >= 2
- override def getRecipeOutput: ItemStack = ItemStack.EMPTY
+ override def getResultItem = Loot.disksForCycling.headOption match {
+ case Some(lootDisk) => lootDisk
+ case _ => ItemStack.EMPTY
+ }
- override def getRemainingItems(crafting: InventoryCrafting): NonNullList[ItemStack] = {
- val result = NonNullList.withSize[ItemStack](crafting.getSizeInventory, ItemStack.EMPTY)
- for (slot <- 0 until crafting.getSizeInventory) {
- val stack = crafting.getStackInSlot(slot)
+ override def getRemainingItems(crafting: CraftingInventory): NonNullList[ItemStack] = {
+ val result = NonNullList.withSize[ItemStack](crafting.getContainerSize, ItemStack.EMPTY)
+ for (slot <- 0 until crafting.getContainerSize) {
+ val stack = crafting.getItem(slot)
if (Wrench.isWrench(stack)) {
result.set(slot, stack.copy())
stack.setCount(0)
@@ -50,4 +61,8 @@ class LootDiskCyclingRecipe extends IForgeRegistryEntry.Impl[IRecipe] with IReci
}
result
}
+
+ override def getIngredients = ingredients
+
+ override def getSerializer = RecipeSerializers.CRAFTING_LOOTDISK_CYCLING
}
diff --git a/src/main/scala/li/cil/oc/common/recipe/RecipeSerializers.java b/src/main/scala/li/cil/oc/common/recipe/RecipeSerializers.java
new file mode 100644
index 0000000000..24d5c7f666
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/recipe/RecipeSerializers.java
@@ -0,0 +1,40 @@
+package li.cil.oc.common.recipe;
+
+import li.cil.oc.OpenComputers;
+import net.minecraft.item.crafting.IRecipeSerializer;
+import net.minecraft.item.crafting.SpecialRecipeSerializer;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.event.RegistryEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.registries.IForgeRegistry;
+import net.minecraftforge.registries.IForgeRegistryEntry;
+import net.minecraftforge.registries.ObjectHolder;
+
+@ObjectHolder("opencomputers")
+public class RecipeSerializers {
+ public static final IRecipeSerializer> CRAFTING_LOOTDISK_CYCLING = null;
+ public static final IRecipeSerializer> CRAFTING_COLORIZE = null;
+ public static final IRecipeSerializer> CRAFTING_DECOLORIZE = null;
+ public static final IRecipeSerializer> CRAFTING_SHAPED_EXTENDED = null;
+ public static final IRecipeSerializer> CRAFTING_SHAPELESS_EXTENDED = null;
+
+ @SubscribeEvent
+ public static void registerSerializers(RegistryEvent.Register> e) {
+ register(e.getRegistry(), "crafting_lootdisk_cycling", new SpecialRecipeSerializer<>(LootDiskCyclingRecipe::new));
+ register(e.getRegistry(), "crafting_colorize", new ItemSpecialSerializer<>(ColorizeRecipe::new, ColorizeRecipe::targetItem));
+ register(e.getRegistry(), "crafting_decolorize", new ItemSpecialSerializer<>(DecolorizeRecipe::new, DecolorizeRecipe::targetItem));
+ register(e.getRegistry(), "crafting_shaped_extended", new ExtendedShapedRecipe.Serializer());
+ register(e.getRegistry(), "crafting_shapeless_extended", new ExtendedShapelessRecipe.Serializer());
+ }
+
+ private static > & IRecipeSerializer>>
+ void register(IForgeRegistry> registry, String name, S serializer) {
+
+ serializer.setRegistryName(new ResourceLocation(OpenComputers.ID(), name));
+ registry.register(serializer);
+ }
+
+ private RecipeSerializers() {
+ throw new Error();
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/recipe/Recipes.scala b/src/main/scala/li/cil/oc/common/recipe/Recipes.scala
deleted file mode 100644
index 93589d601b..0000000000
--- a/src/main/scala/li/cil/oc/common/recipe/Recipes.scala
+++ /dev/null
@@ -1,516 +0,0 @@
-package li.cil.oc.common.recipe
-
-import java.io.File
-import java.io.FileReader
-
-import com.typesafe.config._
-import li.cil.oc._
-import li.cil.oc.common.Loot
-import li.cil.oc.common.block.SimpleBlock
-import li.cil.oc.common.init.Items
-import li.cil.oc.common.item.Delegator
-import li.cil.oc.common.item.data.PrintData
-import li.cil.oc.common.item.traits.Delegate
-import li.cil.oc.common.item.traits.SimpleItem
-import li.cil.oc.integration.util.ItemBlacklist
-import li.cil.oc.util.Color
-import net.minecraft.block.Block
-import net.minecraft.item.Item
-import net.minecraft.item.ItemBlock
-import net.minecraft.item.ItemStack
-import net.minecraft.item.crafting.IRecipe
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.ResourceLocation
-import net.minecraft.util.registry.RegistryNamespaced
-import net.minecraftforge.fluids.FluidRegistry
-import net.minecraftforge.fluids.FluidStack
-import net.minecraftforge.fml.common.Loader
-import net.minecraftforge.fml.common.registry.GameRegistry
-import net.minecraftforge.oredict.OreDictionary
-import net.minecraftforge.oredict.RecipeSorter
-import net.minecraftforge.oredict.RecipeSorter.Category
-import net.minecraftforge.registries.{GameData, IForgeRegistryEntry}
-import org.apache.commons.io.FileUtils
-
-import scala.collection.convert.WrapAsScala._
-import scala.collection.mutable
-
-object Recipes {
- val list: mutable.LinkedHashMap[ItemStack, String] = mutable.LinkedHashMap.empty[ItemStack, String]
- val oreDictEntries: mutable.LinkedHashMap[String, ItemStack] = mutable.LinkedHashMap.empty[String, ItemStack]
- var hadErrors = false
- val recipeHandlers: mutable.LinkedHashMap[String, (ItemStack, Config) => Unit] = mutable.LinkedHashMap.empty[String, (ItemStack, Config) => Unit]
-
- def registerRecipeHandler(name: String, recipe: (ItemStack, Config) => Unit): Unit = {
- recipeHandlers += name -> recipe
- }
-
- def addBlock(instance: Block, name: String, oreDict: String*): Block = {
- Items.registerBlock(instance, name)
- addRecipe(new ItemStack(instance), name)
- register(instance match {
- case simple: SimpleBlock => simple.createItemStack()
- case _ => new ItemStack(instance)
- }, oreDict: _*)
- instance
- }
-
- def addSubItem[T <: Delegate](delegate: T, name: String, oreDict: String*): T = {
- Items.registerItem(delegate, name)
- addRecipe(delegate.createItemStack(), name)
- register(delegate.createItemStack(), oreDict: _*)
- delegate
- }
-
- def addItem(instance: Item, name: String, oreDict: String*): Item = {
- Items.registerItem(instance, name)
- addRecipe(new ItemStack(instance), name)
- register(instance match {
- case simple: SimpleItem => simple.createItemStack()
- case _ => new ItemStack(instance)
- }, oreDict: _*)
- instance
- }
-
- def addSubItem[T <: common.item.traits.Delegate](delegate: T, name: String, registerRecipe: Boolean, oreDict: String*): T = {
- Items.registerItem(delegate, name)
- if (registerRecipe) {
- addRecipe(delegate.createItemStack(), name)
- register(delegate.createItemStack(), oreDict: _*)
- }
- else {
- ItemBlacklist.hide(delegate)
- }
- delegate
- }
-
- def addStack(stack: ItemStack, name: String, oreDict: String*): ItemStack = {
- Items.registerStack(stack, name)
- addRecipe(stack, name)
- register(stack, oreDict: _*)
- stack
- }
-
- def addRecipe(stack: ItemStack, name: String) {
- list += stack -> name
- }
-
- private def register(item: ItemStack, names: String*) {
- for (name <- names if name != null) {
- oreDictEntries += name -> item
- }
- }
-
- def init() {
- RecipeSorter.register(Settings.namespace + "extshaped", classOf[ExtendedShapedOreRecipe], Category.SHAPED, "after:forge:shapedore")
- RecipeSorter.register(Settings.namespace + "extshapeless", classOf[ExtendedShapelessOreRecipe], Category.SHAPELESS, "after:forge:shapelessore")
- RecipeSorter.register(Settings.namespace + "colorizer", classOf[ColorizeRecipe], Category.SHAPELESS, "after:forge:shapelessore")
- RecipeSorter.register(Settings.namespace + "decolorizer", classOf[DecolorizeRecipe], Category.SHAPELESS, "after:oc:colorizer")
- RecipeSorter.register(Settings.namespace + "lootcycler", classOf[LootDiskCyclingRecipe], Category.SHAPELESS, "after:forge:shapelessore")
-
- for ((name, stack) <- oreDictEntries) {
- if (!OreDictionary.getOres(name).contains(stack)) {
- OreDictionary.registerOre(name, stack)
- }
- }
- oreDictEntries.clear()
-
- try {
- val recipeSets = Array("default", "hardmode", "gregtech", "peaceful")
- val recipeDirectory = new File(Loader.instance.getConfigDir + File.separator + "opencomputers")
- val userRecipes = new File(recipeDirectory, "user.recipes")
- userRecipes.getParentFile.mkdirs()
- if (!userRecipes.exists()) {
- FileUtils.copyURLToFile(getClass.getResource("/assets/opencomputers/recipes/user.recipes"), userRecipes)
- }
- for (recipeSet <- recipeSets) {
- FileUtils.copyURLToFile(getClass.getResource(s"/assets/opencomputers/recipes/$recipeSet.recipes"), new File(recipeDirectory, s"$recipeSet.recipes"))
- }
- lazy val config: ConfigParseOptions = ConfigParseOptions.defaults.
- setSyntax(ConfigSyntax.CONF).
- setIncluder(new ConfigIncluder with ConfigIncluderFile {
- var fallback: ConfigIncluder = _
-
- override def withFallback(fallback: ConfigIncluder): ConfigIncluder = {
- this.fallback = fallback
- this
- }
-
- override def include(context: ConfigIncludeContext, what: String): ConfigObject = fallback.include(context, what)
-
- override def includeFile(context: ConfigIncludeContext, what: File): ConfigObject = {
- val in = if (what.isAbsolute) new FileReader(what) else new FileReader(new File(userRecipes.getParentFile, what.getPath))
- val result = ConfigFactory.parseReader(in, config)
- in.close()
- result.root()
- }
- })
- val recipes = ConfigFactory.parseFile(userRecipes, config)
-
- // Register all known recipes.
- for ((stack, name) <- list) {
- if (recipes.hasPath(name)) {
- val value = recipes.getValue(name)
- value.valueType match {
- case ConfigValueType.OBJECT =>
- addRecipe(stack, recipes.getConfig(name), s"'$name'")
- case ConfigValueType.BOOLEAN =>
- // Explicitly disabled, keep in NEI if true.
- if (!value.unwrapped.asInstanceOf[Boolean]) {
- hide(stack)
- }
- case _ =>
- OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item. The error was: Invalid value for recipe.")
- hadErrors = true
- }
- }
- else {
- OpenComputers.log.warn(s"No recipe for '$name', you will not be able to craft this item. To suppress this warning, disable the recipe (assign `false` to it).")
- hadErrors = true
- }
- }
-
- // Register all unknown recipes. Well. Loot disk recipes.
- if (recipes.hasPath("lootdisks")) try {
- val lootRecipes = recipes.getConfigList("lootdisks")
- val lootStacks = Loot.globalDisks.map(_._1)
- for (recipe <- lootRecipes) {
- val name = recipe.getString("name")
- lootStacks.find(s => s.getTagCompound.getString(Settings.namespace + "lootFactory") == name) match {
- case Some(stack) => addRecipe(stack, recipe, s"loot disk '$name'")
- case _ =>
- OpenComputers.log.warn(s"Failed adding recipe for loot disk '$name': No such global loot disk.")
- hadErrors = true
- }
- }
- }
- catch {
- case t: Throwable =>
- OpenComputers.log.warn("Failed parsing loot disk recipes.", t)
- hadErrors = true
- }
-
- if (recipes.hasPath("generic")) try {
- val genericRecipes = recipes.getConfigList("generic")
- for (recipe <- genericRecipes) {
- val result = recipe.getValue("result").unwrapped()
- parseIngredient(result) match {
- case stack: ItemStack => addRecipe(stack, recipe, s"'$result'")
- case _ =>
- OpenComputers.log.warn(s"Failed adding generic recipe for '$result': Invalid output (make sure it's not an OreDictionary name).")
- hadErrors = true
- }
- }
- }
- catch {
- case t: Throwable =>
- OpenComputers.log.warn("Failed parsing generic recipes.", t)
- hadErrors = true
- }
-
- // Recrafting operations.
- val cable = api.Items.get(Constants.BlockName.Cable)
- val chamelium = api.Items.get(Constants.ItemName.Chamelium)
- val chameliumBlock = api.Items.get(Constants.BlockName.ChameliumBlock)
- val drone = api.Items.get(Constants.ItemName.Drone)
- val eeprom = api.Items.get(Constants.ItemName.EEPROM)
- val floppy = api.Items.get(Constants.ItemName.Floppy)
- val hoverBoots = api.Items.get(Constants.ItemName.HoverBoots)
- val mcu = api.Items.get(Constants.BlockName.Microcontroller)
- val navigationUpgrade = api.Items.get(Constants.ItemName.NavigationUpgrade)
- val print = api.Items.get(Constants.BlockName.Print)
- val relay = api.Items.get(Constants.BlockName.Relay)
- val robot = api.Items.get(Constants.BlockName.Robot)
- val tablet = api.Items.get(Constants.ItemName.Tablet)
- val linkedCard = api.Items.get(Constants.ItemName.LinkedCard)
-
- // Navigation upgrade recrafting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- navigationUpgrade.createItemStack(1),
- navigationUpgrade.createItemStack(1), new ItemStack(net.minecraft.init.Items.FILLED_MAP, 1, OreDictionary.WILDCARD_VALUE)))
-
- // Floppy disk coloring.
- for (dye <- Color.dyes) {
- val result = floppy.createItemStack(1)
- val tag = new NBTTagCompound()
- tag.setInteger(Settings.namespace + "color", Color.dyes.indexOf(dye))
- result.setTagCompound(tag)
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(result, floppy.createItemStack(1), dye))
- }
-
- // Microcontroller recrafting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- mcu.createItemStack(1),
- mcu.createItemStack(1), eeprom.createItemStack(1)))
-
- // Drone recrafting.
- Recipes.addRecipe(new ExtendedFuzzyShapelessRecipe(
- drone.createItemStack(1),
- drone.createItemStack(1), eeprom.createItemStack(1)))
-
- // EEPROM copying via crafting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- eeprom.createItemStack(2),
- eeprom.createItemStack(1), eeprom.createItemStack(1)))
-
- // Robot recrafting.
- Recipes.addRecipe(new ExtendedFuzzyShapelessRecipe(
- robot.createItemStack(1),
- robot.createItemStack(1), eeprom.createItemStack(1)))
-
- // Tablet recrafting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- tablet.createItemStack(1),
- tablet.createItemStack(1), eeprom.createItemStack(1)))
-
- // Chamelium block splitting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- chamelium.createItemStack(9),
- chameliumBlock.createItemStack(1)))
-
- // Chamelium dying.
- for ((dye, meta) <- Color.dyes.zipWithIndex) {
- val result = chameliumBlock.createItemStack(1)
- result.setItemDamage(meta)
- val input = chameliumBlock.createItemStack(1)
- input.setItemDamage(OreDictionary.WILDCARD_VALUE)
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- result,
- input, dye))
- }
-
- // Print beaconification.
- val beaconPrint = print.createItemStack(1)
-
- {
- val printData = new PrintData(beaconPrint)
- printData.isBeaconBase = true
- printData.save(beaconPrint)
- }
-
- for (block <- Array(
- net.minecraft.init.Blocks.IRON_BLOCK,
- net.minecraft.init.Blocks.GOLD_BLOCK,
- net.minecraft.init.Blocks.EMERALD_BLOCK,
- net.minecraft.init.Blocks.DIAMOND_BLOCK
- )) {
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- beaconPrint,
- print.createItemStack(1), new ItemStack(block)))
- }
-
- // Floppy disk formatting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(floppy.createItemStack(1), floppy.createItemStack(1)))
-
- // Hard disk formatting.
- val hdds = Array(
- api.Items.get(Constants.ItemName.HDDTier1),
- api.Items.get(Constants.ItemName.HDDTier2),
- api.Items.get(Constants.ItemName.HDDTier3)
- )
- for (hdd <- hdds) {
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(hdd.createItemStack(1), hdd.createItemStack(1)))
- }
-
- // EEPROM formatting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(eeprom.createItemStack(1), eeprom.createItemStack(1)))
-
- // Print light value increments.
- val lightPrint = print.createItemStack(1)
-
- {
- val printData = new PrintData(lightPrint)
- printData.lightLevel = 1
- printData.save(lightPrint)
- }
-
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- lightPrint,
- print.createItemStack(1), new ItemStack(net.minecraft.init.Items.GLOWSTONE_DUST)))
-
- {
- val printData = new PrintData(lightPrint)
- printData.lightLevel = 4
- printData.save(lightPrint)
- }
-
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- lightPrint,
- print.createItemStack(1), new ItemStack(net.minecraft.init.Blocks.GLOWSTONE)))
-
- // Hover Boot dyeing
- Recipes.addRecipe(new ColorizeRecipe(hoverBoots.item()), "colorizeBoots")
- Recipes.addRecipe(new DecolorizeRecipe(hoverBoots.item()), "decolorizeBoots")
-
- // Cable dyeing
- Recipes.addRecipe(new ColorizeRecipe(cable.block()), "colorizeCable")
- Recipes.addRecipe(new DecolorizeRecipe(cable.block()), "decolorizeCable")
-
- // Loot disk cycling.
- if (Settings.get.lootRecrafting) {
- Recipes.addRecipe(new LootDiskCyclingRecipe(), "lootCycling")
- }
-
- // link card copying via crafting.
- Recipes.addRecipe(new ExtendedShapelessOreRecipe(
- linkedCard.createItemStack(2),
- linkedCard.createItemStack(1), linkedCard.createItemStack(1)))
-
- }
- catch {
- case e: Throwable => OpenComputers.log.error("Error parsing recipes, you may not be able to craft any items from this mod!", e)
- }
- list.clear()
- }
-
- private def addRecipe(output: ItemStack, recipe: Config, name: String) = try {
- val recipeType = tryGetType(recipe)
- recipeHandlers.get(recipeType) match {
- case Some(recipeHandler) => recipeHandler(output, recipe)
- case _ =>
- OpenComputers.log.error(s"Failed adding recipe for $name, you will not be able to craft this item. The error was: Invalid recipe type '$recipeType'.")
- hadErrors = true
- }
- }
- catch {
- case e: RecipeException =>
- OpenComputers.log.error(s"Failed adding recipe for $name, you will not be able to craft this item.", e)
- hadErrors = true
- }
-
- def tryGetCount(recipe: Config): Int = if (recipe.hasPath("output")) recipe.getInt("output") else 1
-
- def parseIngredient(entry: AnyRef): AnyRef = entry match {
- case map: java.util.Map[AnyRef, AnyRef]@unchecked =>
- if (map.contains("oreDict")) {
- map.get("oreDict") match {
- case value: String => value
- case other => throw new RecipeException(s"Invalid name in recipe (not a string: $other).")
- }
- }
- else if (map.contains("item")) {
- map.get("item") match {
- case name: String =>
- findItem(name) match {
- case Some(item: Item) => new ItemStack(item, 1, tryGetId(map))
- case _ => throw new RecipeException(s"No item found with name '$name'.")
- }
- case id: Number => new ItemStack(validateItemId(id), 1, tryGetId(map))
- case other => throw new RecipeException(s"Invalid item name in recipe (not a string: $other).")
- }
- }
- else if (map.contains("block")) {
- map.get("block") match {
- case name: String =>
- findBlock(name) match {
- case Some(block: Block) => new ItemStack(block, 1, tryGetId(map))
- case _ => throw new RecipeException(s"No block found with name '$name'.")
- }
- case id: Number => new ItemStack(validateBlockId(id), 1, tryGetId(map))
- case other => throw new RecipeException(s"Invalid block name (not a string: $other).")
- }
- }
- else throw new RecipeException("Invalid ingredient type (no oreDict, item or block entry).")
- case name: String =>
- if (name == null || name.trim.isEmpty) ItemStack.EMPTY
- else if (OreDictionary.getOres(name) != null && !OreDictionary.getOres(name).isEmpty) name
- else {
- findItem(name) match {
- case Some(item: Item) => new ItemStack(item, 1, 0)
- case _ =>
- findBlock(name) match {
- case Some(block: Block) => new ItemStack(block, 1, 0)
- case _ => throw new RecipeException(s"No ore dictionary entry, item or block found for ingredient with name '$name'.")
- }
- }
- }
- case other => throw new RecipeException(s"Invalid ingredient type (not a map or string): $other")
- }
-
- def parseFluidIngredient(entry: Config): Option[FluidStack] = {
- val fluid = FluidRegistry.getFluid(entry.getString("name"))
- val amount =
- if (entry.hasPath("amount")) entry.getInt("amount")
- else 1000
- Option(new FluidStack(fluid, amount))
- }
-
- private def findItem(name: String) = getObjectWithoutFallback(Item.REGISTRY, name).orElse(Item.REGISTRY.find {
- case item: Item => item.getUnlocalizedName == name || item.getUnlocalizedName == "item." + name || Item.REGISTRY.getNameForObject(item).toString == name
- case _ => false
- })
-
- private def findBlock(name: String) = getObjectWithoutFallback(Block.REGISTRY.asInstanceOf[RegistryNamespaced[ResourceLocation, Block]], name).orElse(Block.REGISTRY.find {
- case block: Block => block.getUnlocalizedName == name || block.getUnlocalizedName == "tile." + name || Block.REGISTRY.getNameForObject(block).toString == name
- case _ => false
- })
-
- private def getObjectWithoutFallback[V](registry: RegistryNamespaced[ResourceLocation, V], key: String) = {
- val loc = new ResourceLocation(key)
- if (registry.containsKey(loc)) Option(registry.getObject(loc))
- else None
- }
-
- private def tryGetType(recipe: Config) = if (recipe.hasPath("type")) recipe.getString("type") else "shaped"
-
- private def tryGetId(ingredient: java.util.Map[AnyRef, AnyRef]): Int =
- if (ingredient.contains("subID")) ingredient.get("subID") match {
- case id: Number => id.intValue
- case "any" => OreDictionary.WILDCARD_VALUE
- case id: String => Integer.valueOf(id)
- case _ => 0
- } else 0
-
- private def validateBlockId(id: Number) = {
- val index = id.intValue
- val block = Block.getBlockById(index)
- if (block == null) throw new RecipeException(s"Invalid block ID: $index")
- block
- }
-
- private def validateItemId(id: Number) = {
- val index = id.intValue
- val item = Item.getItemById(index)
- if (item == null) throw new RecipeException(s"Invalid item ID: $index")
- item
- }
-
- private def hide(value: ItemStack) {
- Delegator.subItem(value) match {
- case Some(stack) =>
- stack.showInItemList = false
- case _ =>
- }
- value.getItem match {
- case simple: SimpleItem =>
- simple.setCreativeTab(null)
- case _ =>
- }
- value.getItem match {
- case itemBlock: ItemBlock => itemBlock.getBlock match {
- case simple: SimpleBlock =>
- simple.setCreativeTab(null)
- ItemBlacklist.hide(simple)
- case _ =>
- }
- case _ =>
- }
- }
-
- class RecipeException(message: String) extends RuntimeException(message)
-
- def addRecipe(recipe: IForgeRegistryEntry.Impl[IRecipe], group: String): IRecipe = GameData.register_impl(recipe.setRegistryName(Settings.resourceDomain, group))
-
- private var recipeCounter: Int = 0
-
- def addRecipe(recipe: IForgeRegistryEntry.Impl[IRecipe]): Unit = recipe match {
- case r: IRecipe => r.getRecipeOutput match {
- case stack: ItemStack if !stack.isEmpty =>
- // Who cares about recipe names?
- addRecipe(recipe, stack.getItem.getRegistryName.getResourcePath + recipeCounter.toString)
- recipeCounter += 1
- case _ => throw new IllegalArgumentException("invalid recipe name: " + r.getRecipeOutput)
- }
- case _ => throw new IllegalArgumentException("invalid recipe name: " + recipe)
- }
-}
diff --git a/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala b/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala
index 6928527b22..6b0e0b2d9b 100644
--- a/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala
+++ b/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala
@@ -12,7 +12,7 @@ import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.util.text.ITextComponent
import net.minecraftforge.common.util.Constants.NBT
@@ -26,14 +26,14 @@ object AssemblerTemplates {
private val templateFilters = mutable.ArrayBuffer.empty[Method]
- def add(template: NBTTagCompound): Unit = {
+ def add(template: CompoundNBT): Unit = {
val selector = IMC.getStaticMethod(template.getString("select"), classOf[ItemStack])
val validator = IMC.getStaticMethod(template.getString("validate"), classOf[IInventory])
val assembler = IMC.getStaticMethod(template.getString("assemble"), classOf[IInventory])
val hostClass = tryGetHostClass(template.getString("hostClass"))
- val containerSlots = template.getTagList("containerSlots", NBT.TAG_COMPOUND).map((tag: NBTTagCompound) => parseSlot(tag, Some(Slot.Container), hostClass)).take(3).padTo(3, NoSlot).toArray
- val upgradeSlots = template.getTagList("upgradeSlots", NBT.TAG_COMPOUND).map((tag: NBTTagCompound) => parseSlot(tag, Some(Slot.Upgrade), hostClass)).take(9).padTo(9, NoSlot).toArray
- val componentSlots = template.getTagList("componentSlots", NBT.TAG_COMPOUND).map((tag: NBTTagCompound) => parseSlot(tag, None, hostClass)).take(9).padTo(9, NoSlot).toArray
+ val containerSlots = template.getList("containerSlots", NBT.TAG_COMPOUND).map((tag: CompoundNBT) => parseSlot(tag, Some(Slot.Container), hostClass)).take(3).padTo(3, NoSlot).toArray
+ val upgradeSlots = template.getList("upgradeSlots", NBT.TAG_COMPOUND).map((tag: CompoundNBT) => parseSlot(tag, Some(Slot.Upgrade), hostClass)).take(9).padTo(9, NoSlot).toArray
+ val componentSlots = template.getList("componentSlots", NBT.TAG_COMPOUND).map((tag: CompoundNBT) => parseSlot(tag, None, hostClass)).take(9).padTo(9, NoSlot).toArray
templates += new Template(selector, validator, assembler, containerSlots, upgradeSlots, componentSlots)
}
@@ -73,7 +73,7 @@ object AssemblerTemplates {
class Slot(val kind: String, val tier: Int, val validator: Option[Method], val hostClass: Option[Class[_ <: EnvironmentHost]]) {
def validate(inventory: IInventory, slot: Int, stack: ItemStack) = validator match {
- case Some(method) => IMC.tryInvokeStatic(method, inventory, slot.underlying(), tier.underlying(), stack)(false)
+ case Some(method) => IMC.tryInvokeStatic(method, inventory, Integer.valueOf(slot), Integer.valueOf(tier), stack)(false)
case _ => Option(hostClass.fold(api.Driver.driverFor(stack))(api.Driver.driverFor(stack, _))) match {
case Some(driver) => try driver.slot(stack) == kind && driver.tier(stack) <= tier catch {
case t: AbstractMethodError =>
@@ -85,10 +85,10 @@ object AssemblerTemplates {
}
}
- private def parseSlot(nbt: NBTTagCompound, kindOverride: Option[String], hostClass: Option[Class[_ <: EnvironmentHost]]) = {
- val kind = kindOverride.getOrElse(if (nbt.hasKey("type")) nbt.getString("type") else Slot.None)
- val tier = if (nbt.hasKey("tier")) nbt.getInteger("tier") else Tier.Any
- val validator = if (nbt.hasKey("validate")) Option(IMC.getStaticMethod(nbt.getString("validate"), classOf[IInventory], classOf[Int], classOf[Int], classOf[ItemStack])) else None
+ private def parseSlot(nbt: CompoundNBT, kindOverride: Option[String], hostClass: Option[Class[_ <: EnvironmentHost]]) = {
+ val kind = kindOverride.getOrElse(if (nbt.contains("type")) nbt.getString("type") else Slot.None)
+ val tier = if (nbt.contains("tier")) nbt.getInt("tier") else Tier.Any
+ val validator = if (nbt.contains("validate")) Option(IMC.getStaticMethod(nbt.getString("validate"), classOf[IInventory], classOf[Int], classOf[Int], classOf[ItemStack])) else None
new Slot(kind, tier, validator, hostClass)
}
diff --git a/src/main/scala/li/cil/oc/common/template/DisassemblerTemplates.scala b/src/main/scala/li/cil/oc/common/template/DisassemblerTemplates.scala
index 42a4733616..fe86a58cd6 100644
--- a/src/main/scala/li/cil/oc/common/template/DisassemblerTemplates.scala
+++ b/src/main/scala/li/cil/oc/common/template/DisassemblerTemplates.scala
@@ -5,14 +5,14 @@ import java.lang.reflect.Method
import li.cil.oc.OpenComputers
import li.cil.oc.common.IMC
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
import scala.collection.mutable
object DisassemblerTemplates {
private val templates = mutable.ArrayBuffer.empty[Template]
- def add(template: NBTTagCompound): Unit = try {
+ def add(template: CompoundNBT): Unit = try {
val selector = IMC.getStaticMethod(template.getString("select"), classOf[ItemStack])
val disassembler = IMC.getStaticMethod(template.getString("disassemble"), classOf[ItemStack], classOf[Array[ItemStack]])
diff --git a/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala b/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala
index 1ba28adb26..0b34419bd4 100644
--- a/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala
@@ -13,7 +13,8 @@ import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
object DroneTemplate extends Template {
override protected val suggestedComponents = Array(
@@ -30,14 +31,14 @@ object DroneTemplate extends Template {
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def assemble(inventory: IInventory) = {
- val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
+ val items = (0 until inventory.getContainerSize).map(inventory.getItem)
val data = new DroneData()
data.tier = caseTier(inventory)
data.name = RobotData.randomName
data.components = items.drop(1).filter(!_.isEmpty).toArray
data.storedEnergy = Settings.get.bufferDrone.toInt
val stack = api.Items.get(Constants.ItemName.Drone).createItemStack(1)
- data.save(stack)
+ data.saveData(stack)
val energy = Settings.get.droneBaseCost + complexity(inventory) * Settings.get.droneComplexityCost
Array(stack, Double.box(energy))
@@ -139,5 +140,5 @@ object DroneTemplate extends Template {
else if (caseTier(inventory) == Tier.Four) 9001 // Creative
else 5
- override protected def caseTier(inventory: IInventory) = ItemUtils.caseTier(inventory.getStackInSlot(0))
+ override protected def caseTier(inventory: IInventory) = ItemUtils.caseTier(inventory.getItem(0))
}
diff --git a/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala b/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala
index 333eab5175..ccd2d3ca99 100644
--- a/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala
@@ -12,7 +12,8 @@ import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
object MicrocontrollerTemplate extends Template {
override protected val suggestedComponents = Array(
@@ -29,7 +30,7 @@ object MicrocontrollerTemplate extends Template {
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def assemble(inventory: IInventory): Array[Object] = {
- val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
+ val items = (0 until inventory.getContainerSize).map(inventory.getItem)
val data = new MicrocontrollerData()
data.tier = caseTier(inventory)
data.components = items.drop(1).filter(!_.isEmpty).toArray
@@ -133,5 +134,5 @@ object MicrocontrollerTemplate extends Template {
else if (caseTier(inventory) == Tier.Four) 9001 // Creative
else 4
- override protected def caseTier(inventory: IInventory): Int = ItemUtils.caseTier(inventory.getStackInSlot(0))
+ override protected def caseTier(inventory: IInventory): Int = ItemUtils.caseTier(inventory.getItem(0))
}
diff --git a/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala b/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala
index 71b48b3538..99d1a9f50f 100644
--- a/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala
@@ -13,7 +13,7 @@ object NavigationUpgradeTemplate {
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new NavigationUpgradeData(stack)
ingredients.map {
- case part if part.getItem == net.minecraft.init.Items.FILLED_MAP => info.map
+ case part if part.getItem == net.minecraft.item.Items.FILLED_MAP => info.map
case part => part
}
}
diff --git a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala
index 59ae9f1b7d..e3251b04ee 100644
--- a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala
@@ -11,7 +11,8 @@ import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
object RobotTemplate extends Template {
override protected def hostClass = classOf[internal.Robot]
@@ -27,7 +28,7 @@ object RobotTemplate extends Template {
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def assemble(inventory: IInventory) = {
- val items = (1 until inventory.getSizeInventory).map(inventory.getStackInSlot)
+ val items = (1 until inventory.getContainerSize).map(inventory.getItem)
val data = new RobotData()
data.tier = caseTier(inventory)
data.name = RobotData.randomName
@@ -187,5 +188,5 @@ object RobotTemplate extends Template {
"li.cil.oc.common.template.RobotTemplate.disassemble")
}
- override protected def caseTier(inventory: IInventory) = ItemUtils.caseTier(inventory.getStackInSlot(0))
+ override protected def caseTier(inventory: IInventory) = ItemUtils.caseTier(inventory.getItem(0))
}
diff --git a/src/main/scala/li/cil/oc/common/template/ServerTemplate.scala b/src/main/scala/li/cil/oc/common/template/ServerTemplate.scala
index 6b4edab25c..ad3a9031b5 100644
--- a/src/main/scala/li/cil/oc/common/template/ServerTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/ServerTemplate.scala
@@ -17,8 +17,10 @@ object ServerTemplate {
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ServerInventory {
override def container = stack
+
+ override def rackSlot = -1
}
- Array(ingredients, (0 until info.getSizeInventory).map(info.getStackInSlot).filter(null !=).toArray)
+ Array(ingredients, (0 until info.getContainerSize).map(info.getItem).filter(null !=).toArray)
}
def register() {
diff --git a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala
index 13bd1c04da..26d48c1626 100644
--- a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala
@@ -11,7 +11,8 @@ import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
object TabletTemplate extends Template {
override protected val suggestedComponents = Array(
@@ -38,15 +39,15 @@ object TabletTemplate extends Template {
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def assemble(inventory: IInventory): Array[AnyRef] = {
- val items = (1 until inventory.getSizeInventory).map(slot => inventory.getStackInSlot(slot))
+ val items = (1 until inventory.getContainerSize).map(slot => inventory.getItem(slot))
val data = new TabletData()
- data.tier = ItemUtils.caseTier(inventory.getStackInSlot(0))
+ data.tier = ItemUtils.caseTier(inventory.getItem(0))
data.container = items.headOption.getOrElse(ItemStack.EMPTY)
data.items = Array(api.Items.get(Constants.BlockName.ScreenTier1).createItemStack(1)) ++ items.drop(if (data.tier == Tier.One) 0 else 1).filter(!_.isEmpty)
data.energy = Settings.get.bufferTablet
data.maxEnergy = data.energy
val stack = api.Items.get(Constants.ItemName.Tablet).createItemStack(1)
- data.save(stack)
+ data.saveData(stack)
val energy = Settings.get.tabletBaseCost + complexity(inventory) * Settings.get.tabletComplexityCost
Array(stack, Double.box(energy))
@@ -152,5 +153,5 @@ object TabletTemplate extends Template {
override protected def maxComplexity(inventory: IInventory) = super.maxComplexity(inventory) / 2 + 5
- override protected def caseTier(inventory: IInventory) = ItemUtils.caseTier(inventory.getStackInSlot(0))
+ override protected def caseTier(inventory: IInventory) = ItemUtils.caseTier(inventory.getItem(0))
}
diff --git a/src/main/scala/li/cil/oc/common/template/Template.scala b/src/main/scala/li/cil/oc/common/template/Template.scala
index e237af2a88..e5a5e7f623 100644
--- a/src/main/scala/li/cil/oc/common/template/Template.scala
+++ b/src/main/scala/li/cil/oc/common/template/Template.scala
@@ -62,7 +62,7 @@ abstract class Template {
}
protected def exists(inventory: IInventory, p: ItemStack => Boolean) = {
- (0 until inventory.getSizeInventory).exists(slot => StackOption(inventory.getStackInSlot(slot)) match {
+ (0 until inventory.getContainerSize).exists(slot => StackOption(inventory.getItem(slot)) match {
case SomeStack(stack) => p(stack)
case _ => false
})
@@ -78,8 +78,8 @@ abstract class Template {
case _ => false
})
- protected def requiresRAM(inventory: IInventory) = !(0 until inventory.getSizeInventory).
- map(inventory.getStackInSlot).
+ protected def requiresRAM(inventory: IInventory) = !(0 until inventory.getContainerSize).
+ map(inventory.getItem).
exists(stack => api.Driver.driverFor(stack, hostClass) match {
case driver: api.driver.item.Processor =>
val architecture = driver.architecture(stack)
@@ -104,8 +104,8 @@ abstract class Template {
protected def complexity(inventory: IInventory) = {
var acc = 0
- for (slot <- 1 until inventory.getSizeInventory) {
- val stack = inventory.getStackInSlot(slot)
+ for (slot <- 1 until inventory.getContainerSize) {
+ val stack = inventory.getItem(slot)
acc += (Option(api.Driver.driverFor(stack, hostClass)) match {
case Some(driver: api.driver.item.Processor) => 0 // CPUs are exempt, since they control the limit.
case Some(driver: api.driver.item.Container) => (1 + driver.tier(stack)) * 2
@@ -118,8 +118,8 @@ abstract class Template {
protected def maxComplexity(inventory: IInventory) = {
val caseTier = this.caseTier(inventory)
- val cpuTier = (0 until inventory.getSizeInventory).foldRight(0)((slot, acc) => {
- val stack = inventory.getStackInSlot(slot)
+ val cpuTier = (0 until inventory.getContainerSize).foldRight(0)((slot, acc) => {
+ val stack = inventory.getItem(slot)
acc + (api.Driver.driverFor(stack, hostClass) match {
case processor: api.driver.item.Processor => processor.tier(stack)
case _ => 0
diff --git a/src/main/scala/li/cil/oc/common/template/TemplateBlacklist.scala b/src/main/scala/li/cil/oc/common/template/TemplateBlacklist.scala
index edcad23014..158b774161 100644
--- a/src/main/scala/li/cil/oc/common/template/TemplateBlacklist.scala
+++ b/src/main/scala/li/cil/oc/common/template/TemplateBlacklist.scala
@@ -3,23 +3,25 @@ package li.cil.oc.common.template
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
-import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
+import net.minecraftforge.registries.ForgeRegistries
-import scala.collection.convert.WrapAsScala._
+import scala.collection.convert.ImplicitConversionsToScala._
object TemplateBlacklist {
private lazy val TheBlacklist = { // scnr
val pattern = """^([^@]+)(?:@(\d+))?$""".r
def parseDescriptor(id: String, meta: Int) = {
- val item = Item.REGISTRY.getObject(new ResourceLocation(id))
+ val item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(id))
if (item == null) {
OpenComputers.log.warn(s"Bad assembler blacklist entry '$id', unknown item id.")
None
}
else {
- Option(new ItemStack(item, 1, meta))
+ val stack = new ItemStack(item, 1)
+ stack.setDamageValue(meta)
+ Option(stack)
}
}
Settings.get.assemblerBlacklist.map {
@@ -42,6 +44,6 @@ object TemplateBlacklist {
}
def filter(stack: ItemStack): Boolean = {
- !TheBlacklist.exists(_.isItemEqual(stack))
+ !TheBlacklist.exists(_.sameItem(stack))
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala b/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala
index 0b4ac2e1e5..9c5e6fc246 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala
@@ -14,20 +14,28 @@ import li.cil.oc.api.internal
import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network._
import li.cil.oc.common.Slot
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.server.{PacketSender => ServerPacketSender}
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.init.SoundEvents
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.nbt.NBTTagList
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.ListNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraft.util.SoundCategory
+import net.minecraft.util.SoundEvents
import net.minecraftforge.common.util.Constants.NBT
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
-class Adapter extends traits.Environment with traits.ComponentInventory with traits.Tickable with traits.OpenSides with Analyzable with internal.Adapter with DeviceInfo {
+class Adapter(selfType: TileEntityType[_ <: Adapter]) extends TileEntity(selfType) with traits.Environment with traits.ComponentInventory
+ with traits.Tickable with traits.OpenSides with Analyzable with internal.Adapter with DeviceInfo with INamedContainerProvider {
+
val node = api.Network.newNode(this, Visibility.Network).create()
private val blocks = Array.fill[Option[(ManagedEnvironment, DriverBlock)]](6)(None)
@@ -49,21 +57,21 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
override protected def defaultState = true
- override def setSideOpen(side: EnumFacing, value: Boolean) {
+ override def setSideOpen(side: Direction, value: Boolean) {
super.setSideOpen(side, value)
if (isServer) {
ServerPacketSender.sendAdapterState(this)
- getWorld.playSound(null, x + 0.5, y + 0.5, z + 0.5, SoundEvents.BLOCK_PISTON_EXTEND, SoundCategory.BLOCKS, 0.5f, getWorld.rand.nextFloat() * 0.25f + 0.7f)
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, false)
+ getLevel.playSound(null, getBlockPos, SoundEvents.PISTON_EXTEND, SoundCategory.BLOCKS, 0.5f, getLevel.random.nextFloat() * 0.25f + 0.7f)
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
neighborChanged(side)
} else {
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
(blocks collect {
case Some((environment, _)) => environment.node
}) ++
@@ -83,10 +91,10 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
}
}
- def neighborChanged(d: EnumFacing) {
+ def neighborChanged(d: Direction) {
if (node != null && node.network != null) {
- val blockPos = getPos.offset(d)
- getWorld.getTileEntity(blockPos) match {
+ val blockPos = getBlockPos.relative(d)
+ getLevel.getBlockEntity(blockPos) match {
case _: traits.Environment =>
// Don't provide adaption for our stuffs. This is mostly to avoid
// cables and other non-functional stuff popping up in the adapter
@@ -94,7 +102,7 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
// but the only 'downside' is that it can't be used to manipulate
// inventories, which I actually consider a plus :P
case _ =>
- Option(api.Driver.driverFor(getWorld, blockPos, d)) match {
+ Option(api.Driver.driverFor(getLevel, blockPos, d)) match {
case Some(newDriver) if isSideOpen(d) => blocks(d.ordinal()) match {
case Some((oldEnvironment, driver)) =>
if (newDriver != driver) {
@@ -105,13 +113,13 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
node.disconnect(oldEnvironment.node)
// Then rebuild - if we have something.
- val environment = newDriver.createEnvironment(getWorld, blockPos, d)
+ val environment = newDriver.createEnvironment(getLevel, blockPos, d)
if (environment != null) {
blocks(d.ordinal()) = Some((environment, newDriver))
if (environment.canUpdate) {
updatingBlocks += environment
}
- blocksData(d.ordinal()) = Some(new BlockData(environment.getClass.getName, new NBTTagCompound()))
+ blocksData(d.ordinal()) = Some(new BlockData(environment.getClass.getName, new CompoundNBT()))
node.connect(environment.node)
}
} // else: the more things change, the more they stay the same.
@@ -120,7 +128,7 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
return
}
// A challenger appears. Maybe.
- val environment = newDriver.createEnvironment(getWorld, blockPos, d)
+ val environment = newDriver.createEnvironment(getLevel, blockPos, d)
if (environment != null) {
blocks(d.ordinal()) = Some((environment, newDriver))
if (environment.canUpdate) {
@@ -128,10 +136,10 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
}
blocksData(d.ordinal()) match {
case Some(data) if data.name == environment.getClass.getName =>
- environment.load(data.data)
+ environment.loadData(data.data)
case _ =>
}
- blocksData(d.ordinal()) = Some(new BlockData(environment.getClass.getName, new NBTTagCompound()))
+ blocksData(d.ordinal()) = Some(new BlockData(environment.getClass.getName, new CompoundNBT()))
node.connect(environment.node)
}
}
@@ -139,7 +147,7 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
case Some((environment, driver)) =>
// We had something there, but it's gone now...
node.disconnect(environment.node)
- environment.save(blocksData(d.ordinal()).get.data)
+ environment.saveData(blocksData(d.ordinal()).get.data)
Option(environment.node).foreach(_.remove())
blocks(d.ordinal()) = None
updatingBlocks -= environment
@@ -152,7 +160,7 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
def neighborChanged() {
if (node != null && node.network != null) {
- for (d <- EnumFacing.values) {
+ for (d <- Direction.values) {
neighborChanged(d)
}
}
@@ -176,57 +184,62 @@ class Adapter extends traits.Environment with traits.ComponentInventory with tra
// ----------------------------------------------------------------------- //
- override def getSizeInventory = 1
+ override def getContainerSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack, getClass))) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack, getClass))) match {
case (0, Some(driver)) => driver.slot(stack) == Slot.Upgrade
case _ => false
}
// ----------------------------------------------------------------------- //
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Adapter(ContainerTypes.ADAPTER, id, playerInventory, this)
+
+ // ----------------------------------------------------------------------- //
+
private final val BlocksTag = Settings.namespace + "adapter.blocks"
private final val BlockNameTag = "name"
private final val BlockDataTag = "data"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
- val blocksNbt = nbt.getTagList(BlocksTag, NBT.TAG_COMPOUND)
- (0 until (blocksNbt.tagCount min blocksData.length)).
- map(blocksNbt.getCompoundTagAt).
+ val blocksNbt = nbt.getList(BlocksTag, NBT.TAG_COMPOUND)
+ (0 until (blocksNbt.size min blocksData.length)).
+ map(blocksNbt.getCompound).
zipWithIndex.
foreach {
case (blockNbt, i) =>
- if (blockNbt.hasKey(BlockNameTag) && blockNbt.hasKey(BlockDataTag)) {
- blocksData(i) = Some(new BlockData(blockNbt.getString(BlockNameTag), blockNbt.getCompoundTag(BlockDataTag)))
+ if (blockNbt.contains(BlockNameTag) && blockNbt.contains(BlockDataTag)) {
+ blocksData(i) = Some(new BlockData(blockNbt.getString(BlockNameTag), blockNbt.getCompound(BlockDataTag)))
}
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
- val blocksNbt = new NBTTagList()
+ val blocksNbt = new ListNBT()
for (i <- blocks.indices) {
- val blockNbt = new NBTTagCompound()
+ val blockNbt = new CompoundNBT()
blocksData(i) match {
case Some(data) =>
blocks(i) match {
- case Some((environment, _)) => environment.save(data.data)
+ case Some((environment, _)) => environment.saveData(data.data)
case _ =>
}
- blockNbt.setString(BlockNameTag, data.name)
- blockNbt.setTag(BlockDataTag, data.data)
+ blockNbt.putString(BlockNameTag, data.name)
+ blockNbt.put(BlockDataTag, data.data)
case _ =>
}
- blocksNbt.appendTag(blockNbt)
+ blocksNbt.add(blockNbt)
}
- nbt.setTag(BlocksTag, blocksNbt)
+ nbt.put(BlocksTag, blocksNbt)
}
// ----------------------------------------------------------------------- //
- private class BlockData(val name: String, val data: NBTTagCompound)
+ private class BlockData(val name: String, val data: CompoundNBT)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala b/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala
index c65c8a1649..85e81df00f 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala
@@ -12,20 +12,30 @@ import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network._
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraft.util.text.StringTextComponent
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
+
+class Assembler(selfType: TileEntityType[_ <: Assembler]) extends TileEntity(selfType) with traits.Environment with traits.PowerAcceptor
+ with traits.Inventory with SidedEnvironment with traits.StateAware with traits.Tickable with DeviceInfo with INamedContainerProvider {
-class Assembler extends traits.Environment with traits.PowerAcceptor with traits.Inventory with SidedEnvironment with traits.StateAware with traits.Tickable with DeviceInfo {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("assembler").
withConnector(Settings.get.bufferConverter).
@@ -48,15 +58,15 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing) = side != EnumFacing.UP
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction) = side != Direction.UP
- override def sidedNode(side: EnumFacing) = if (side != EnumFacing.UP) node else null
+ override def sidedNode(side: Direction) = if (side != Direction.UP) node else null
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing) = canConnect(side)
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction) = canConnect(side)
- override protected def connector(side: EnumFacing) = Option(if (side != EnumFacing.UP) node else null)
+ override protected def connector(side: Direction) = Option(if (side != Direction.UP) node else null)
override def energyThroughput = Settings.get.assemblerRate
@@ -68,7 +78,7 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
// ----------------------------------------------------------------------- //
- def canAssemble = AssemblerTemplates.select(getStackInSlot(0)) match {
+ def canAssemble = AssemblerTemplates.select(getItem(0)) match {
case Some(template) => !isAssembling && output.isEmpty && template.validate(this)._1
case _ => false
}
@@ -82,11 +92,11 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
// ----------------------------------------------------------------------- //
def start(finishImmediately: Boolean = false): Boolean = this.synchronized {
- AssemblerTemplates.select(getStackInSlot(0)) match {
+ AssemblerTemplates.select(getItem(0)) match {
case Some(template) if !isAssembling && output.isEmpty && template.validate(this)._1 =>
- for (slot <- 0 until getSizeInventory) {
- val stack = getStackInSlot(slot)
- if (!stack.isEmpty && !isItemValidForSlot(slot, stack)) return false
+ for (slot <- 0 until getContainerSize) {
+ val stack = getItem(slot)
+ if (!stack.isEmpty && !canPlaceItem(slot, stack)) return false
}
val (stack, energy) = template.assemble(this)
output = StackOption(stack)
@@ -99,8 +109,8 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
requiredEnergy = totalRequiredEnergy
ServerPacketSender.sendRobotAssembling(this, assembling = true)
- for (slot <- 0 until getSizeInventory) updateItems(slot, ItemStack.EMPTY)
- markDirty()
+ for (slot <- 0 until getContainerSize) updateItems(slot, ItemStack.EMPTY)
+ setChanged()
true
case _ => false
@@ -112,7 +122,7 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
@Callback(doc = """function(): string, number or boolean -- The current state of the assembler, `busy' or `idle', followed by the progress or template validity, respectively.""")
def status(context: Context, args: Arguments): Array[Object] = {
if (isAssembling) result("busy", progress)
- else AssemblerTemplates.select(getStackInSlot(0)) match {
+ else AssemblerTemplates.select(getItem(0)) match {
case Some(template) if template.validate(this)._1 => result("idle", true)
case _ => result("idle", false)
}
@@ -125,12 +135,12 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
override def updateEntity() {
super.updateEntity()
- if (!output.isEmpty && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (!output.isEmpty && getLevel.getGameTime % Settings.get.tickFrequency == 0) {
val want = math.max(1, math.min(requiredEnergy, Settings.get.assemblerTickAmount * Settings.get.tickFrequency))
val have = want + (if (Settings.get.ignorePower) 0 else node.changeBuffer(-want))
requiredEnergy -= have
if (requiredEnergy <= 0) {
- setInventorySlotContents(0, output.get)
+ setItem(0, output.get)
output = EmptyStack
requiredEnergy = 0
}
@@ -145,47 +155,47 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
private final val TotalTag = Settings.namespace + "total"
private final val RemainingTag = Settings.namespace + "remaining"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(OutputTag)) {
- output = StackOption(new ItemStack(nbt.getCompoundTag(OutputTag)))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ if (nbt.contains(OutputTag)) {
+ output = StackOption(ItemStack.of(nbt.getCompound(OutputTag)))
}
- else if (nbt.hasKey(OutputTagCompat)) {
- output = StackOption(new ItemStack(nbt.getCompoundTag(OutputTagCompat)))
+ else if (nbt.contains(OutputTagCompat)) {
+ output = StackOption(ItemStack.of(nbt.getCompound(OutputTagCompat)))
}
totalRequiredEnergy = nbt.getDouble(TotalTag)
requiredEnergy = nbt.getDouble(RemainingTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setNewCompoundTag(OutputTag, output.get.writeToNBT)
- nbt.setDouble(TotalTag, totalRequiredEnergy)
- nbt.setDouble(RemainingTag, requiredEnergy)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.setNewCompoundTag(OutputTag, output.get.save)
+ nbt.putDouble(TotalTag, totalRequiredEnergy)
+ nbt.putDouble(RemainingTag, requiredEnergy)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
requiredEnergy = nbt.getDouble(RemainingTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setDouble(RemainingTag, requiredEnergy)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putDouble(RemainingTag, requiredEnergy)
}
// ----------------------------------------------------------------------- //
- override def getSizeInventory = 22
+ override def getContainerSize = 22
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack) =
+ override def canPlaceItem(slot: Int, stack: ItemStack) =
if (slot == 0) {
!isAssembling && AssemblerTemplates.select(stack).isDefined
}
- else AssemblerTemplates.select(getStackInSlot(0)) match {
+ else AssemblerTemplates.select(getItem(0)) match {
case Some(template) =>
val tplSlot =
if ((1 until 4) contains slot) template.containerSlots(slot - 1)
@@ -195,4 +205,11 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
tplSlot.validate(this, slot, stack)
case _ => false
}
+
+ // ----------------------------------------------------------------------- //
+
+ override def getDisplayName = StringTextComponent.EMPTY
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Assembler(ContainerTypes.ASSEMBLER, id, playerInventory, this)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Cable.scala b/src/main/scala/li/cil/oc/common/tileentity/Cable.scala
index 3bbde82150..131d76cd76 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Cable.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Cable.scala
@@ -5,19 +5,21 @@ import li.cil.oc.api.network.Visibility
import li.cil.oc.common
import li.cil.oc.Constants
import li.cil.oc.util.Color
-import net.minecraft.item.EnumDyeColor
+import net.minecraft.item.DyeColor
import li.cil.oc.util.ItemColorizer
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
-class Cable extends traits.Environment with traits.NotAnalyzable with traits.ImmibisMicroblock with traits.Colored {
+class Cable(selfType: TileEntityType[_ <: Cable]) extends TileEntity(selfType) with traits.Environment with traits.NotAnalyzable with traits.ImmibisMicroblock with traits.Colored {
val node = api.Network.newNode(this, Visibility.None).create()
- setColor(Color.rgbValues(EnumDyeColor.SILVER))
+ setColor(Color.rgbValues(DyeColor.LIGHT_GRAY))
def createItemStack() = {
val stack = api.Items.get(Constants.BlockName.Cable).createItemStack(1)
- if (getColor != Color.rgbValues(EnumDyeColor.SILVER)) {
+ if (getColor != Color.rgbValues(DyeColor.LIGHT_GRAY)) {
ItemColorizer.setColor(stack, getColor)
}
stack
@@ -35,10 +37,8 @@ class Cable extends traits.Environment with traits.NotAnalyzable with traits.Imm
override protected def onColorChanged() {
super.onColorChanged()
- if (getWorld != null && isServer) {
+ if (getLevel != null && isServer) {
api.Network.joinOrCreateNetwork(this)
}
}
-
- override def getRenderBoundingBox = common.block.Cable.bounds(getWorld, getPos).offset(x, y, z)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Capacitor.scala b/src/main/scala/li/cil/oc/common/tileentity/Capacitor.scala
index 31da0e1c21..06bfab5abb 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Capacitor.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Capacitor.scala
@@ -10,11 +10,14 @@ import li.cil.oc.api
import li.cil.oc.api.driver.DeviceInfo
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
-import net.minecraft.util.EnumFacing
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraft.util.math.BlockPos
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
-class Capacitor extends traits.Environment with DeviceInfo {
+class Capacitor(selfType: TileEntityType[_ <: Capacitor]) extends TileEntity(selfType) with traits.Environment with DeviceInfo {
// Start with maximum theoretical capacity, gets reduced after validation.
// This is done so that we don't lose energy while loading.
val node = api.Network.newNode(this, Visibility.Network).
@@ -37,7 +40,7 @@ class Capacitor extends traits.Environment with DeviceInfo {
super.dispose()
if (isServer) {
indirectNeighbors.map(coordinate => {
- if (getWorld.isBlockLoaded(coordinate)) Option(getWorld.getTileEntity(coordinate))
+ if (getLevel.isLoaded(coordinate)) Option(getLevel.getBlockEntity(coordinate))
else None
}).collect {
case Some(capacitor: Capacitor) => capacitor.recomputeCapacity()
@@ -57,14 +60,14 @@ class Capacitor extends traits.Environment with DeviceInfo {
def recomputeCapacity(updateSecondGradeNeighbors: Boolean = false) {
node.setLocalBufferSize(
Settings.get.bufferCapacitor +
- Settings.get.bufferCapacitorAdjacencyBonus * EnumFacing.values.count(side => {
- val blockPos = getPos.offset(side)
- getWorld.isBlockLoaded(blockPos) && (getWorld.getTileEntity(blockPos) match {
+ Settings.get.bufferCapacitorAdjacencyBonus * Direction.values.count(side => {
+ val blockPos = getBlockPos.relative(side)
+ getLevel.isLoaded(blockPos) && (getLevel.getBlockEntity(blockPos) match {
case capacitor: Capacitor => true
case _ => false
})
}) +
- Settings.get.bufferCapacitorAdjacencyBonus / 2 * indirectNeighbors.count(blockPos => getWorld.isBlockLoaded(blockPos) && (getWorld.getTileEntity(blockPos) match {
+ Settings.get.bufferCapacitorAdjacencyBonus / 2 * indirectNeighbors.count(blockPos => getLevel.isLoaded(blockPos) && (getLevel.getBlockEntity(blockPos) match {
case capacitor: Capacitor =>
if (updateSecondGradeNeighbors) {
capacitor.recomputeCapacity()
@@ -74,7 +77,7 @@ class Capacitor extends traits.Environment with DeviceInfo {
})))
}
- private def indirectNeighbors = EnumFacing.values.map(getPos.offset(_, 2))
+ private def indirectNeighbors = Direction.values.map(getBlockPos.relative(_, 2): BlockPos)
protected def maxCapacity = Settings.get.bufferCapacitor + Settings.get.bufferCapacitorAdjacencyBonus * 9
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/CarpetedCapacitor.scala b/src/main/scala/li/cil/oc/common/tileentity/CarpetedCapacitor.scala
index b355dc9d92..92fc496c09 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/CarpetedCapacitor.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/CarpetedCapacitor.scala
@@ -6,16 +6,16 @@ import li.cil.oc.Constants
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
import li.cil.oc.api.driver.DeviceInfo.DeviceClass
import li.cil.oc.Settings
-import net.minecraft.entity.EntityLivingBase
-import net.minecraft.entity.passive.{EntityOcelot, EntitySheep}
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.passive.{OcelotEntity, SheepEntity}
+import net.minecraft.tileentity.TileEntityType
import net.minecraft.util.DamageSource
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
-import li.cil.oc.common.tileentity.traits.Tickable
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
-class CarpetedCapacitor extends Capacitor with Tickable {
+class CarpetedCapacitor(selfType: TileEntityType[_ <: CarpetedCapacitor]) extends Capacitor(selfType) with traits.Tickable {
private final lazy val deviceInfo = Map(
DeviceAttribute.Class -> DeviceClass.Power,
DeviceAttribute.Description -> "Battery",
@@ -26,38 +26,38 @@ class CarpetedCapacitor extends Capacitor with Tickable {
override def getDeviceInfo: util.Map[String, String] = deviceInfo
- private def _world: net.minecraft.world.World = getWorld
+ private def _world: net.minecraft.world.World = getLevel
private val rng = scala.util.Random
private val chance: Double = Settings.get.carpetDamageChance
private var nextChanceTime: Long = 0
- private def energyFromGroup(entities: Set[EntityLivingBase], power: Double): Double = {
+ private def energyFromGroup(entities: Set[LivingEntity], power: Double): Double = {
if (entities.size < 2) return 0
def tryDamageOne(): Unit = {
for (ent <- entities) {
if (rng.nextDouble() < chance) {
- ent.attackEntityFrom(DamageSource.GENERIC, 1)
- ent.setRevengeTarget(ent) // panic
- ent.knockBack(ent, 0, .25, 0)
+ ent.hurt(DamageSource.GENERIC, 1)
+ ent.setLastHurtByMob(ent) // panic
+ ent.knockback(0, .25, 0)
// wait a minute before the next possible shock
- nextChanceTime = _world.getTotalWorldTime + (20 * 60)
+ nextChanceTime = _world.getGameTime + (20 * 60)
return
}
}
}
- if (chance > 0 && nextChanceTime < _world.getTotalWorldTime) {
+ if (chance > 0 && nextChanceTime < _world.getGameTime) {
tryDamageOne()
}
power
}
override def updateEntity() {
- if (node != null && (_world.getTotalWorldTime + hashCode) % 20 == 0) {
- val entities = _world.getEntitiesWithinAABB(classOf[EntityLivingBase], capacitorPowerBounds)
- .filter(entity => entity.isEntityAlive)
+ if (node != null && (_world.getGameTime + hashCode) % 20 == 0) {
+ val entities = _world.getEntitiesOfClass(classOf[LivingEntity], capacitorPowerBounds)
+ .filter(entity => entity.isAlive)
.toSet
- val sheepPower = energyFromGroup(entities.filter(_.isInstanceOf[EntitySheep]), Settings.get.sheepPower)
- val ocelotPower = energyFromGroup(entities.filter(_.isInstanceOf[EntityOcelot]), Settings.get.ocelotPower)
+ val sheepPower = energyFromGroup(entities.filter(_.isInstanceOf[SheepEntity]), Settings.get.sheepPower)
+ val ocelotPower = energyFromGroup(entities.filter(_.isInstanceOf[OcelotEntity]), Settings.get.ocelotPower)
val totalPower = sheepPower + ocelotPower
if (totalPower > 0) {
node.changeBuffer(totalPower)
@@ -65,5 +65,5 @@ class CarpetedCapacitor extends Capacitor with Tickable {
}
}
- private def capacitorPowerBounds = position.offset(EnumFacing.UP).bounds
+ private def capacitorPowerBounds = position.offset(Direction.UP).bounds
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Case.scala b/src/main/scala/li/cil/oc/common/tileentity/Case.scala
index 20d423a0c5..58e1a8ec5a 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Case.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Case.scala
@@ -15,19 +15,25 @@ import li.cil.oc.common.InventorySlots
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.block.property.PropertyRunning
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.util.Color
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-import scala.collection.convert.WrapAsJava._
-
-class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with traits.Colored with internal.Case with DeviceInfo {
- def this() = {
- this(0)
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+import scala.collection.convert.ImplicitConversionsToJava._
+
+class Case(selfType: TileEntityType[_ <: Case], var tier: Int) extends TileEntity(selfType) with traits.PowerAcceptor with traits.Computer with traits.Colored with internal.Case with DeviceInfo with INamedContainerProvider {
+ def this(selfType: TileEntityType[_ <: Case]) = {
+ this(selfType, 0)
// If no tier was defined when constructing this case, then we don't yet know the inventory size
// this is set back to true when the nbt data is loaded
isSizeInventoryReady = false
@@ -44,17 +50,17 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
DeviceAttribute.Description -> "Computer",
DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor,
DeviceAttribute.Product -> "Blocker",
- DeviceAttribute.Capacity -> getSizeInventory.toString
+ DeviceAttribute.Capacity -> getContainerSize.toString
)
override def getDeviceInfo: util.Map[String, String] = deviceInfo
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing) = side != facing
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction) = side != facing
- override protected def connector(side: EnumFacing) = Option(if (side != facing && machine != null) machine.node.asInstanceOf[Connector] else null)
+ override protected def connector(side: Direction) = Option(if (side != facing && machine != null) machine.node.asInstanceOf[Connector] else null)
override def energyThroughput = Settings.get.caseRate(tier)
@@ -67,7 +73,7 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
// ----------------------------------------------------------------------- //
override def updateEntity() {
- if (isServer && isCreative && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (isServer && isCreative && getLevel.getGameTime % Settings.get.tickFrequency == 0) {
// Creative case, make it generate power.
node.asInstanceOf[Connector].changeBuffer(Double.PositiveInfinity)
}
@@ -78,12 +84,12 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
override protected def onRunningChanged(): Unit = {
super.onRunningChanged()
- getBlockType match {
+ getBlockState.getBlock match {
case block: common.block.Case => {
- val state = getWorld.getBlockState(getPos)
+ val state = getLevel.getBlockState(getBlockPos)
// race condition that the world no longer has this block at the position (e.g. it was broken)
if (block == state.getBlock) {
- getWorld.setBlockState(getPos, state.withProperty(PropertyRunning.Running, Boolean.box(isRunning)))
+ getLevel.setBlockAndUpdate(getBlockPos, state.setValue(PropertyRunning.Running, Boolean.box(isRunning)))
}
}
case _ =>
@@ -94,16 +100,16 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
private final val TierTag = Settings.namespace + "tier"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
+ override def loadForServer(nbt: CompoundNBT) {
tier = nbt.getByte(TierTag) max 0 min 3
setColor(Color.rgbValues(Color.byTier(tier)))
- super.readFromNBTForServer(nbt)
+ super.loadForServer(nbt)
isSizeInventoryReady = true
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- nbt.setByte(TierTag, tier.toByte)
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ nbt.putByte(TierTag, tier.toByte)
+ super.saveForServer(nbt)
}
// ----------------------------------------------------------------------- //
@@ -130,14 +136,19 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
}
}
- override def getSizeInventory = if (tier < 0 || tier >= InventorySlots.computer.length) 0 else InventorySlots.computer(tier).length
+ override def getContainerSize = if (tier < 0 || tier >= InventorySlots.computer.length) 0 else InventorySlots.computer(tier).length
- override def isUsableByPlayer(player: EntityPlayer) =
- super.isUsableByPlayer(player) && (!isCreative || player.capabilities.isCreativeMode)
+ override def stillValid(player: PlayerEntity) =
+ super.stillValid(player) && (!isCreative || player.isCreative)
- override def isItemValidForSlot(slot: Int, stack: ItemStack) =
+ override def canPlaceItem(slot: Int, stack: ItemStack) =
Option(Driver.driverFor(stack, getClass)).fold(false)(driver => {
val provided = InventorySlots.computer(tier)(slot)
driver.slot(stack) == provided.slot && driver.tier(stack) <= provided.tier
})
+
+ // ----------------------------------------------------------------------- //
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Case(ContainerTypes.CASE, id, playerInventory, this, tier)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
index 946e5d0b9d..1d8545beb3 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
@@ -14,25 +14,34 @@ import li.cil.oc.api.nanomachines.Controller
import li.cil.oc.api.network._
import li.cil.oc.api.util.StateAware
import li.cil.oc.common.Slot
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.entity.Drone
import li.cil.oc.integration.util.ItemCharge
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraft.util.EnumParticleTypes
-import net.minecraft.util.math.Vec3d
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-import scala.collection.convert.WrapAsJava._
-import scala.collection.convert.WrapAsScala._
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.particles.ParticleTypes
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraft.util.Util
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+import scala.collection.convert.ImplicitConversionsToJava._
+import scala.collection.convert.ImplicitConversionsToScala._
import scala.collection.mutable
-class Charger extends traits.Environment with traits.PowerAcceptor with traits.RedstoneAware with traits.Rotatable with traits.ComponentInventory with traits.Tickable with Analyzable with traits.StateAware with DeviceInfo {
+class Charger(selfType: TileEntityType[_ <: Charger]) extends TileEntity(selfType) with traits.Environment with traits.PowerAcceptor with traits.RedstoneAware
+ with traits.Rotatable with traits.ComponentInventory with traits.Tickable with Analyzable with traits.StateAware with DeviceInfo with INamedContainerProvider {
+
val node: Connector = api.Network.newNode(this, Visibility.None).
withConnector(Settings.get.bufferConverter).
create()
@@ -57,10 +66,10 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing): Boolean = side != facing
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction): Boolean = side != facing
- override protected def connector(side: EnumFacing) = Option(if (side != facing) node else null)
+ override protected def connector(side: Direction) = Option(if (side != facing) node else null)
override def energyThroughput: Double = Settings.get.chargerRate
@@ -73,8 +82,8 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
else util.EnumSet.noneOf(classOf[api.util.StateAware.State])
}
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Null = {
- player.sendMessage(Localization.Analyzer.ChargerSpeed(chargeSpeed))
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Null = {
+ player.sendMessage(Localization.Analyzer.ChargerSpeed(chargeSpeed), Util.NIL_UUID)
null
}
@@ -92,11 +101,11 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
super.updateEntity()
// Offset by hashcode to avoid all chargers ticking at the same time.
- if ((getWorld.getWorldInfo.getWorldTotalTime + math.abs(hashCode())) % 20 == 0) {
+ if ((getLevel.getLevelData.getGameTime + math.abs(hashCode())) % 20 == 0) {
updateConnectors()
}
- if (isServer && getWorld.getWorldInfo.getWorldTotalTime % Settings.get.tickFrequency == 0) {
+ if (isServer && getLevel.getLevelData.getGameTime % Settings.get.tickFrequency == 0) {
var canCharge = Settings.get.ignorePower
// Charging of external devices.
@@ -117,7 +126,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
val charge = Settings.get.chargeRateTablet * chargeSpeed * Settings.get.tickFrequency
canCharge ||= charge > 0 && node.globalBuffer >= charge * 0.5
if (canCharge) {
- (0 until getSizeInventory).map(getStackInSlot).foreach(chargeStack(_, charge))
+ (0 until getContainerSize).map(getItem).foreach(chargeStack(_, charge))
}
}
@@ -140,15 +149,15 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
}
}
- if (isClient && chargeSpeed > 0 && hasPower && getWorld.getWorldInfo.getWorldTotalTime % 10 == 0) {
+ if (isClient && chargeSpeed > 0 && hasPower && getLevel.getLevelData.getGameTime % 10 == 0) {
connectors.foreach(connector => {
val position = connector.pos
- val theta = getWorld.rand.nextDouble * Math.PI
- val phi = getWorld.rand.nextDouble * Math.PI * 2
+ val theta = getLevel.random.nextDouble * Math.PI
+ val phi = getLevel.random.nextDouble * Math.PI * 2
val dx = 0.45 * Math.sin(theta) * Math.cos(phi)
val dy = 0.45 * Math.sin(theta) * Math.sin(phi)
val dz = 0.45 * Math.cos(theta)
- getWorld.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, position.x + dx, position.y + dz, position.z + dy, 0, 0, 0)
+ getLevel.addParticle(ParticleTypes.HAPPY_VILLAGER, position.x + dx, position.y + dz, position.z + dy, 0, 0, 0)
})
}
}
@@ -169,40 +178,40 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
private final val InvertSignalTag = Settings.namespace + "invertSignal"
private final val InvertSignalTagCompat = "invertSignal"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(ChargeSpeedTagCompat))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ if (nbt.contains(ChargeSpeedTagCompat))
chargeSpeed = nbt.getDouble(ChargeSpeedTagCompat) max 0 min 1
else
chargeSpeed = nbt.getDouble(ChargeSpeedTag) max 0 min 1
- if (nbt.hasKey(HasPowerTagCompat))
+ if (nbt.contains(HasPowerTagCompat))
hasPower = nbt.getBoolean(HasPowerTagCompat)
else
hasPower = nbt.getBoolean(HasPowerTag)
- if (nbt.hasKey(InvertSignalTagCompat))
+ if (nbt.contains(InvertSignalTagCompat))
invertSignal = nbt.getBoolean(InvertSignalTagCompat)
else
invertSignal = nbt.getBoolean(InvertSignalTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setDouble(ChargeSpeedTag, chargeSpeed)
- nbt.setBoolean(HasPowerTag, hasPower)
- nbt.setBoolean(InvertSignalTag, invertSignal)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.putDouble(ChargeSpeedTag, chargeSpeed)
+ nbt.putBoolean(HasPowerTag, hasPower)
+ nbt.putBoolean(InvertSignalTag, invertSignal)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
chargeSpeed = nbt.getDouble(ChargeSpeedTag)
hasPower = nbt.getBoolean(HasPowerTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setDouble(ChargeSpeedTag, chargeSpeed)
- nbt.setBoolean(HasPowerTag, hasPower)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putDouble(ChargeSpeedTag, chargeSpeed)
+ nbt.putBoolean(HasPowerTag, hasPower)
}
// ----------------------------------------------------------------------- //
@@ -213,16 +222,21 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
case _ => false
})
- override def getSizeInventory = 1
+ override def getContainerSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
case (0, Some(driver)) if driver.slot(stack) == Slot.Tablet => true
case _ => ItemCharge.canCharge(stack)
}
// ----------------------------------------------------------------------- //
- override def updateRedstoneInput(side: EnumFacing) {
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Charger(ContainerTypes.CHARGER, id, playerInventory, this)
+
+ // ----------------------------------------------------------------------- //
+
+ override def updateRedstoneInput(side: Direction) {
super.updateRedstoneInput(side)
val signal = getInput.max min 15
@@ -239,20 +253,20 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
}
def updateConnectors() {
- val robots = EnumFacing.values.map(side => {
+ val robots = Direction.values.map(side => {
val blockPos = BlockPosition(this).offset(side)
- if (getWorld.blockExists(blockPos)) Option(getWorld.getTileEntity(blockPos))
+ if (getLevel.blockExists(blockPos)) Option(getLevel.getBlockEntity(blockPos))
else None
}).collect {
case Some(t: RobotProxy) => new RobotChargeable(t.robot)
}
- val bounds = BlockPosition(this).bounds.grow(1, 1, 1)
- val drones = getWorld.getEntitiesWithinAABB(classOf[Drone], bounds).collect {
+ val bounds = BlockPosition(this).bounds.inflate(1, 1, 1)
+ val drones = getLevel.getEntitiesOfClass(classOf[Drone], bounds).collect {
case drone: Drone => new DroneChargeable(drone)
}
- val players = getWorld.getEntitiesWithinAABB(classOf[EntityPlayer], bounds).collect {
- case player: EntityPlayer => player
+ val players = getLevel.getEntitiesOfClass(classOf[PlayerEntity], bounds).collect {
+ case player: PlayerEntity => player
}
val chargeablePlayers = players.collect {
@@ -265,13 +279,13 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
if (connectors.size != newConnectors.length || (connectors.nonEmpty && (connectors -- newConnectors).nonEmpty)) {
connectors.clear()
connectors ++= newConnectors
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, false)
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
}
// scan players for chargeable equipment
equipment.clear()
players.foreach {
- player => player.inventory.mainInventory.foreach {
+ player => player.inventory.items.foreach {
stack: ItemStack =>
if (Option(Driver.driverFor(stack, getClass)) match {
case Some(driver) if driver.slot(stack) == Slot.Tablet => true
@@ -284,7 +298,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
}
trait Chargeable {
- def pos: Vec3d
+ def pos: Vector3d
def changeBuffer(delta: Double): Double
}
@@ -299,7 +313,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
}
class RobotChargeable(val robot: Robot) extends ConnectorChargeable(robot.node.asInstanceOf[Connector]) {
- override def pos: Vec3d = BlockPosition(robot).toVec3
+ override def pos: Vector3d = BlockPosition(robot).toVec3
override def equals(obj: scala.Any): Boolean = obj match {
case chargeable: RobotChargeable => chargeable.robot == robot
@@ -310,7 +324,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
}
class DroneChargeable(val drone: Drone) extends ConnectorChargeable(drone.components.node.asInstanceOf[Connector]) {
- override def pos: Vec3d = new Vec3d(drone.posX, drone.posY, drone.posZ)
+ override def pos: Vector3d = new Vector3d(drone.getX, drone.getY, drone.getZ)
override def equals(obj: scala.Any): Boolean = obj match {
case chargeable: DroneChargeable => chargeable.drone == drone
@@ -320,8 +334,8 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
override def hashCode(): Int = drone.hashCode()
}
- class PlayerChargeable(val player: EntityPlayer) extends Chargeable {
- override def pos: Vec3d = new Vec3d(player.posX, player.posY, player.posZ)
+ class PlayerChargeable(val player: PlayerEntity) extends Chargeable {
+ override def pos: Vector3d = new Vector3d(player.getX, player.getY, player.getZ)
override def changeBuffer(delta: Double): Double = {
api.Nanomachines.getController(player) match {
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala b/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala
index 9d02fb9c9b..69770cb83d 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala
@@ -11,25 +11,33 @@ import li.cil.oc.api.driver.DeviceInfo
import li.cil.oc.api.network.Connector
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.util.StateAware
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.template.DisassemblerTemplates
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
-class Disassembler extends traits.Environment with traits.PowerAcceptor with traits.Inventory with traits.StateAware with traits.PlayerInputAware with traits.Tickable with DeviceInfo {
+class Disassembler(selfType: TileEntityType[_ <: Disassembler]) extends TileEntity(selfType) with traits.Environment with traits.PowerAcceptor
+ with traits.Inventory with traits.StateAware with traits.PlayerInputAware with traits.Tickable with DeviceInfo with INamedContainerProvider {
+
val node: Connector = api.Network.newNode(this, Visibility.None).
withConnector(Settings.get.bufferConverter).
create()
@@ -40,7 +48,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
var totalRequiredEnergy = 0.0
- override def getInventoryStackLimit: Int = 1
+ override def getMaxStackSize: Int = 1
var buffer = 0.0
@@ -51,7 +59,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
private def setActive(value: Boolean) = if (value != isActive) {
isActive = value
ServerPacketSender.sendDisassemblerActive(this, isActive)
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, true)
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
}
private final lazy val deviceInfo = Map(
@@ -65,10 +73,10 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing): Boolean = side != EnumFacing.UP
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction): Boolean = side != Direction.UP
- override protected def connector(side: EnumFacing) = Option(if (side != EnumFacing.UP) node else null)
+ override protected def connector(side: Direction) = Option(if (side != Direction.UP) node else null)
override def energyThroughput: Double = Settings.get.disassemblerRate
@@ -82,10 +90,10 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
override def updateEntity() {
super.updateEntity()
- if (isServer && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (isServer && getLevel.getGameTime % Settings.get.tickFrequency == 0) {
if (queue.isEmpty) {
- val instant = disassembleNextInstantly // Is reset via decrStackSize
- disassemble(decrStackSize(0, 1), instant)
+ val instant = disassembleNextInstantly // Is reset via removeItem
+ disassemble(removeItem(0, 1), instant)
setActive(queue.nonEmpty)
}
else {
@@ -100,7 +108,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
while (buffer >= Settings.get.disassemblerItemCost && queue.nonEmpty) {
buffer -= Settings.get.disassemblerItemCost
val stack = queue.remove(0)
- if (disassembleNextInstantly || getWorld.rand.nextDouble >= Settings.get.disassemblerBreakChance) {
+ if (disassembleNextInstantly || getLevel.random.nextDouble >= Settings.get.disassemblerBreakChance) {
drop(stack)
}
}
@@ -111,8 +119,8 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
def disassemble(stack: ItemStack, instant: Boolean = false) {
// Validate the item, never trust Minecraft / other Mods on anything!
- if (isItemValidForSlot(0, stack)) {
- val ingredients = ItemUtils.getIngredients(stack)
+ if (canPlaceItem(0, stack)) {
+ val ingredients = ItemUtils.getIngredients(getLevel.getRecipeManager, stack)
DisassemblerTemplates.select(stack) match {
case Some(template) =>
val (stacks, drops) = template.disassemble(stack, ingredients)
@@ -132,11 +140,11 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
private def drop(stack: ItemStack) {
if (!stack.isEmpty) {
- for (side <- EnumFacing.values if stack.getCount > 0) {
+ for (side <- Direction.values if stack.getCount > 0) {
InventoryUtils.insertIntoInventoryAt(stack, BlockPosition(this).offset(side), Some(side.getOpposite))
}
if (stack.getCount > 0) {
- spawnStackInWorld(stack, Option(EnumFacing.UP))
+ spawnStackInWorld(stack, Option(Direction.UP))
}
}
}
@@ -148,55 +156,60 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
private final val TotalTag = Settings.namespace + "total"
private final val IsActiveTag = Settings.namespace + "isActive"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
queue.clear()
- queue ++= nbt.getTagList(QueueTag, NBT.TAG_COMPOUND).
- map((tag: NBTTagCompound) => new ItemStack(tag))
+ queue ++= nbt.getList(QueueTag, NBT.TAG_COMPOUND).
+ map((tag: CompoundNBT) => ItemStack.of(tag))
buffer = nbt.getDouble(BufferTag)
totalRequiredEnergy = nbt.getDouble(TotalTag)
isActive = queue.nonEmpty
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
nbt.setNewTagList(QueueTag, queue)
- nbt.setDouble(BufferTag, buffer)
- nbt.setDouble(TotalTag, totalRequiredEnergy)
+ nbt.putDouble(BufferTag, buffer)
+ nbt.putDouble(TotalTag, totalRequiredEnergy)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
isActive = nbt.getBoolean(IsActiveTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setBoolean(IsActiveTag, isActive)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putBoolean(IsActiveTag, isActive)
}
// ----------------------------------------------------------------------- //
- override def getSizeInventory = 1
+ override def getContainerSize = 1
- override def isItemValidForSlot(i: Int, stack: ItemStack): Boolean =
+ override def canPlaceItem(i: Int, stack: ItemStack): Boolean =
allowDisassembling(stack) &&
- (((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && ItemUtils.getIngredients(stack).nonEmpty) ||
+ (((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && ItemUtils.getIngredients(getLevel.getRecipeManager, stack).nonEmpty) ||
DisassemblerTemplates.select(stack).isDefined)
- private def allowDisassembling(stack: ItemStack) = !stack.isEmpty && (!stack.hasTagCompound || !stack.getTagCompound.getBoolean(Settings.namespace + "undisassemblable"))
+ private def allowDisassembling(stack: ItemStack) = !stack.isEmpty && (!stack.hasTag || !stack.getTag.getBoolean(Settings.namespace + "undisassemblable"))
- override def setInventorySlotContents(slot: Int, stack: ItemStack): Unit = {
- super.setInventorySlotContents(slot, stack)
- if (!getWorld.isRemote) {
+ override def setItem(slot: Int, stack: ItemStack): Unit = {
+ super.setItem(slot, stack)
+ if (!getLevel.isClientSide) {
disassembleNextInstantly = false
}
}
- override def onSetInventorySlotContents(player: EntityPlayer, slot: Int, stack: ItemStack): Unit = {
- if (!getWorld.isRemote) {
- disassembleNextInstantly = !stack.isEmpty && slot == 0 && player.capabilities.isCreativeMode
+ override def onSetInventorySlotContents(player: PlayerEntity, slot: Int, stack: ItemStack): Unit = {
+ if (!getLevel.isClientSide) {
+ disassembleNextInstantly = !stack.isEmpty && slot == 0 && player.isCreative
}
}
+
+ // ----------------------------------------------------------------------- //
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Disassembler(ContainerTypes.DISASSEMBLER, id, playerInventory, this)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/DiskDrive.scala b/src/main/scala/li/cil/oc/common/tileentity/DiskDrive.scala
index d206db2260..00362d76d5 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/DiskDrive.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/DiskDrive.scala
@@ -18,19 +18,27 @@ import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.Slot
import li.cil.oc.common.Sound
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.InventoryUtils
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
+
+class DiskDrive(selfType: TileEntityType[_ <: DiskDrive]) extends TileEntity(selfType) with traits.Environment
+ with traits.ComponentInventory with traits.Rotatable with Analyzable with DeviceInfo with INamedContainerProvider {
-class DiskDrive extends traits.Environment with traits.ComponentInventory with traits.Rotatable with Analyzable with DeviceInfo {
// Used on client side to check whether to render disk activity indicators.
var lastAccess = 0L
@@ -63,14 +71,14 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
@Callback(doc = "function([velocity:number]):boolean -- Eject the currently present medium from the drive.")
def eject(context: Context, args: Arguments): Array[AnyRef] = {
val velocity = args.optDouble(0, 0) max 0 min 1
- val ejected = decrStackSize(0, 1)
+ val ejected = removeItem(0, 1)
if (!ejected.isEmpty) {
val entity = InventoryUtils.spawnStackInWorld(position, ejected, Option(facing))
if (entity != null) {
- val vx = facing.getFrontOffsetX * velocity
- val vy = facing.getFrontOffsetY * velocity
- val vz = facing.getFrontOffsetZ * velocity
- entity.addVelocity(vx, vy, vz)
+ val vx = facing.getStepX * velocity
+ val vy = facing.getStepY * velocity
+ val vz = facing.getStepZ * velocity
+ entity.push(vx, vy, vz)
}
result(true)
}
@@ -80,7 +88,7 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
@Callback(doc = "function(): string -- Return the internal floppy disk address")
def media(context: Context, args: Arguments): Array[AnyRef] = {
if (filesystemNode.isEmpty)
- result(Unit, "drive is empty")
+ result((), "drive is empty")
else
result(filesystemNode.head.address)
}
@@ -88,18 +96,24 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
// ----------------------------------------------------------------------- //
// Analyzable
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = filesystemNode.fold(null: Array[Node])(Array(_))
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = filesystemNode.fold(null: Array[Node])(Array(_))
// ----------------------------------------------------------------------- //
// IInventory
- override def getSizeInventory = 1
+ override def getContainerSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
case (0, Some(driver)) => driver.slot(stack) == Slot.Floppy
case _ => false
}
+ // ----------------------------------------------------------------------- //
+ // INamedContainerProvider
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.DiskDrive(ContainerTypes.DISK_DRIVE, id, playerInventory, this)
+
// ----------------------------------------------------------------------- //
// ComponentInventory
@@ -130,16 +144,16 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
private final val DiskTag = Settings.namespace + "disk"
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- if (nbt.hasKey(DiskTag)) {
- setInventorySlotContents(0, new ItemStack(nbt.getCompoundTag(DiskTag)))
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ if (nbt.contains(DiskTag)) {
+ setItem(0, ItemStack.of(nbt.getCompound(DiskTag)))
}
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- if (!items(0).isEmpty) nbt.setNewCompoundTag(DiskTag, items(0).writeToNBT)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ if (!items(0).isEmpty) nbt.setNewCompoundTag(DiskTag, items(0).save)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Geolyzer.scala b/src/main/scala/li/cil/oc/common/tileentity/Geolyzer.scala
index f5e8e9bb89..3cddb4f001 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Geolyzer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Geolyzer.scala
@@ -1,20 +1,22 @@
package li.cil.oc.common.tileentity
import li.cil.oc.server.component
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
-class Geolyzer extends traits.Environment {
+class Geolyzer(selfType: TileEntityType[_ <: Geolyzer]) extends TileEntity(selfType) with traits.Environment {
val geolyzer = new component.Geolyzer(this)
def node = geolyzer.node
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- geolyzer.load(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ geolyzer.loadData(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- geolyzer.save(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ geolyzer.saveData(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala
index 74ef1c8aa3..718770fb75 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala
@@ -13,19 +13,21 @@ import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network._
import li.cil.oc.common.SaveHandler
import li.cil.oc.server.{PacketSender => ServerPacketSender}
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraft.util.math.AxisAlignedBB
-import net.minecraft.util.math.Vec3d
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
-class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment with Analyzable with traits.RotatableTile with traits.Tickable with DeviceInfo {
- def this() = this(0)
+class Hologram(selfType: TileEntityType[_ <: Hologram], var tier: Int) extends TileEntity(selfType) with traits.Environment with SidedEnvironment with Analyzable with traits.RotatableTile with traits.Tickable with DeviceInfo {
+ def this(selfType: TileEntityType[_ <: Hologram]) = this(selfType, 0)
val node = api.Network.newNode(this, Visibility.Network).
withComponent("hologram").
@@ -57,7 +59,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
var scale = 1.0
// Projection Y position offset - consider adding X,Z later perhaps
- var translation = new Vec3d(0, 0, 0)
+ var translation = new Vector3d(0, 0, 0)
// Relative number of lit columns (for energy cost).
var litRatio = -1.0
@@ -130,13 +132,13 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing) = toLocal(side) == EnumFacing.DOWN
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction) = toLocal(side) == Direction.DOWN
- override def sidedNode(side: EnumFacing) = if (toLocal(side) == EnumFacing.DOWN) node else null
+ override def sidedNode(side: Direction) = if (toLocal(side) == Direction.DOWN) node else null
// Override automatic analyzer implementation for sided environments.
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(node)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(node)
// ----------------------------------------------------------------------- //
@@ -289,7 +291,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
val ty = math.max(0, math.min(maxTranslation * 2, args.checkDouble(1)))
val tz = math.max(-maxTranslation, math.min(maxTranslation, args.checkDouble(2)))
- translation = new Vec3d(tx, ty, tz)
+ translation = new Vector3d(tx, ty, tz)
ServerPacketSender.sendHologramOffset(this)
null
@@ -337,7 +339,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
result(true)
}
- else result(Unit, "not supported")
+ else result((), "not supported")
}
@Callback(doc = """function(speed:number, x:number, y:number, z:number):boolean -- Set the rotation speed of the displayed hologram.""")
@@ -356,7 +358,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
result(true)
}
- else result(Unit, "not supported")
+ else result((), "not supported")
}
@Callback(direct = true, doc = "function():number, number, number -- Get the dimension of the x,y,z axes.")
@@ -410,7 +412,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
ServerPacketSender.sendHologramValues(this)
resetDirtyFlag()
}
- if (getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (getLevel.getGameTime % Settings.get.tickFrequency == 0) {
if (litRatio < 0) this.synchronized {
litRatio = 0
for (i <- volume.indices) {
@@ -431,9 +433,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
// ----------------------------------------------------------------------- //
- override def shouldRenderInPass(pass: Int) = pass == 1
-
- override def getMaxRenderDistanceSquared = scale / Settings.get.hologramMaxScaleByTier.max * Settings.get.hologramRenderDistance * Settings.get.hologramRenderDistance
+ override def getViewDistance = scale / Settings.get.hologramMaxScaleByTier.max * Settings.get.hologramRenderDistance
def getFadeStartDistanceSquared = scale / Settings.get.hologramMaxScaleByTier.max * Settings.get.hologramFadeStartDistance * Settings.get.hologramFadeStartDistance
@@ -476,9 +476,9 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
private final val RotationSpeedZTag = Settings.namespace + "rotationSpeedZ"
private final val HasPowerTag = Settings.namespace + "hasPower"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
+ override def loadForServer(nbt: CompoundNBT) {
tier = nbt.getByte(TierTag) max 0 min 1
- super.readFromNBTForServer(nbt)
+ super.loadForServer(nbt)
val tag = SaveHandler.loadNBT(nbt, dataPath)
tag.getIntArray(VolumeTag).copyToArray(volume)
tag.getIntArray(ColorsTag).map(convertColor).copyToArray(colors)
@@ -486,7 +486,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
val tx = nbt.getDouble(OffsetXTag)
val ty = nbt.getDouble(OffsetYTag)
val tz = nbt.getDouble(OffsetZTag)
- translation = new Vec3d(tx, ty, tz)
+ translation = new Vector3d(tx, ty, tz)
rotationAngle = nbt.getFloat(RotationAngleTag)
rotationX = nbt.getFloat(RotationXTag)
rotationY = nbt.getFloat(RotationYTag)
@@ -497,30 +497,30 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
rotationSpeedZ = nbt.getFloat(RotationSpeedZTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) = this.synchronized {
- nbt.setByte(TierTag, tier.toByte)
- super.writeToNBTForServer(nbt)
- SaveHandler.scheduleSave(getWorld, x, z, nbt, dataPath, tag => {
- tag.setIntArray(VolumeTag, volume)
- tag.setIntArray(ColorsTag, colors.map(convertColor))
+ override def saveForServer(nbt: CompoundNBT) = this.synchronized {
+ nbt.putByte(TierTag, tier.toByte)
+ super.saveForServer(nbt)
+ SaveHandler.scheduleSave(getLevel, x, z, nbt, dataPath, tag => {
+ tag.putIntArray(VolumeTag, volume)
+ tag.putIntArray(ColorsTag, colors.map(convertColor))
})
- nbt.setDouble(ScaleTag, scale)
- nbt.setDouble(OffsetXTag, translation.x)
- nbt.setDouble(OffsetYTag, translation.y)
- nbt.setDouble(OffsetZTag, translation.z)
- nbt.setFloat(RotationAngleTag, rotationAngle)
- nbt.setFloat(RotationXTag, rotationX)
- nbt.setFloat(RotationYTag, rotationY)
- nbt.setFloat(RotationZTag, rotationZ)
- nbt.setFloat(RotationSpeedTag, rotationSpeed)
- nbt.setFloat(RotationSpeedXTag, rotationSpeedX)
- nbt.setFloat(RotationSpeedYTag, rotationSpeedY)
- nbt.setFloat(RotationSpeedZTag, rotationSpeedZ)
+ nbt.putDouble(ScaleTag, scale)
+ nbt.putDouble(OffsetXTag, translation.x)
+ nbt.putDouble(OffsetYTag, translation.y)
+ nbt.putDouble(OffsetZTag, translation.z)
+ nbt.putFloat(RotationAngleTag, rotationAngle)
+ nbt.putFloat(RotationXTag, rotationX)
+ nbt.putFloat(RotationYTag, rotationY)
+ nbt.putFloat(RotationZTag, rotationZ)
+ nbt.putFloat(RotationSpeedTag, rotationSpeed)
+ nbt.putFloat(RotationSpeedXTag, rotationSpeedX)
+ nbt.putFloat(RotationSpeedYTag, rotationSpeedY)
+ nbt.putFloat(RotationSpeedZTag, rotationSpeedZ)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
nbt.getIntArray(VolumeTag).copyToArray(volume)
nbt.getIntArray(ColorsTag).copyToArray(colors)
scale = nbt.getDouble(ScaleTag)
@@ -528,7 +528,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
val tx = nbt.getDouble(OffsetXTag)
val ty = nbt.getDouble(OffsetYTag)
val tz = nbt.getDouble(OffsetZTag)
- translation = new Vec3d(tx, ty, tz)
+ translation = new Vector3d(tx, ty, tz)
rotationAngle = nbt.getFloat(RotationAngleTag)
rotationX = nbt.getFloat(RotationXTag)
rotationY = nbt.getFloat(RotationYTag)
@@ -539,22 +539,22 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
rotationSpeedZ = nbt.getFloat(RotationSpeedZTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setIntArray(VolumeTag, volume)
- nbt.setIntArray(ColorsTag, colors)
- nbt.setDouble(ScaleTag, scale)
- nbt.setBoolean(HasPowerTag, hasPower)
- nbt.setDouble(OffsetXTag, translation.x)
- nbt.setDouble(OffsetYTag, translation.y)
- nbt.setDouble(OffsetZTag, translation.z)
- nbt.setFloat(RotationAngleTag, rotationAngle)
- nbt.setFloat(RotationXTag, rotationX)
- nbt.setFloat(RotationYTag, rotationY)
- nbt.setFloat(RotationZTag, rotationZ)
- nbt.setFloat(RotationSpeedTag, rotationSpeed)
- nbt.setFloat(RotationSpeedXTag, rotationSpeedX)
- nbt.setFloat(RotationSpeedYTag, rotationSpeedY)
- nbt.setFloat(RotationSpeedZTag, rotationSpeedZ)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putIntArray(VolumeTag, volume)
+ nbt.putIntArray(ColorsTag, colors)
+ nbt.putDouble(ScaleTag, scale)
+ nbt.putBoolean(HasPowerTag, hasPower)
+ nbt.putDouble(OffsetXTag, translation.x)
+ nbt.putDouble(OffsetYTag, translation.y)
+ nbt.putDouble(OffsetZTag, translation.z)
+ nbt.putFloat(RotationAngleTag, rotationAngle)
+ nbt.putFloat(RotationXTag, rotationX)
+ nbt.putFloat(RotationYTag, rotationY)
+ nbt.putFloat(RotationZTag, rotationZ)
+ nbt.putFloat(RotationSpeedTag, rotationSpeed)
+ nbt.putFloat(RotationSpeedXTag, rotationSpeedX)
+ nbt.putFloat(RotationSpeedYTag, rotationSpeedY)
+ nbt.putFloat(RotationSpeedZTag, rotationSpeedZ)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Keyboard.scala b/src/main/scala/li/cil/oc/common/tileentity/Keyboard.scala
index 1ffbfe301a..bf6d1e9f4a 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Keyboard.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Keyboard.scala
@@ -6,14 +6,16 @@ import li.cil.oc.api
import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-class Keyboard extends traits.Environment with traits.Rotatable with traits.ImmibisMicroblock with SidedEnvironment with Analyzable {
- override def validFacings = EnumFacing.values
+class Keyboard(selfType: TileEntityType[_ <: Keyboard]) extends TileEntity(selfType) with traits.Environment with traits.Rotatable with traits.ImmibisMicroblock with SidedEnvironment with Analyzable {
+ override def validFacings = Direction.values
val keyboard = {
val keyboardItem = api.Items.get(Constants.BlockName.Keyboard).createItemStack(1)
@@ -22,18 +24,18 @@ class Keyboard extends traits.Environment with traits.Rotatable with traits.Immi
override def node = keyboard.node
- def hasNodeOnSide(side: EnumFacing) : Boolean =
+ def hasNodeOnSide(side: Direction) : Boolean =
side != facing && (isOnWall || side.getOpposite != forward)
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing) = hasNodeOnSide(side)
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction) = hasNodeOnSide(side)
- override def sidedNode(side: EnumFacing) = if (hasNodeOnSide(side)) node else null
+ override def sidedNode(side: Direction) = if (hasNodeOnSide(side)) node else null
// Override automatic analyzer implementation for sided environments.
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(node)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(node)
// ----------------------------------------------------------------------- //
@@ -41,23 +43,23 @@ class Keyboard extends traits.Environment with traits.Rotatable with traits.Immi
private final val KeyboardTag = Settings.namespace + "keyboard"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
if (isServer) {
- keyboard.load(nbt.getCompoundTag(KeyboardTag))
+ keyboard.loadData(nbt.getCompound(KeyboardTag))
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
if (isServer) {
- nbt.setNewCompoundTag(KeyboardTag, keyboard.save)
+ nbt.setNewCompoundTag(KeyboardTag, keyboard.saveData)
}
}
// ----------------------------------------------------------------------- //
- private def isOnWall = facing != EnumFacing.UP && facing != EnumFacing.DOWN
+ private def isOnWall = facing != Direction.UP && facing != Direction.DOWN
- private def forward = if (isOnWall) EnumFacing.UP else yaw
+ private def forward = if (isOnWall) Direction.UP else yaw
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala
index b3c256206f..84b09653e7 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala
@@ -1,6 +1,7 @@
package li.cil.oc.common.tileentity
import java.util
+import java.util.function.Consumer
import li.cil.oc.Constants
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
@@ -19,18 +20,21 @@ import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.ISidedInventory
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.JavaConverters.asJavaIterable
+import scala.collection.convert.ImplicitConversionsToJava._
-class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.Computer with ISidedInventory with internal.Microcontroller with DeviceInfo {
+class Microcontroller(selfType: TileEntityType[_ <: Microcontroller]) extends TileEntity(selfType) with traits.PowerAcceptor with traits.Hub with traits.Computer with ISidedInventory with internal.Microcontroller with DeviceInfo {
val info = new MicrocontrollerData()
override def node = null
@@ -60,31 +64,31 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
DeviceAttribute.Description -> "Microcontroller",
DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor,
DeviceAttribute.Product -> "Cubicle",
- DeviceAttribute.Capacity -> getSizeInventory.toString
+ DeviceAttribute.Capacity -> getContainerSize.toString
)
override def getDeviceInfo: util.Map[String, String] = deviceInfo
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing): Boolean = side != facing
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction): Boolean = side != facing
- override def sidedNode(side: EnumFacing): Node = if (side != facing) super.sidedNode(side) else null
+ override def sidedNode(side: Direction): Node = if (side != facing) super.sidedNode(side) else null
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing): Boolean = side != facing
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction): Boolean = side != facing
- override protected def connector(side: EnumFacing) = Option(if (side != facing) snooperNode else null)
+ override protected def connector(side: Direction) = Option(if (side != facing) snooperNode else null)
override def energyThroughput: Double = Settings.get.caseRate(Tier.One)
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
super.onAnalyze(player, side, hitX, hitY, hitZ)
if (side != facing)
- Array(componentNodes(side.getIndex))
+ Array(componentNodes(side.get3DDataValue))
else
Array(machine.node)
}
@@ -133,8 +137,8 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
super.updateEntity()
// Pump energy into the internal network.
- if (isServer && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
- for (side <- EnumFacing.values if side != facing) {
+ if (isServer && getLevel.getGameTime % Settings.get.tickFrequency == 0) {
+ for (side <- Direction.values if side != facing) {
sidedNode(side) match {
case connector: Connector =>
val demand = snooperNode.globalBufferSize - snooperNode.globalBuffer
@@ -192,7 +196,7 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
override def onMessage(message: Message): Unit = {
if (message.name == "network.message" && message.source.network == snooperNode.network) {
- for (side <- EnumFacing.values if outputSides(side.ordinal) && side != facing) {
+ for (side <- Direction.values if outputSides(side.ordinal) && side != facing) {
sidedNode(side).sendToReachable(message.name, message.data: _*)
}
}
@@ -205,44 +209,44 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
private final val ComponentNodesTag = Settings.namespace + "componentNodes"
private final val SnooperTag = Settings.namespace + "snooper"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
+ override def loadForServer(nbt: CompoundNBT) {
// Load info before inventory and such, to avoid initializing components
// to empty inventory.
- info.load(nbt.getCompoundTag(InfoTag))
+ info.loadData(nbt.getCompound(InfoTag))
nbt.getBooleanArray(OutputsTag)
- nbt.getTagList(ComponentNodesTag, NBT.TAG_COMPOUND).toArray[NBTTagCompound].
+ nbt.getList(ComponentNodesTag, NBT.TAG_COMPOUND).toTagArray[CompoundNBT].
zipWithIndex.foreach {
- case (tag, index) => componentNodes(index).load(tag)
+ case (tag, index) => componentNodes(index).loadData(tag)
}
- snooperNode.load(nbt.getCompoundTag(SnooperTag))
- super.readFromNBTForServer(nbt)
+ snooperNode.loadData(nbt.getCompound(SnooperTag))
+ super.loadForServer(nbt)
api.Network.joinNewNetwork(machine.node)
machine.node.connect(snooperNode)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setNewCompoundTag(InfoTag, info.save)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.setNewCompoundTag(InfoTag, info.saveData)
nbt.setBooleanArray(OutputsTag, outputSides)
nbt.setNewTagList(ComponentNodesTag, componentNodes.map {
case node: Node =>
- val tag = new NBTTagCompound()
- node.save(tag)
+ val tag = new CompoundNBT()
+ node.saveData(tag)
tag
- case _ => new NBTTagCompound()
+ case _ => new CompoundNBT()
})
- nbt.setNewCompoundTag(SnooperTag, snooperNode.save)
+ nbt.setNewCompoundTag(SnooperTag, snooperNode.saveData)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound) {
- info.load(nbt.getCompoundTag(InfoTag))
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT) {
+ info.loadData(nbt.getCompound(InfoTag))
+ super.loadForClient(nbt)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setNewCompoundTag(InfoTag, info.save)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.setNewCompoundTag(InfoTag, info.saveData)
}
// ----------------------------------------------------------------------- //
@@ -251,38 +255,47 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
override def updateItems(slot: Int, stack: ItemStack): Unit = info.components(slot) = stack
- override def getSizeInventory: Int = info.components.length
+ override def getContainerSize: Int = info.components.length
- override def isItemValidForSlot(slot: Int, stack: ItemStack) = false
+ override def canPlaceItem(slot: Int, stack: ItemStack) = false
// Nope.
- override def setInventorySlotContents(slot: Int, stack: ItemStack) {}
+ override def setItem(slot: Int, stack: ItemStack) {}
// Nope.
- override def decrStackSize(slot: Int, amount: Int) = ItemStack.EMPTY
+ override def removeItem(slot: Int, amount: Int) = ItemStack.EMPTY
// Nope.
- override def removeStackFromSlot(slot: Int) = ItemStack.EMPTY
+ override def removeItemNoUpdate(slot: Int) = ItemStack.EMPTY
// Nope.
- override def canExtractItem(slot: Int, stack: ItemStack, side: EnumFacing) = false
+ override def canTakeItemThroughFace(slot: Int, stack: ItemStack, side: Direction) = false
- override def canInsertItem(slot: Int, stack: ItemStack, side: EnumFacing) = false
+ override def canPlaceItemThroughFace(slot: Int, stack: ItemStack, side: Direction) = false
- override def getSlotsForFace(side: EnumFacing): Array[Int] = Array()
+ override def getSlotsForFace(side: Direction): Array[Int] = Array()
// For hotswapping EEPROMs.
def changeEEPROM(newEeprom: ItemStack): StackOption = {
val oldEepromIndex = info.components.indexWhere(api.Items.get(_) == api.Items.get(Constants.ItemName.EEPROM))
if (oldEepromIndex >= 0) {
val oldEeprom = info.components(oldEepromIndex)
- super.setInventorySlotContents(oldEepromIndex, newEeprom)
+ super.setItem(oldEepromIndex, newEeprom)
SomeStack(oldEeprom)
}
else {
- assert(info.components(getSizeInventory - 1).isEmpty)
- super.setInventorySlotContents(getSizeInventory - 1, newEeprom)
+ assert(info.components(getContainerSize - 1).isEmpty)
+ super.setItem(getContainerSize - 1, newEeprom)
EmptyStack
}
}
+
+ // Uses the loot system, so still nope.
+ override def forAllLoot(dst: Consumer[ItemStack]) = ()
+
+ // Nope.
+ override def dropSlot(slot: Int, count: Int = getMaxStackSize, direction: Option[Direction]) = false
+
+ // Nope.
+ override def dropAllSlots() = ()
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/MotionSensor.scala b/src/main/scala/li/cil/oc/common/tileentity/MotionSensor.scala
index 9d09d5d0d5..0f6218e8d2 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/MotionSensor.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/MotionSensor.scala
@@ -2,9 +2,11 @@ package li.cil.oc.common.tileentity
import li.cil.oc.api.network.Node
import li.cil.oc.server.component
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
-class MotionSensor extends traits.Environment with traits.Tickable {
+class MotionSensor(selfType: TileEntityType[_ <: MotionSensor]) extends TileEntity(selfType) with traits.Environment with traits.Tickable {
val motionSensor = new component.MotionSensor(this)
def node: Node = motionSensor.node
@@ -16,13 +18,13 @@ class MotionSensor extends traits.Environment with traits.Tickable {
}
}
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- motionSensor.load(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ motionSensor.loadData(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- motionSensor.save(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ motionSensor.saveData(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala b/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala
index d7d8e264e0..ccc3b44d23 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala
@@ -10,17 +10,20 @@ import li.cil.oc.api.network.{Node, Visibility}
import li.cil.oc.common.EventHandler
import li.cil.oc.common.tileentity.traits.RedstoneChangedEventArgs
import li.cil.oc.server.{PacketSender => ServerPacketSender}
-import net.minecraft.init.SoundEvents
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import li.cil.oc.util.RotationHelper
+import net.minecraft.util.SoundEvents
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraft.util.SoundCategory
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
-class NetSplitter extends traits.Environment with traits.OpenSides with traits.RedstoneAware with api.network.SidedEnvironment with DeviceInfo {
+class NetSplitter(selfType: TileEntityType[_ <: NetSplitter]) extends TileEntity(selfType) with traits.Environment with traits.OpenSides with traits.RedstoneAware with api.network.SidedEnvironment with DeviceInfo {
private lazy val deviceInfo: util.Map[String, String] = Map(
DeviceAttribute.Class -> DeviceClass.Network,
DeviceAttribute.Description -> "Ethernet controller",
@@ -40,9 +43,9 @@ class NetSplitter extends traits.Environment with traits.OpenSides with traits.R
var isInverted = false
- override def isSideOpen(side: EnumFacing): Boolean = if (isInverted) !super.isSideOpen(side) else super.isSideOpen(side)
+ override def isSideOpen(side: Direction): Boolean = if (isInverted) !super.isSideOpen(side) else super.isSideOpen(side)
- override def setSideOpen(side: EnumFacing, value: Boolean) {
+ override def setSideOpen(side: Direction, value: Boolean) {
val previous = isSideOpen(side)
super.setSideOpen(side, value)
if (previous != isSideOpen(side)) {
@@ -50,21 +53,21 @@ class NetSplitter extends traits.Environment with traits.OpenSides with traits.R
node.remove()
api.Network.joinOrCreateNetwork(this)
ServerPacketSender.sendNetSplitterState(this)
- getWorld.playSound(null, x + 0.5, y + 0.5, z + 0.5, SoundEvents.BLOCK_PISTON_EXTEND, SoundCategory.BLOCKS, 0.5f, getWorld.rand.nextFloat() * 0.25f + 0.7f)
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, false)
+ getLevel.playSound(null, getBlockPos, SoundEvents.PISTON_EXTEND, SoundCategory.BLOCKS, 0.5f, getLevel.random.nextFloat() * 0.25f + 0.7f)
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
}
else {
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
}
// ----------------------------------------------------------------------- //
- override def sidedNode(side: EnumFacing): Node = if (isSideOpen(side)) node else null
+ override def sidedNode(side: Direction): Node = if (isSideOpen(side)) node else null
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing): Boolean = isSideOpen(side)
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction): Boolean = isSideOpen(side)
// ----------------------------------------------------------------------- //
@@ -84,10 +87,10 @@ class NetSplitter extends traits.Environment with traits.OpenSides with traits.R
node.remove()
api.Network.joinOrCreateNetwork(this)
ServerPacketSender.sendNetSplitterState(this)
- getWorld.playSound(null, x + 0.5, y + 0.5, z + 0.5, SoundEvents.BLOCK_PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5f, getWorld.rand.nextFloat() * 0.25f + 0.7f)
+ getLevel.playSound(null, getBlockPos, SoundEvents.PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5f, getLevel.random.nextFloat() * 0.25f + 0.7f)
}
else {
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
}
@@ -97,37 +100,37 @@ class NetSplitter extends traits.Environment with traits.OpenSides with traits.R
private final val IsInvertedTag = Settings.namespace + "isInverted"
private final val OpenSidesTag = Settings.namespace + "openSides"
- override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT): Unit = {
+ super.loadForServer(nbt)
isInverted = nbt.getBoolean(IsInvertedTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
- nbt.setBoolean(IsInvertedTag, isInverted)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
+ nbt.putBoolean(IsInvertedTag, isInverted)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT): Unit = {
+ super.loadForClient(nbt)
isInverted = nbt.getBoolean(IsInvertedTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForClient(nbt)
- nbt.setBoolean(IsInvertedTag, isInverted)
+ override def saveForClient(nbt: CompoundNBT): Unit = {
+ super.saveForClient(nbt)
+ nbt.putBoolean(IsInvertedTag, isInverted)
}
// component api
def currentStatus(): mutable.Map[Int, Boolean] = {
val openStatus = mutable.Map[Int, Boolean]()
- for (side <- EnumFacing.VALUES) {
+ for (side <- Direction.values) {
openStatus += side.ordinal() -> isSideOpen(side)
}
openStatus
}
- def setSide(side: EnumFacing, state: Boolean): Boolean = {
+ def setSide(side: Direction, state: Boolean): Boolean = {
val previous = isSideOpen(side) // isSideOpen uses inverter
setSideOpen(side, if (isInverted) !state else state) // but setSideOpen does not
previous != state
@@ -137,7 +140,7 @@ class NetSplitter extends traits.Environment with traits.OpenSides with traits.R
def setSides(context: Context, args: Arguments): Array[AnyRef] = {
val settings = args.checkTable(0)
val previous = currentStatus()
- for (side <- EnumFacing.VALUES) {
+ for (side <- Direction.values) {
val ordinal = side.ordinal()
val value = if (settings.containsKey(ordinal)) {
settings.get(ordinal) match {
@@ -156,8 +159,8 @@ class NetSplitter extends traits.Environment with traits.OpenSides with traits.R
def setSideHelper(args: Arguments, value: Boolean): Array[AnyRef] = {
val sideIndex = args.checkInteger(0)
if (sideIndex < 0 || sideIndex > 5)
- return result(Unit, "invalid direction")
- val side = EnumFacing.getFront(sideIndex)
+ return result((), "invalid direction")
+ val side = Direction.from3DDataValue(sideIndex)
result(setSide(side, value))
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/PowerConverter.scala b/src/main/scala/li/cil/oc/common/tileentity/PowerConverter.scala
index cf6ad933b8..598fc534ef 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/PowerConverter.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/PowerConverter.scala
@@ -9,13 +9,15 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.DeviceInfo
import li.cil.oc.api.network._
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
-class PowerConverter extends traits.PowerAcceptor with traits.Environment with traits.NotAnalyzable with DeviceInfo {
+class PowerConverter(selfType: TileEntityType[_ <: PowerConverter]) extends TileEntity(selfType) with traits.PowerAcceptor with traits.Environment with traits.NotAnalyzable with DeviceInfo {
val node = api.Network.newNode(this, Visibility.None).
withConnector(Settings.get.bufferConverter).
create()
@@ -30,10 +32,10 @@ class PowerConverter extends traits.PowerAcceptor with traits.Environment with t
override def getDeviceInfo: util.Map[String, String] = deviceInfo
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing) = true
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction) = true
- override protected def connector(side: EnumFacing) = Option(node)
+ override protected def connector(side: Direction) = Option(node)
override def energyThroughput = Settings.get.powerConverterRate
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/PowerDistributor.scala b/src/main/scala/li/cil/oc/common/tileentity/PowerDistributor.scala
index 12984473d9..83a5716dd0 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/PowerDistributor.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/PowerDistributor.scala
@@ -4,13 +4,15 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.network._
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-class PowerDistributor extends traits.Environment with traits.PowerBalancer with traits.NotAnalyzable {
+class PowerDistributor(selfType: TileEntityType[_ <: PowerDistributor]) extends TileEntity(selfType) with traits.Environment with traits.PowerBalancer with traits.NotAnalyzable {
val node = null
private val nodes = Array.fill(6)(api.Network.newNode(this, Visibility.None).
@@ -21,30 +23,30 @@ class PowerDistributor extends traits.Environment with traits.PowerBalancer with
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing) = true
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction) = true
- override def sidedNode(side: EnumFacing): Connector = nodes(side.ordinal)
+ override def sidedNode(side: Direction): Connector = nodes(side.ordinal)
// ----------------------------------------------------------------------- //
private final val ConnectorTag = Settings.namespace + "connector"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- nbt.getTagList(ConnectorTag, NBT.TAG_COMPOUND).toArray[NBTTagCompound].
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ nbt.getList(ConnectorTag, NBT.TAG_COMPOUND).toTagArray[CompoundNBT].
zipWithIndex.foreach {
- case (tag, index) => nodes(index).load(tag)
+ case (tag, index) => nodes(index).loadData(tag)
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
// Side check for Waila (and other mods that may call this client side).
if (isServer) {
nbt.setNewTagList(ConnectorTag, nodes.map(connector => {
- val connectorNbt = new NBTTagCompound()
- connector.save(connectorNbt)
+ val connectorNbt = new CompoundNBT()
+ connector.saveData(connectorNbt)
connectorNbt
}))
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Print.scala b/src/main/scala/li/cil/oc/common/tileentity/Print.scala
index 1214010bc7..6123a0a640 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Print.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Print.scala
@@ -6,104 +6,51 @@ import com.google.common.base.Strings
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
+import li.cil.oc.common.block.{Print => PrintBlock}
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity.traits.RedstoneChangedEventArgs
import li.cil.oc.util.ExtendedAABB
import li.cil.oc.util.ExtendedAABB._
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.init.SoundEvents
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util._
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.util.SoundEvents
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraft.util.SoundCategory
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.RayTraceResult
-import net.minecraft.util.math.Vec3d
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-import scala.collection.convert.WrapAsJava._
-
-class Print(val canToggle: Option[() => Boolean], val scheduleUpdate: Option[Int => Unit], val onStateChange: Option[() => Unit]) extends traits.TileEntity with traits.RedstoneAware with traits.RotatableTile {
- def this() = this(None, None, None)
- def this(canToggle: () => Boolean, scheduleUpdate: Int => Unit, onStateChange: () => Unit) = this(Option(canToggle), Option(scheduleUpdate), Option(onStateChange))
+import net.minecraft.util.math.shapes.IBooleanFunction
+import net.minecraft.util.math.shapes.VoxelShape
+import net.minecraft.util.math.shapes.VoxelShapes
+import net.minecraft.util.math.vector.Vector3d
+import net.minecraft.world.server.ServerWorld
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+import net.minecraftforge.client.model.data.IModelData
+import net.minecraftforge.client.model.data.ModelProperty
+import scala.collection.Iterable
+import scala.collection.convert.ImplicitConversionsToJava._
+
+class Print(selfType: TileEntityType[_ <: Print], val canToggle: Option[() => Boolean], val scheduleUpdate: Option[Int => Unit], val onStateChange: Option[() => Unit])
+ extends TileEntity(selfType) with traits.TileEntity with traits.RedstoneAware with traits.RotatableTile with IModelData {
+
+ def this(selfType: TileEntityType[_ <: Print]) = this(selfType, None, None, None)
+ def this(selfType: TileEntityType[_ <: Print], canToggle: () => Boolean, scheduleUpdate: Int => Unit, onStateChange: () => Unit) =
+ this(selfType, Option(canToggle), Option(scheduleUpdate), Option(onStateChange))
_isOutputEnabled = true
val data = new PrintData()
- var boundsOff = ExtendedAABB.unitBounds
- var boundsOn = ExtendedAABB.unitBounds
+ var shapeOff = VoxelShapes.block
+ var shapeOn = VoxelShapes.block
var state = false
- def bounds = if (state) boundsOn else boundsOff
+ def shape = if (state) shapeOn else shapeOff
def noclip = if (state) data.noclipOn else data.noclipOff
def shapes = if (state) data.stateOn else data.stateOff
- def isSideSolid(side: EnumFacing): Boolean = {
- for (shape <- shapes if !Strings.isNullOrEmpty(shape.texture)) {
- val bounds = shape.bounds.rotateTowards(facing)
- val fullX = bounds.minX == 0 && bounds.maxX == 1
- val fullY = bounds.minY == 0 && bounds.maxY == 1
- val fullZ = bounds.minZ == 0 && bounds.maxZ == 1
- if (side match {
- case EnumFacing.DOWN => bounds.minY == 0 && fullX && fullZ
- case EnumFacing.UP => bounds.maxY == 1 && fullX && fullZ
- case EnumFacing.NORTH => bounds.minZ == 0 && fullX && fullY
- case EnumFacing.SOUTH => bounds.maxZ == 1 && fullX && fullY
- case EnumFacing.WEST => bounds.minX == 0 && fullY && fullZ
- case EnumFacing.EAST => bounds.maxX == 1 && fullY && fullZ
- case _ => false
- }) return true
- }
- false
- }
-
- def addCollisionBoxesToList(mask: AxisAlignedBB, list: util.List[AxisAlignedBB], pos: BlockPos = BlockPos.ORIGIN): Unit = {
- if (!noclip) {
- if (shapes.isEmpty) {
- val unitBounds = new AxisAlignedBB(0, 0, 0, 1, 1, 1).offset(pos)
- if (mask == null || unitBounds.intersects(mask)) {
- list.add(unitBounds)
- }
- } else {
- for (shape <- shapes) {
- val bounds = shape.bounds.rotateTowards(facing).offset(pos)
- if (mask == null || bounds.intersects(mask)) {
- list.add(bounds)
- }
- }
- }
- }
- }
-
- def rayTrace(start: Vec3d, end: Vec3d, pos: BlockPos = BlockPos.ORIGIN): RayTraceResult = {
- var closestDistance = Double.PositiveInfinity
- var closest: Option[RayTraceResult] = None
- if (shapes.isEmpty) {
- val bounds = new AxisAlignedBB(0, 0, 0, 1, 1, 1).offset(pos)
- val hit = bounds.calculateIntercept(start, end)
- if (hit != null) {
- val distance = hit.hitVec.distanceTo(start)
- if (distance < closestDistance) {
- closestDistance = distance
- closest = Option(hit)
- }
- }
- } else {
- for (shape <- shapes) {
- val bounds = shape.bounds.rotateTowards(facing).offset(pos)
- val hit = bounds.calculateIntercept(start, end)
- if (hit != null) {
- val distance = hit.hitVec.distanceTo(start)
- if (distance < closestDistance) {
- closestDistance = distance
- closest = Option(hit)
- }
- }
- }
- }
- closest.map(hit => new RayTraceResult(hit.hitVec, hit.sideHit, pos)).orNull
- }
-
def activate(): Boolean = {
if (data.hasActiveState) {
if (!state || !data.isButtonMode) {
@@ -116,7 +63,7 @@ class Print(val canToggle: Option[() => Boolean], val scheduleUpdate: Option[Int
private def buildValueSet(value: Int): util.Map[AnyRef, AnyRef] = {
val map: util.Map[AnyRef, AnyRef] = new util.HashMap[AnyRef, AnyRef]()
- EnumFacing.values.foreach {
+ Direction.values.foreach {
side => map.put(new java.lang.Integer(side.ordinal), new java.lang.Integer(value))
}
map
@@ -125,28 +72,33 @@ class Print(val canToggle: Option[() => Boolean], val scheduleUpdate: Option[Int
def toggleState(): Unit = {
if (canToggle.fold(true)(_.apply())) {
state = !state
- world.playSound(null, x + 0.5, y + 0.5, z + 0.5, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 0.3F, if (state) 0.6F else 0.5F)
- world.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ getLevel.playSound(null, getBlockPos, SoundEvents.LEVER_CLICK, SoundCategory.BLOCKS, 0.3F, if (state) 0.6F else 0.5F)
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
updateRedstone()
if (state && data.isButtonMode) {
- val block = api.Items.get(Constants.BlockName.Print).block()
- val delay = block.tickRate(world)
+ val block = api.Items.get(Constants.BlockName.Print).block().asInstanceOf[PrintBlock]
+ val delay = block.tickRate(getLevel)
scheduleUpdate match {
case Some(callback) => callback(delay)
- case _ => world.scheduleUpdate(getPos, block, delay)
+ case _ if !getLevel.isClientSide => getLevel.asInstanceOf[ServerWorld].getBlockTicks.scheduleTick(getBlockPos, block, delay)
+ case _ =>
}
}
onStateChange.foreach(_.apply())
}
}
- def updateBounds(): Unit = {
- boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.union(b.bounds))
- if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds
- else boundsOff = boundsOff.rotateTowards(facing)
- boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.union(b.bounds))
- if (boundsOn.volume == 0) boundsOn = ExtendedAABB.unitBounds
- else boundsOn = boundsOn.rotateTowards(facing)
+ private def convertShape(state: Iterable[PrintData.Shape]): VoxelShape = if (!state.isEmpty) {
+ state.foldLeft(VoxelShapes.empty)((curr, s) => {
+ val voxel = VoxelShapes.create(s.bounds.rotateTowards(facing))
+ VoxelShapes.joinUnoptimized(curr, voxel, IBooleanFunction.OR)
+ }).optimize()
+ }
+ else VoxelShapes.block
+
+ def updateShape(): Unit = {
+ shapeOff = convertShape(data.stateOff)
+ shapeOn = convertShape(data.stateOn)
}
def updateRedstone(): Unit = {
@@ -164,50 +116,66 @@ class Print(val canToggle: Option[() => Boolean], val scheduleUpdate: Option[Int
override protected def onRotationChanged(): Unit = {
super.onRotationChanged()
- updateBounds()
+ updateShape()
}
// ----------------------------------------------------------------------- //
private final val DataTag = Settings.namespace + "data"
+ @Deprecated
private final val DataTagCompat = "data"
private final val StateTag = Settings.namespace + "state"
+ @Deprecated
private final val StateTagCompat = "state"
- override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(DataTagCompat))
- data.load(nbt.getCompoundTag(DataTagCompat))
+ override def loadForServer(nbt: CompoundNBT): Unit = {
+ super.loadForServer(nbt)
+ if (nbt.contains(DataTagCompat))
+ data.loadData(nbt.getCompound(DataTagCompat))
else
- data.load(nbt.getCompoundTag(DataTag))
- if (nbt.hasKey(StateTagCompat))
+ data.loadData(nbt.getCompound(DataTag))
+ if (nbt.contains(StateTagCompat))
state = nbt.getBoolean(StateTagCompat)
else
state = nbt.getBoolean(StateTag)
- updateBounds()
+ updateShape()
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
- nbt.setNewCompoundTag(DataTag, data.save)
- nbt.setBoolean(StateTag, state)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
+ nbt.setNewCompoundTag(DataTag, data.saveData)
+ nbt.putBoolean(StateTag, state)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForClient(nbt)
- data.load(nbt.getCompoundTag(DataTag))
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT): Unit = {
+ super.loadForClient(nbt)
+ data.loadData(nbt.getCompound(DataTag))
state = nbt.getBoolean(StateTag)
- updateBounds()
- if (world != null) {
- world.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
- if (data.emitLight) world.checkLight(getPos)
+ updateShape()
+ if (getLevel != null) {
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
+ if (data.emitLight) getLevel.getLightEngine.checkBlock(getBlockPos)
}
}
- override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForClient(nbt)
- nbt.setNewCompoundTag(DataTag, data.save)
- nbt.setBoolean(StateTag, state)
+ override def saveForClient(nbt: CompoundNBT): Unit = {
+ super.saveForClient(nbt)
+ nbt.setNewCompoundTag(DataTag, data.saveData)
+ nbt.putBoolean(StateTag, state)
}
+
+ // ----------------------------------------------------------------------- //
+
+ @Deprecated
+ override def getModelData() = this
+
+ @Deprecated
+ override def hasProperty(prop: ModelProperty[_]) = false
+
+ @Deprecated
+ override def getData[T](prop: ModelProperty[T]): T = null.asInstanceOf[T]
+
+ @Deprecated
+ override def setData[T](prop: ModelProperty[T], value: T): T = null.asInstanceOf[T]
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala
index f60e2e2d45..04a8d8034a 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala
@@ -13,22 +13,31 @@ import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network._
import li.cil.oc.api.util.StateAware
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.ISidedInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraft.util.math.AxisAlignedBB
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
+
+class Printer(selfType: TileEntityType[_ <: Printer]) extends TileEntity(selfType) with traits.Environment with traits.Inventory with traits.Rotatable
+ with SidedEnvironment with traits.StateAware with traits.Tickable with ISidedInventory with DeviceInfo with INamedContainerProvider {
-class Printer extends traits.Environment with traits.Inventory with traits.Rotatable with SidedEnvironment with traits.StateAware with traits.Tickable with ISidedInventory with DeviceInfo {
val node: ComponentConnector = api.Network.newNode(this, Visibility.Network).
withComponent("printer3d").
withConnector(Settings.get.bufferConverter).
@@ -61,10 +70,10 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing): Boolean = side != EnumFacing.UP
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction): Boolean = side != Direction.UP
- override def sidedNode(side: EnumFacing): ComponentConnector = if (side != EnumFacing.UP) node else null
+ override def sidedNode(side: Direction): ComponentConnector = if (side != Direction.UP) node else null
override def getCurrentState: util.EnumSet[StateAware.State] = {
if (isPrinting) util.EnumSet.of(api.util.StateAware.State.IsWorking)
@@ -170,7 +179,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
@Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false][,tint:number]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""")
def addShape(context: Context, args: Arguments): Array[Object] = {
if (data.stateOff.size > Settings.get.maxPrintComplexity || data.stateOn.size > Settings.get.maxPrintComplexity) {
- return result(Unit, "model too complex")
+ return result((), "model too complex")
}
val minX = (args.checkInteger(0) max 0 min 16) / 16f
val minY = (args.checkInteger(1) max 0 min 16) / 16f
@@ -197,7 +206,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
texture, tint)
isActive = false // Needs committing.
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
result(true)
}
@@ -211,7 +220,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
@Callback(doc = """function([count:number]):boolean -- Commit and begin printing the current configuration.""")
def commit(context: Context, args: Arguments): Array[Object] = {
if (!canPrint) {
- return result(Unit, "model invalid")
+ return result((), "model invalid")
}
limit = (args.optDouble(0, 1) max 0 min Integer.MAX_VALUE).toInt
isActive = limit > 0
@@ -235,9 +244,9 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
}
def canMergeOutput = {
- val presentStack = getStackInSlot(slotOutput)
+ val presentStack = getItem(slotOutput)
val outputStack = data.createItemStack()
- presentStack.isEmpty || (presentStack.isItemEqual(outputStack) && ItemStack.areItemStackTagsEqual(presentStack, outputStack))
+ presentStack.isEmpty || (presentStack.sameItem(outputStack) && ItemStack.tagMatches(presentStack, outputStack))
}
if (isActive && output.isEmpty && canMergeOutput) {
@@ -265,13 +274,13 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
val have = want + (if (Settings.get.ignorePower) 0 else node.changeBuffer(-want))
requiredEnergy -= have
if (requiredEnergy <= 0) {
- val result = getStackInSlot(slotOutput)
+ val result = getItem(slotOutput)
if (result.isEmpty) {
- setInventorySlotContents(slotOutput, output.get)
+ setItem(slotOutput, output.get)
}
else if (result.getCount < result.getMaxStackSize && canMergeOutput /* Should never fail, but just in case... */ ) {
result.grow(1)
- markDirty()
+ setChanged()
}
else {
return
@@ -282,21 +291,21 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
ServerPacketSender.sendPrinting(this, have > 0.5 && output.isDefined)
}
- val inputValue = PrintData.materialValue(getStackInSlot(slotMaterial))
+ val inputValue = PrintData.materialValue(getItem(slotMaterial))
if (inputValue > 0 && maxAmountMaterial - amountMaterial >= inputValue) {
- val material = decrStackSize(slotMaterial, 1)
+ val material = removeItem(slotMaterial, 1)
if (material != null) {
amountMaterial += inputValue
}
}
- val inkValue = PrintData.inkValue(getStackInSlot(slotInk))
+ val inkValue = PrintData.inkValue(getItem(slotInk))
if (inkValue > 0 && maxAmountInk - amountInk >= inkValue) {
- val material = decrStackSize(slotInk, 1)
+ val material = removeItem(slotInk, 1)
if (material != null) {
amountInk += inkValue
- if (material.getItem.hasContainerItem(material)) {
- setInventorySlotContents(slotInk, material.getItem.getContainerItem(material))
+ if (material.hasContainerItem()) {
+ setItem(slotInk, material.getContainerItem())
}
}
}
@@ -313,15 +322,15 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
private final val TotalTag = Settings.namespace + "total"
private final val RemainingTag = Settings.namespace + "remaining"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- amountMaterial = nbt.getInteger(AmountMaterialTag)
- amountInk = nbt.getInteger(AmountInkTag)
- data.load(nbt.getCompoundTag(DataTag))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ amountMaterial = nbt.getInt(AmountMaterialTag)
+ amountInk = nbt.getInt(AmountInkTag)
+ data.loadData(nbt.getCompound(DataTag))
isActive = nbt.getBoolean(IsActiveTag)
- limit = nbt.getInteger(LimitTag)
- if (nbt.hasKey(OutputTag)) {
- output = StackOption(new ItemStack(nbt.getCompoundTag(OutputTag)))
+ limit = nbt.getInt(LimitTag)
+ if (nbt.contains(OutputTag)) {
+ output = StackOption(ItemStack.of(nbt.getCompound(OutputTag)))
}
else {
output = EmptyStack
@@ -330,36 +339,36 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
requiredEnergy = nbt.getDouble(RemainingTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setInteger(AmountMaterialTag, amountMaterial)
- nbt.setInteger(AmountInkTag, amountInk)
- nbt.setNewCompoundTag(DataTag, data.save)
- nbt.setBoolean(IsActiveTag, isActive)
- nbt.setInteger(LimitTag, limit)
- output.foreach(stack => nbt.setNewCompoundTag(OutputTag, stack.writeToNBT))
- nbt.setDouble(TotalTag, totalRequiredEnergy)
- nbt.setDouble(RemainingTag, requiredEnergy)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.putInt(AmountMaterialTag, amountMaterial)
+ nbt.putInt(AmountInkTag, amountInk)
+ nbt.setNewCompoundTag(DataTag, data.saveData)
+ nbt.putBoolean(IsActiveTag, isActive)
+ nbt.putInt(LimitTag, limit)
+ output.foreach(stack => nbt.setNewCompoundTag(OutputTag, stack.save))
+ nbt.putDouble(TotalTag, totalRequiredEnergy)
+ nbt.putDouble(RemainingTag, requiredEnergy)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- data.load(nbt.getCompoundTag(DataTag))
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ data.loadData(nbt.getCompound(DataTag))
requiredEnergy = nbt.getDouble(RemainingTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setNewCompoundTag(DataTag, data.save)
- nbt.setDouble(RemainingTag, requiredEnergy)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.setNewCompoundTag(DataTag, data.saveData)
+ nbt.putDouble(RemainingTag, requiredEnergy)
}
// ----------------------------------------------------------------------- //
- override def getSizeInventory = 3
+ override def getContainerSize = 3
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean =
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean =
if (slot == slotMaterial)
PrintData.materialValue(stack) > 0
else if (slot == slotInk)
@@ -368,9 +377,14 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
// ----------------------------------------------------------------------- //
- override def getSlotsForFace(side: EnumFacing): Array[Int] = Array(slotMaterial, slotInk, slotOutput)
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Printer(ContainerTypes.PRINTER, id, playerInventory, this)
+
+ // ----------------------------------------------------------------------- //
+
+ override def getSlotsForFace(side: Direction): Array[Int] = Array(slotMaterial, slotInk, slotOutput)
- override def canExtractItem(slot: Int, stack: ItemStack, side: EnumFacing): Boolean = !isItemValidForSlot(slot, stack)
+ override def canTakeItemThroughFace(slot: Int, stack: ItemStack, side: Direction): Boolean = !canPlaceItem(slot, stack)
- override def canInsertItem(slot: Int, stack: ItemStack, side: EnumFacing): Boolean = slot != slotOutput
+ override def canPlaceItemThroughFace(slot: Int, stack: ItemStack, side: Direction): Boolean = slot != slotOutput
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Rack.scala b/src/main/scala/li/cil/oc/common/tileentity/Rack.scala
index eff335baf4..db290aad6e 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Rack.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Rack.scala
@@ -16,25 +16,34 @@ import li.cil.oc.api.network.Packet
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.util.StateAware
import li.cil.oc.common.Slot
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.tileentity.traits.RedstoneChangedEventArgs
import li.cil.oc.integration.opencomputers.DriverRedstoneCard
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedInventory._
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
+import li.cil.oc.util.RotationHelper
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.IInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.nbt.NBTTagIntArray
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.IntArrayNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class Rack(selfType: TileEntityType[_ <: Rack]) extends TileEntity(selfType) with traits.PowerAcceptor with traits.Hub with traits.PowerBalancer
+ with traits.ComponentInventory with traits.Rotatable with traits.BundledRedstoneAware with Analyzable with internal.Rack with traits.StateAware with INamedContainerProvider {
-class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalancer with traits.ComponentInventory with traits.Rotatable with traits.BundledRedstoneAware with Analyzable with internal.Rack with traits.StateAware {
var isRelayEnabled = false
- val lastData = new Array[NBTTagCompound](getSizeInventory)
- val hasChanged: Array[Boolean] = Array.fill(getSizeInventory)(true)
+ val lastData = new Array[CompoundNBT](getContainerSize)
+ val hasChanged: Array[Boolean] = Array.fill(getContainerSize)(true)
// Map node connections for each installed mountable. Each mountable may
// have up to four outgoing connections, with the first one always being
@@ -43,12 +52,12 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
// The other nodes are "secondary" connections and merely transfer network
// messages.
// mountable -> connectable -> side
- val nodeMapping: Array[Array[Option[EnumFacing]]] = Array.fill(getSizeInventory)(Array.fill[Option[EnumFacing]](4)(None))
- val snifferNodes: Array[Array[Node]] = Array.fill(getSizeInventory)(Array.fill(3)(api.Network.newNode(this, Visibility.Neighbors).create()))
+ val nodeMapping: Array[Array[Option[Direction]]] = Array.fill(getContainerSize)(Array.fill[Option[Direction]](4)(None))
+ val snifferNodes: Array[Array[Node]] = Array.fill(getContainerSize)(Array.fill(3)(api.Network.newNode(this, Visibility.Neighbors).create()))
- def connect(slot: Int, connectableIndex: Int, side: Option[EnumFacing]): Unit = {
+ def connect(slot: Int, connectableIndex: Int, side: Option[Direction]): Unit = {
val newSide = side match {
- case Some(direction) if direction != EnumFacing.SOUTH => Option(direction)
+ case Some(direction) if direction != Direction.SOUTH => Option(direction)
case _ => None
}
@@ -93,8 +102,8 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
}
}
- private def reconnect(plugSide: EnumFacing): Unit = {
- for (slot <- 0 until getSizeInventory) {
+ private def reconnect(plugSide: Direction): Unit = {
+ for (slot <- 0 until getContainerSize) {
val mapping = nodeMapping(slot)
mapping(0) match {
case Some(side) if toGlobal(side) == plugSide =>
@@ -125,11 +134,11 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
}
}
- protected def sendPacketToMountables(sourceSide: Option[EnumFacing], packet: Packet): Unit = {
+ protected def sendPacketToMountables(sourceSide: Option[Direction], packet: Packet): Unit = {
// When a message arrives on a bus, also send it to all secondary nodes
// connected to it. Only deliver it to that very node, if it's not the
// sender, to avoid loops.
- for (slot <- 0 until getSizeInventory) {
+ for (slot <- 0 until getContainerSize) {
val mapping = nodeMapping(slot)
for (connectableIndex <- 0 until 3) {
mapping(connectableIndex + 1) match {
@@ -150,7 +159,7 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
// ----------------------------------------------------------------------- //
// Hub
- override def tryEnqueuePacket(sourceSide: Option[EnumFacing], packet: Packet): Boolean = {
+ override def tryEnqueuePacket(sourceSide: Option[Direction], packet: Packet): Boolean = {
sendPacketToMountables(sourceSide, packet)
if (isRelayEnabled)
super.tryEnqueuePacket(sourceSide, packet)
@@ -158,7 +167,7 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
true
}
- override protected def relayPacket(sourceSide: Option[EnumFacing], packet: Packet): Unit = {
+ override protected def relayPacket(sourceSide: Option[Direction], packet: Packet): Unit = {
if (isRelayEnabled)
super.relayPacket(sourceSide, packet)
}
@@ -190,7 +199,7 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
}
private def relayIfMessageFromConnectable(message: Message, packet: Packet): Unit = {
- for (slot <- 0 until getSizeInventory) {
+ for (slot <- 0 until getContainerSize) {
val mountable = getMountable(slot)
if (mountable != null) {
val mapping = nodeMapping(slot)
@@ -212,8 +221,8 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
}
}
- private def relayToConnectablesOnSide(message: Message, packet: Packet, sourceSide: EnumFacing): Unit = {
- for (slot <- 0 until getSizeInventory) {
+ private def relayToConnectablesOnSide(message: Message, packet: Packet, sourceSide: Direction): Unit = {
+ for (slot <- 0 until getContainerSize) {
val mountable = getMountable(slot)
if (mountable != null) {
val mapping = nodeMapping(slot)
@@ -236,24 +245,24 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
// ----------------------------------------------------------------------- //
// SidedEnvironment
- override def canConnect(side: EnumFacing): Boolean = side != facing
+ override def canConnect(side: Direction): Boolean = side != facing
- override def sidedNode(side: EnumFacing): Node = if (side != facing) super.sidedNode(side) else null
+ override def sidedNode(side: Direction): Node = if (side != facing) super.sidedNode(side) else null
// ----------------------------------------------------------------------- //
// power.Common
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing): Boolean = side != facing
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction): Boolean = side != facing
- override protected def connector(side: EnumFacing) = Option(if (side != facing) sidedNode(side).asInstanceOf[Connector] else null)
+ override protected def connector(side: Direction) = Option(if (side != facing) sidedNode(side).asInstanceOf[Connector] else null)
override def energyThroughput: Double = Settings.get.serverRackRate
// ----------------------------------------------------------------------- //
// Analyzable
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
slotAt(side, hitX, hitY, hitZ) match {
case Some(slot) => components(slot) match {
case Some(analyzable: Analyzable) => analyzable.onAnalyze(player, side, hitX, hitY, hitZ)
@@ -273,7 +282,7 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
case _ => null
}
- override def getMountableData(slot: Int): NBTTagCompound = lastData(slot)
+ override def getMountableData(slot: Int): CompoundNBT = lastData(slot)
override def markChanged(slot: Int): Unit = {
hasChanged.synchronized(hasChanged(slot) = true)
@@ -314,26 +323,32 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
// ----------------------------------------------------------------------- //
// IInventory
- override def getSizeInventory = 4
+ override def getContainerSize = 4
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
case (_, Some(driver)) => driver.slot(stack) == Slot.RackMountable
case _ => false
}
- override def markDirty() {
- super.markDirty()
+ override def setChanged() {
+ super.setChanged()
if (isServer) {
setOutputEnabled(hasRedstoneCard)
ServerPacketSender.sendRackInventory(this)
}
else {
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
+ // ----------------------------------------------------------------------- //
+ // INamedContainerProvider
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Rack(ContainerTypes.RACK, id, playerInventory, this)
+
// ----------------------------------------------------------------------- //
// ComponentInventory
@@ -370,7 +385,7 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
override def updateEntity() {
super.updateEntity()
if (isServer && isConnected) {
- lazy val connectors = EnumFacing.VALUES.map(sidedNode).collect {
+ lazy val connectors = Direction.values.map(sidedNode).collect {
case connector: Connector => connector
}
components.zipWithIndex.collect {
@@ -379,7 +394,7 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
hasChanged(slot) = false
lastData(slot) = mountable.getData
ServerPacketSender.sendRackMountableData(this, slot)
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, false)
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
// These are working state dependent, so recompute them.
setOutputEnabled(hasRedstoneCard)
}
@@ -409,54 +424,54 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
private final val LastDataTag = Settings.namespace + "lastData"
private final val RackDataTag = Settings.namespace + "rackData"
- override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT): Unit = {
+ super.loadForServer(nbt)
isRelayEnabled = nbt.getBoolean(IsRelayEnabledTag)
- nbt.getTagList(NodeMappingTag, NBT.TAG_INT_ARRAY).map((buses: NBTTagIntArray) =>
- buses.getIntArray.map(id => if (id < 0 || id == EnumFacing.SOUTH.ordinal()) None else Option(EnumFacing.getFront(id)))).
+ nbt.getList(NodeMappingTag, NBT.TAG_INT_ARRAY).map((buses: IntArrayNBT) =>
+ buses.getAsIntArray.map(id => if (id < 0 || id == Direction.SOUTH.ordinal()) None else Option(Direction.from3DDataValue(id)))).
copyToArray(nodeMapping)
// Kickstart initialization.
_isOutputEnabled = hasRedstoneCard
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
- nbt.setBoolean(IsRelayEnabledTag, isRelayEnabled)
+ nbt.putBoolean(IsRelayEnabledTag, isRelayEnabled)
nbt.setNewTagList(NodeMappingTag, nodeMapping.map(buses =>
toNbt(buses.map(side => side.fold(-1)(_.ordinal())))))
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT): Unit = {
+ super.loadForClient(nbt)
- val data = nbt.getTagList(LastDataTag, NBT.TAG_COMPOUND).
- toArray[NBTTagCompound]
+ val data = nbt.getList(LastDataTag, NBT.TAG_COMPOUND).
+ toTagArray[CompoundNBT]
data.copyToArray(lastData)
- load(nbt.getCompoundTag(RackDataTag))
+ loadData(nbt.getCompound(RackDataTag))
connectComponents()
}
- override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForClient(nbt)
+ override def saveForClient(nbt: CompoundNBT): Unit = {
+ super.saveForClient(nbt)
- val data = lastData.map(tag => if (tag == null) new NBTTagCompound() else tag)
+ val data = lastData.map(tag => if (tag == null) new CompoundNBT() else tag)
nbt.setNewTagList(LastDataTag, data)
- nbt.setNewCompoundTag(RackDataTag, save)
+ nbt.setNewCompoundTag(RackDataTag, saveData)
}
// ----------------------------------------------------------------------- //
- def slotAt(side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Option[Int] = {
+ def slotAt(side: Direction, hitX: Float, hitY: Float, hitZ: Float): Option[Int] = {
if (side == facing) {
val globalY = (hitY * 16).toInt // [0, 15]
val l = 2
val h = 14
- val slot = ((15 - globalY) - l) * getSizeInventory / (h - l)
- Some(math.max(0, math.min(getSizeInventory - 1, slot)))
+ val slot = ((15 - globalY) - l) * getContainerSize / (h - l)
+ Some(math.max(0, math.min(getContainerSize - 1, slot)))
}
else None
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Raid.scala b/src/main/scala/li/cil/oc/common/tileentity/Raid.scala
index 9b21c5523a..ac94acfda1 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Raid.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Raid.scala
@@ -1,6 +1,7 @@
package li.cil.oc.common.tileentity
import java.util.UUID
+import java.util.function.Consumer
import li.cil.oc.Settings
import li.cil.oc.api
@@ -8,20 +9,26 @@ import li.cil.oc.api.Driver
import li.cil.oc.api.fs.Label
import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network.Visibility
-import li.cil.oc.common.item.data.DriveData
import li.cil.oc.common.Slot
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
+import li.cil.oc.common.item.data.DriveData
import li.cil.oc.common.item.data.NodeData
import li.cil.oc.server.component.FileSystem
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-class Raid extends traits.Environment with traits.Inventory with traits.Rotatable with Analyzable {
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class Raid(selfType: TileEntityType[_ <: Raid]) extends TileEntity(selfType) with traits.Environment with traits.Inventory with traits.Rotatable with Analyzable with INamedContainerProvider {
val node = api.Network.newNode(this, Visibility.None).create()
var filesystem: Option[FileSystem] = None
@@ -32,19 +39,19 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
var lastAccess = 0L
// For client side rendering.
- val presence = Array.fill(getSizeInventory)(false)
+ val presence = Array.fill(getContainerSize)(false)
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(filesystem.map(_.node).orNull)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(filesystem.map(_.node).orNull)
// ----------------------------------------------------------------------- //
- override def getSizeInventory = 3
+ override def getContainerSize = 3
- override def getInventoryStackLimit = 1
+ override def getMaxStackSize = 1
- override def isItemValidForSlot(slot: Int, stack: ItemStack) = Option(Driver.driverFor(stack, getClass)) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack) = Option(Driver.driverFor(stack, getClass)) match {
case Some(driver) => driver.slot(stack) == Slot.HDD
case _ => false
}
@@ -57,8 +64,8 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
}
}
- override def markDirty() {
- super.markDirty()
+ override def setChanged() {
+ super.setChanged()
// Makes the implementation of the comparator output easier.
items.map(!_.isEmpty).copyToArray(presence)
}
@@ -70,13 +77,20 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
filesystem.foreach(fs => {
fs.fileSystem.close()
fs.fileSystem.list("/").foreach(fs.fileSystem.delete)
- fs.save(new NBTTagCompound()) // Flush buffered fs.
+ fs.saveData(new CompoundNBT()) // Flush buffered fs.
fs.node.remove()
filesystem = None
})
}
}
+ // Uses the loot system, so nope.
+ override def forAllLoot(dst: Consumer[ItemStack]) = ()
+
+ override def dropSlot(slot: Int, count: Int = getMaxStackSize, direction: Option[Direction]) = false
+
+ override def dropAllSlots() = ()
+
def tryCreateRaid(id: String) {
if (items.count(!_.isEmpty) == items.length && filesystem.fold(true)(fs => fs.node == null || fs.node.address != id)) {
filesystem.foreach(fs => if (fs.node != null) fs.node.remove())
@@ -84,15 +98,15 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
val drive = new DriveData(fsStack)
drive.lockInfo = ""
drive.isUnmanaged = false
- drive.save(fsStack)
+ drive.saveData(fsStack)
})
val fs = api.FileSystem.asManagedEnvironment(
api.FileSystem.fromSaveDirectory(id, wipeDisksAndComputeSpace, Settings.get.bufferChanges),
label, this, Settings.resourceDomain + ":hdd_access", 6).
asInstanceOf[FileSystem]
- val nbtToSetAddress = new NBTTagCompound()
- nbtToSetAddress.setString(NodeData.AddressTag, id)
- fs.node.load(nbtToSetAddress)
+ val nbtToSetAddress = new CompoundNBT()
+ nbtToSetAddress.putString(NodeData.AddressTag, id)
+ fs.node.loadData(nbtToSetAddress)
fs.node.setVisibility(Visibility.Network)
// Ensure we're in a network before connecting the raid fs.
api.Network.joinNewNetwork(node)
@@ -106,10 +120,10 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
case Some(driver) => driver.createEnvironment(hdd, this) match {
case fs: FileSystem =>
val nbt = driver.dataTag(hdd)
- fs.load(nbt)
+ fs.loadData(nbt)
fs.fileSystem.close()
fs.fileSystem.list("/").foreach(fs.fileSystem.delete)
- fs.save(nbt)
+ fs.saveData(nbt)
fs.fileSystem.spaceTotal.toInt
case _ => 0L // Ignore.
}
@@ -120,40 +134,45 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
// ----------------------------------------------------------------------- //
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Raid(ContainerTypes.RAID, id, playerInventory, this)
+
+ // ----------------------------------------------------------------------- //
+
private final val FileSystemTag = Settings.namespace + "fs"
private final val PresenceTag = Settings.namespace + "presence"
private final val LabelTag = Settings.namespace + "label"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(FileSystemTag)) {
- val tag = nbt.getCompoundTag(FileSystemTag)
- tryCreateRaid(tag.getCompoundTag(NodeData.NodeTag).getString(NodeData.AddressTag))
- filesystem.foreach(fs => fs.load(tag))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ if (nbt.contains(FileSystemTag)) {
+ val tag = nbt.getCompound(FileSystemTag)
+ tryCreateRaid(tag.getCompound(NodeData.NodeTag).getString(NodeData.AddressTag))
+ filesystem.foreach(fs => fs.loadData(tag))
}
- label.load(nbt)
+ label.loadData(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- filesystem.foreach(fs => nbt.setNewCompoundTag(FileSystemTag, fs.save))
- label.save(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ filesystem.foreach(fs => nbt.setNewCompoundTag(FileSystemTag, fs.saveData))
+ label.saveData(nbt)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
nbt.getByteArray(PresenceTag).
map(_ != 0).
copyToArray(presence)
label.setLabel(nbt.getString(LabelTag))
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setTag(PresenceTag, items.map(!_.isEmpty))
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.put(PresenceTag, items.map(!_.isEmpty))
if (label.getLabel != null)
- nbt.setString(LabelTag, label.getLabel)
+ nbt.putString(LabelTag, label.getLabel)
}
// ----------------------------------------------------------------------- //
@@ -165,14 +184,14 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
override def setLabel(value: String) = label = Option(value).map(_.take(16)).orNull
- override def load(nbt: NBTTagCompound) {
- if (nbt.hasKey(Settings.namespace + "label")) {
+ override def loadData(nbt: CompoundNBT) {
+ if (nbt.contains(Settings.namespace + "label")) {
label = nbt.getString(Settings.namespace + "label")
}
}
- override def save(nbt: NBTTagCompound) {
- nbt.setString(Settings.namespace + "label", label)
+ override def saveData(nbt: CompoundNBT) {
+ nbt.putString(Settings.namespace + "label", label)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala b/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala
index 19acb84f6f..23b657fba2 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala
@@ -10,10 +10,12 @@ import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.server.component
import li.cil.oc.server.component.RedstoneVanilla
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
-class Redstone extends traits.Environment with traits.BundledRedstoneAware with traits.Tickable {
+class Redstone(selfType: TileEntityType[_ <: Redstone]) extends TileEntity(selfType) with traits.Environment with traits.BundledRedstoneAware with traits.Tickable {
val instance: RedstoneVanilla =
if (BundledRedstone.isAvailable)
new component.Redstone.Bundled(this)
@@ -32,14 +34,14 @@ class Redstone extends traits.Environment with traits.BundledRedstoneAware with
private final val RedstoneTag = Settings.namespace + "redstone"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- instance.load(nbt.getCompoundTag(RedstoneTag))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ instance.loadData(nbt.getCompound(RedstoneTag))
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setNewCompoundTag(RedstoneTag, instance.save)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.setNewCompoundTag(RedstoneTag, instance.saveData)
}
// ----------------------------------------------------------------------- //
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Relay.scala b/src/main/scala/li/cil/oc/common/tileentity/Relay.scala
index d1410d5b04..2c67d78bdd 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Relay.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Relay.scala
@@ -24,21 +24,29 @@ import li.cil.oc.api.network.WirelessEndpoint
import li.cil.oc.common.InventorySlots
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.item
-import li.cil.oc.common.item.Delegator
import li.cil.oc.integration.Mods
import li.cil.oc.integration.opencomputers.DriverLinkedCard
import li.cil.oc.server.network.QuantumNetwork
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraft.util.Util
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class Relay(selfType: TileEntityType[_ <: Relay]) extends TileEntity(selfType) with traits.Hub with traits.ComponentInventory
+ with traits.PowerAcceptor with Analyzable with WirelessEndpoint with QuantumNetwork.QuantumNode with INamedContainerProvider {
-class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerAcceptor with Analyzable with WirelessEndpoint with QuantumNetwork.QuantumNode {
lazy final val WirelessNetworkCardTier1: ItemInfo = api.Items.get(Constants.ItemName.WirelessNetworkCardTier1)
lazy final val WirelessNetworkCardTier2: ItemInfo = api.Items.get(Constants.ItemName.WirelessNetworkCardTier2)
lazy final val LinkedCard: ItemInfo = api.Items.get(Constants.ItemName.LinkedCard)
@@ -79,10 +87,10 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override protected def hasConnector(side: EnumFacing) = true
+ @OnlyIn(Dist.CLIENT)
+ override protected def hasConnector(side: Direction) = true
- override protected def connector(side: EnumFacing): Option[Connector] = sidedNode(side) match {
+ override protected def connector(side: Direction): Option[Connector] = sidedNode(side) match {
case connector: Connector => Option(connector)
case _ => None
}
@@ -91,10 +99,10 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
if (isWirelessEnabled) {
- player.sendMessage(Localization.Analyzer.WirelessStrength(strength))
- Array(componentNodes(side.getIndex))
+ player.sendMessage(Localization.Analyzer.WirelessStrength(strength), Util.NIL_UUID)
+ Array(componentNodes(side.get3DDataValue))
}
else null
}
@@ -121,14 +129,20 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
// ----------------------------------------------------------------------- //
- protected def queueMessage(source: String, destination: String, port: Int, answerPort: Int, args: Array[AnyRef]) {
- for (computer <- computers.map(_.asInstanceOf[IComputerAccess])) {
- val address = s"cc${computer.getID}_${computer.getAttachmentName}"
- if (source != address && Option(destination).forall(_ == address) && openPorts(computer).contains(port))
- computer.queueEvent("modem_message", Array(Seq(computer.getAttachmentName, Int.box(port), Int.box(answerPort)) ++ args.map {
- case x: Array[Byte] => new String(x, Charsets.UTF_8)
- case x => x
- }: _*))
+ // Isolated from parent class so automatic callbacks don't depend on optional mods.
+ protected object RelayCCAdapter {
+ def queueMessage(source: String, destination: String, port: Int, answerPort: Int, args: Array[AnyRef]) {
+ for (computer <- computers.map(_.asInstanceOf[IComputerAccess])) {
+ val address = s"cc${computer.getID}_${computer.getAttachmentName}"
+ if (source != address && Option(destination).forall(_ == address) && openPorts(computer).contains(port)) {
+ val header = Seq(computer.getAttachmentName, Int.box(port), Int.box(answerPort))
+ val payload = args.map {
+ case x: Array[Byte] => new String(x, Charsets.UTF_8)
+ case x => x
+ }
+ computer.queueEvent("modem_message", Array((header :+ (if (payload.length > 1) payload else payload(0))): _*): _*)
+ }
+ }
}
}
@@ -148,17 +162,17 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
val computers = mutable.Buffer.empty[AnyRef]
- override def tryEnqueuePacket(sourceSide: Option[EnumFacing], packet: Packet): Boolean = {
+ override def tryEnqueuePacket(sourceSide: Option[Direction], packet: Packet): Boolean = {
if (Mods.ComputerCraft.isModAvailable) {
packet.data.headOption match {
- case Some(answerPort: java.lang.Double) => queueMessage(packet.source, packet.destination, packet.port, answerPort.toInt, packet.data.drop(1))
- case _ => queueMessage(packet.source, packet.destination, packet.port, -1, packet.data)
+ case Some(answerPort: java.lang.Double) => RelayCCAdapter.queueMessage(packet.source, packet.destination, packet.port, answerPort.toInt, packet.data.drop(1))
+ case _ => RelayCCAdapter.queueMessage(packet.source, packet.destination, packet.port, -1, packet.data)
}
}
super.tryEnqueuePacket(sourceSide, packet)
}
- override protected def relayPacket(sourceSide: Option[EnumFacing], packet: Packet): Unit = {
+ override protected def relayPacket(sourceSide: Option[Direction], packet: Packet): Unit = {
super.relayPacket(sourceSide, packet)
val tryChangeBuffer = sourceSide match {
@@ -228,8 +242,8 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
case Some(driver) if driver.slot(stack) == Slot.CPU =>
relayDelay = math.max(1, relayBaseDelay - ((driver.tier(stack) + 1) * relayDelayPerUpgrade).toInt)
case Some(driver) if driver.slot(stack) == Slot.Memory =>
- relayAmount = math.max(1, relayBaseAmount + (Delegator.subItem(stack) match {
- case Some(ram: item.Memory) => (ram.tier + 1) * relayAmountPerUpgrade
+ relayAmount = math.max(1, relayBaseAmount + (stack.getItem match {
+ case ram: item.Memory => (ram.tier + 1) * relayAmountPerUpgrade
case _ => (driver.tier(stack) + 1) * (relayAmountPerUpgrade * 2)
}))
case Some(driver) if driver.slot(stack) == Slot.HDD =>
@@ -240,7 +254,7 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
wirelessTier = if (descriptor == WirelessNetworkCardTier1) Tier.One else Tier.Two
if (descriptor == LinkedCard) {
val data = DriverLinkedCard.dataTag(stack)
- if (data.hasKey(Settings.namespace + "tunnel")) {
+ if (data.contains(Settings.namespace + "tunnel")) {
tunnel = data.getString(Settings.namespace + "tunnel")
isLinkedEnabled = true
QuantumNetwork.add(this)
@@ -263,9 +277,9 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
}
}
- override def getSizeInventory: Int = InventorySlots.relay.length
+ override def getContainerSize: Int = InventorySlots.relay.length
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean =
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean =
Option(Driver.driverFor(stack, getClass)).fold(false)(driver => {
val provided = InventorySlots.relay(slot)
val tierSatisfied = driver.slot(stack) == provided.slot && driver.tier(stack) <= provided.tier
@@ -276,38 +290,43 @@ class Relay extends traits.Hub with traits.ComponentInventory with traits.PowerA
// ----------------------------------------------------------------------- //
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Relay(ContainerTypes.RELAY, id, playerInventory, this)
+
+ // ----------------------------------------------------------------------- //
+
private final val StrengthTag = Settings.namespace + "strength"
private final val IsRepeaterTag = Settings.namespace + "isRepeater"
private final val ComponentNodesTag = Settings.namespace + "componentNodes"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
for (slot <- items.indices) if (!items(slot).isEmpty) {
updateLimits(slot, items(slot))
}
- if (nbt.hasKey(StrengthTag)) {
+ if (nbt.contains(StrengthTag)) {
strength = nbt.getDouble(StrengthTag) max 0 min maxWirelessRange
}
- if (nbt.hasKey(IsRepeaterTag)) {
+ if (nbt.contains(IsRepeaterTag)) {
isRepeater = nbt.getBoolean(IsRepeaterTag)
}
- nbt.getTagList(ComponentNodesTag, NBT.TAG_COMPOUND).toArray[NBTTagCompound].
+ nbt.getList(ComponentNodesTag, NBT.TAG_COMPOUND).toTagArray[CompoundNBT].
zipWithIndex.foreach {
- case (tag, index) => componentNodes(index).load(tag)
+ case (tag, index) => componentNodes(index).loadData(tag)
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
- nbt.setDouble(StrengthTag, strength)
- nbt.setBoolean(IsRepeaterTag, isRepeater)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
+ nbt.putDouble(StrengthTag, strength)
+ nbt.putBoolean(IsRepeaterTag, isRepeater)
nbt.setNewTagList(ComponentNodesTag, componentNodes.map {
case node: Node =>
- val tag = new NBTTagCompound()
- node.save(tag)
+ val tag = new CompoundNBT()
+ node.saveData(tag)
tag
- case _ => new NBTTagCompound()
+ case _ => new CompoundNBT()
})
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala
index 5ab733c9b4..ec7a82e547 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala
@@ -1,6 +1,7 @@
package li.cil.oc.common.tileentity
import java.util.UUID
+import java.util.function.Consumer
import li.cil.oc._
import li.cil.oc.api.Driver
@@ -14,6 +15,8 @@ import li.cil.oc.client.gui
import li.cil.oc.common.EventHandler
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.container
+import li.cil.oc.common.container.ContainerTypes
import li.cil.oc.common.inventory.InventoryProxy
import li.cil.oc.common.inventory.InventorySelection
import li.cil.oc.common.inventory.TankSelection
@@ -32,27 +35,33 @@ import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
import net.minecraft.block.Block
-import net.minecraft.block.BlockLiquid
+import net.minecraft.block.Blocks
+import net.minecraft.block.FlowingFluidBlock
import net.minecraft.client.Minecraft
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.init.Blocks
-import net.minecraft.init.SoundEvents
-import net.minecraft.inventory.EntityEquipmentSlot
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.player.PlayerInventory
+import net.minecraft.fluid.Fluid
+import net.minecraft.inventory.EquipmentSlotType
+import net.minecraft.inventory.container.INamedContainerProvider
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.util.Direction
import net.minecraft.util.SoundCategory
-import net.minecraft.util.math.AxisAlignedBB
+import net.minecraft.util.SoundEvents
+import net.minecraft.util.Util
import net.minecraft.util.math.BlockPos
+import net.minecraft.util.text.StringTextComponent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.capabilities.Capability
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
import net.minecraftforge.fluids._
import net.minecraftforge.fluids.capability.CapabilityFluidHandler
-import net.minecraftforge.fluids.capability.FluidTankProperties
import net.minecraftforge.fluids.capability.IFluidHandler
-import net.minecraftforge.fluids.capability.IFluidTankProperties
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import scala.collection.mutable
@@ -62,23 +71,28 @@ import scala.collection.mutable
// robot moves we only create a new proxy tile entity, hook the instance of this
// class that was held by the old proxy to it and can then safely forget the
// old proxy, which will be cleaned up by Minecraft like any other tile entity.
-class Robot extends traits.Computer with traits.PowerInformation with traits.RotatableTile with IFluidHandler with internal.Robot with InventorySelection with TankSelection {
+class Robot extends TileEntity(TileEntityTypes.ROBOT) with traits.Computer with traits.PowerInformation with traits.RotatableTile
+ with IFluidHandler with internal.Robot with InventorySelection with TankSelection with INamedContainerProvider {
+
var proxy: RobotProxy = _
val info = new RobotData()
val bot: component.Robot = if (isServer) new component.Robot(this) else null
+ val fluidCap: LazyOptional[IFluidHandler] = LazyOptional.of(new NonNullSupplier[IFluidHandler] {
+ override def get = Robot.this
+ })
+
if (isServer) {
machine.setCostPerTick(Settings.get.robotCost)
}
-
// ----------------------------------------------------------------------- //
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
- capability.cast(this.asInstanceOf[T])
+ fluidCap.cast()
else
super.getCapability(capability, facing)
}
@@ -90,29 +104,29 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
val equipmentInventory = new InventoryProxy {
override def inventory: Robot = Robot.this
- override def getSizeInventory = 4
+ override def getContainerSize = 4
}
// Wrapper for the part of the inventory that is mutable.
val mainInventory = new InventoryProxy {
override def inventory: Robot = Robot.this
- override def getSizeInventory: Int = Robot.this.inventorySize
+ override def getContainerSize: Int = Robot.this.inventorySize
- override def offset: Int = equipmentInventory.getSizeInventory
+ override def offset: Int = equipmentInventory.getContainerSize
}
val actualInventorySize = 100
- def maxInventorySize: Int = actualInventorySize - equipmentInventory.getSizeInventory - componentCount
+ def maxInventorySize: Int = actualInventorySize - equipmentInventory.getContainerSize - componentCount
var inventorySize: Int = -1
var selectedSlot = 0
override def setSelectedSlot(index: Int): Unit = {
- selectedSlot = index max 0 min mainInventory.getSizeInventory - 1
- if (getWorld != null) {
+ selectedSlot = index max 0 min mainInventory.getContainerSize - 1
+ if (getLevel != null) {
ServerPacketSender.sendRobotSelectedSlotChange(this)
}
}
@@ -136,12 +150,12 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
override def player: Player = {
agent.Player.updatePositionAndRotation(player_, facing, facing)
- agent.Player.setInventoryPlayerItems(player_)
+ agent.Player.setPlayerInventoryItems(player_)
player_
}
- override def synchronizeSlot(slot: Int): Unit = if (slot >= 0 && slot < getSizeInventory) this.synchronized {
- val stack = getStackInSlot(slot)
+ override def synchronizeSlot(slot: Int): Unit = if (slot >= 0 && slot < getContainerSize) this.synchronized {
+ val stack = getItem(slot)
components(slot) match {
case Some(component) =>
// We're guaranteed to have a driver for entries.
@@ -153,9 +167,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
def containerSlots: Range.Inclusive = 1 to info.containers.length
- def componentSlots: Range = getSizeInventory - componentCount until getSizeInventory
+ def componentSlots: Range = getContainerSize - componentCount until getContainerSize
- def inventorySlots: Range = equipmentInventory.getSizeInventory until (equipmentInventory.getSizeInventory + mainInventory.getSizeInventory)
+ def inventorySlots: Range = equipmentInventory.getContainerSize until (equipmentInventory.getContainerSize + mainInventory.getContainerSize)
def setLightColor(value: Int): Unit = {
info.lightColor = value
@@ -196,17 +210,17 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
override def setName(name: String): Unit = info.name = name
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
- player.sendMessage(Localization.Analyzer.RobotOwner(ownerName))
- player.sendMessage(Localization.Analyzer.RobotName(player_.getName))
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
+ player.sendMessage(Localization.Analyzer.RobotOwner(ownerName), Util.NIL_UUID)
+ player.sendMessage(Localization.Analyzer.RobotName(player_.getName.getString), Util.NIL_UUID)
MinecraftForge.EVENT_BUS.post(new RobotAnalyzeEvent(this, player))
super.onAnalyze(player, side, hitX, hitY, hitZ)
}
- def move(direction: EnumFacing): Boolean = {
- val oldPosition = getPos
- val newPosition = oldPosition.offset(direction)
- if (!getWorld.isBlockLoaded(newPosition)) {
+ def move(direction: Direction): Boolean = {
+ val oldPosition = getBlockPos
+ val newPosition = oldPosition.relative(direction)
+ if (!getLevel.isLoaded(newPosition)) {
return false // Don't fall off the earth.
}
@@ -218,10 +232,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
val blockRobotProxy = api.Items.get(Constants.BlockName.Robot).block.asInstanceOf[common.block.RobotProxy]
val blockRobotAfterImage = api.Items.get(Constants.BlockName.RobotAfterimage).block.asInstanceOf[common.block.RobotAfterimage]
- val wasAir = getWorld.isAirBlock(newPosition)
- val state = getWorld.getBlockState(newPosition)
+ val wasAir = getLevel.isEmptyBlock(newPosition)
+ val state = getLevel.getBlockState(newPosition)
val block = state.getBlock
- val metadata = block.getMetaFromState(state)
try {
// Setting this will make the tile entity created via the following call
// to setBlock to re-use our "real" instance as the inner object, instead
@@ -231,16 +244,16 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
// worked before the client is notified so that we can use the same trick on
// the client by sending a corresponding packet. This also saves us from
// having to send the complete state again (e.g. screen buffer) each move.
- getWorld.setBlockToAir(newPosition)
+ getLevel.setBlockAndUpdate(newPosition, Blocks.AIR.defaultBlockState)
// In some cases (though I couldn't quite figure out which one) setBlock
// will return true, even though the block was not created / adjusted.
- val created = getWorld.setBlockState(newPosition, getWorld.getBlockState(oldPosition), 1) &&
- getWorld.getTileEntity(newPosition) == proxy
+ val created = getLevel.setBlock(newPosition, getLevel.getBlockState(oldPosition), 1) &&
+ getLevel.getBlockEntity(newPosition) == proxy
if (created) {
- assert(getPos == newPosition)
- getWorld.setBlockState(oldPosition, net.minecraft.init.Blocks.AIR.getDefaultState, 1)
- getWorld.setBlockState(oldPosition, blockRobotAfterImage.getDefaultState, 1)
- assert(getWorld.getBlockState(oldPosition).getBlock == blockRobotAfterImage)
+ assert(getBlockPos == newPosition)
+ getLevel.setBlock(oldPosition, Blocks.AIR.defaultBlockState, 1)
+ getLevel.setBlock(oldPosition, blockRobotAfterImage.defaultBlockState, 1)
+ assert(getLevel.getBlockState(oldPosition).getBlock == blockRobotAfterImage)
// Here instead of Lua callback so that it gets called on client, too.
val moveTicks = math.max((Settings.get.moveDelay * 20).toInt, 1)
setAnimateMove(oldPosition, moveTicks)
@@ -253,29 +266,24 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
// If we broke some replaceable block (like grass) play its break sound.
if (!wasAir) {
if (block != Blocks.AIR && block != blockRobotAfterImage) {
- if (FluidRegistry.lookupFluidForBlock(block) == null &&
- !block.isInstanceOf[BlockFluidBase] &&
- !block.isInstanceOf[BlockLiquid]) {
- getWorld.playEvent(2001, newPosition, Block.getIdFromBlock(block) + (metadata << 12))
+ if (!state.getFluidState.isEmpty) {
+ getLevel.playLocalSound(newPosition.getX + 0.5, newPosition.getY + 0.5, newPosition.getZ + 0.5, SoundEvents.WATER_AMBIENT, SoundCategory.BLOCKS,
+ getLevel.random.nextFloat * 0.25f + 0.75f, getLevel.random.nextFloat * 1.0f + 0.5f, false)
}
- else {
- val sx = newPosition.getX + 0.5
- val sy = newPosition.getY + 0.5
- val sz = newPosition.getZ + 0.5
- getWorld.playSound(sx, sy, sz, SoundEvents.BLOCK_WATER_AMBIENT, SoundCategory.BLOCKS,
- getWorld.rand.nextFloat * 0.25f + 0.75f, getWorld.rand.nextFloat * 1.0f + 0.5f, false)
+ if (!block.isInstanceOf[FlowingFluidBlock]) {
+ getLevel.levelEvent(2001, newPosition, Block.getId(state))
}
}
}
- getWorld.notifyBlockUpdate(oldPosition)
- getWorld.notifyBlockUpdate(newPosition)
+ getLevel.notifyBlockUpdate(oldPosition)
+ getLevel.notifyBlockUpdate(newPosition)
}
- assert(!isInvalid)
+ assert(!isRemoved)
}
else {
- getWorld.setBlockToAir(newPosition)
+ getLevel.setBlockAndUpdate(newPosition, Blocks.AIR.defaultBlockState)
}
- created && this.pos == newPosition
+ created && getBlockPos == newPosition
}
finally {
blockRobotProxy.moving.set(None)
@@ -327,16 +335,6 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
// ----------------------------------------------------------------------- //
- override def shouldRenderInPass(pass: Int) = true
-
- override def getRenderBoundingBox: AxisAlignedBB =
- if (getBlockType != null && getWorld != null)
- getBlockType.getCollisionBoundingBox(getWorld.getBlockState(getPos), getWorld, getPos).grow(0.5, 0.5, 0.5).offset(getPos)
- else
- new AxisAlignedBB(0, 0, 0, 1, 1, 1).offset(getPos)
-
- // ----------------------------------------------------------------------- //
-
override def updateEntity() {
if (animationTicksLeft > 0) {
animationTicksLeft -= 1
@@ -348,7 +346,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
}
super.updateEntity()
if (isServer) {
- if (getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (getLevel.getGameTime % Settings.get.tickFrequency == 0) {
if (info.tier == 3) {
bot.node.changeBuffer(Double.PositiveInfinity)
}
@@ -360,8 +358,8 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
}
if (!appliedToolEnchantments) {
appliedToolEnchantments = true
- StackOption(getStackInSlot(0)) match {
- case SomeStack(item) => player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers(EntityEquipmentSlot.MAINHAND))
+ StackOption(getItem(0)) match {
+ case SomeStack(item) => player_.getAttributes.addTransientAttributeModifiers(item.getAttributeModifiers(EquipmentSlotType.MAINHAND))
case _ =>
}
}
@@ -370,9 +368,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
client.Sound.updatePosition(this)
}
- for (slot <- 0 until equipmentInventory.getSizeInventory + mainInventory.getSizeInventory) {
- getStackInSlot(slot) match {
- case stack: ItemStack => try stack.updateAnimation(getWorld, if (!getWorld.isRemote) player_ else null, slot, slot == 0) catch {
+ for (slot <- 0 until equipmentInventory.getContainerSize + mainInventory.getContainerSize) {
+ getItem(slot) match {
+ case stack: ItemStack => try stack.inventoryTick(getLevel, if (!getLevel.isClientSide) player_ else null, slot, slot == 0) catch {
case ignored: NullPointerException => // Client side item updates that need a player instance...
}
case _ =>
@@ -401,9 +399,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
override def dispose() {
super.dispose()
if (isClient) {
- Minecraft.getMinecraft.currentScreen match {
- case robotGui: gui.Robot if robotGui.robot == this =>
- Minecraft.getMinecraft.displayGuiScreen(null)
+ Minecraft.getInstance.screen match {
+ case robotGui: gui.Robot if robotGui.inventoryContainer.otherInventory == this =>
+ robotGui.onClose()
case _ =>
}
}
@@ -425,28 +423,28 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
private final val SwingingToolTag = Settings.namespace + "swingingTool"
private final val TurnAxisTag = Settings.namespace + "turnAxis"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
+ override def loadForServer(nbt: CompoundNBT) {
updateInventorySize()
machine.onHostChanged()
- bot.load(nbt.getCompoundTag(RobotTag))
- if (nbt.hasKey(OwnerTag)) {
+ bot.loadData(nbt.getCompound(RobotTag))
+ if (nbt.contains(OwnerTag)) {
ownerName = nbt.getString(OwnerTag)
}
- if (nbt.hasKey(OwnerUUIDTag)) {
+ if (nbt.contains(OwnerUUIDTag)) {
ownerUUID = UUID.fromString(nbt.getString(OwnerUUIDTag))
}
if (inventorySize > 0) {
- selectedSlot = nbt.getInteger(SelectedSlotTag) max 0 min mainInventory.getSizeInventory - 1
+ selectedSlot = nbt.getInt(SelectedSlotTag) max 0 min mainInventory.getContainerSize - 1
}
- selectedTank = nbt.getInteger(SelectedTankTag)
- animationTicksTotal = nbt.getInteger(AnimationTicksTotalTag)
- animationTicksLeft = nbt.getInteger(AnimationTicksLeftTag)
+ selectedTank = nbt.getInt(SelectedTankTag)
+ animationTicksTotal = nbt.getInt(AnimationTicksTotalTag)
+ animationTicksLeft = nbt.getInt(AnimationTicksLeftTag)
if (animationTicksLeft > 0) {
- if (nbt.hasKey(MoveFromXTag)) {
- val moveFromX = nbt.getInteger(MoveFromXTag)
- val moveFromY = nbt.getInteger(MoveFromYTag)
- val moveFromZ = nbt.getInteger(MoveFromZTag)
+ if (nbt.contains(MoveFromXTag)) {
+ val moveFromX = nbt.getInt(MoveFromXTag)
+ val moveFromY = nbt.getInt(MoveFromYTag)
+ val moveFromZ = nbt.getInt(MoveFromZTag)
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
}
swingingTool = nbt.getBoolean(SwingingToolTag)
@@ -460,47 +458,47 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
}
// Side check for Waila (and other mods that may call this client side).
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = if (isServer) this.synchronized {
- info.save(nbt)
+ override def saveForServer(nbt: CompoundNBT): Unit = if (isServer) this.synchronized {
+ info.saveData(nbt)
- // Note: computer is saved when proxy is saved (in proxy's super writeToNBT)
+ // Note: computer is saved when proxy is saved (in proxy's super save)
// which is a bit ugly, and may be refactored some day, but it works.
- nbt.setNewCompoundTag(RobotTag, bot.save)
- nbt.setString(OwnerTag, ownerName)
- nbt.setString(OwnerUUIDTag, ownerUUID.toString)
- nbt.setInteger(SelectedSlotTag, selectedSlot)
- nbt.setInteger(SelectedTankTag, selectedTank)
+ nbt.setNewCompoundTag(RobotTag, bot.saveData)
+ nbt.putString(OwnerTag, ownerName)
+ nbt.putString(OwnerUUIDTag, ownerUUID.toString)
+ nbt.putInt(SelectedSlotTag, selectedSlot)
+ nbt.putInt(SelectedTankTag, selectedTank)
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
- nbt.setInteger(AnimationTicksTotalTag, animationTicksTotal)
- nbt.setInteger(AnimationTicksLeftTag, animationTicksLeft)
+ nbt.putInt(AnimationTicksTotalTag, animationTicksTotal)
+ nbt.putInt(AnimationTicksLeftTag, animationTicksLeft)
moveFrom match {
case Some(blockPos) =>
- nbt.setInteger(MoveFromXTag, blockPos.getX)
- nbt.setInteger(MoveFromYTag, blockPos.getY)
- nbt.setInteger(MoveFromZTag, blockPos.getZ)
+ nbt.putInt(MoveFromXTag, blockPos.getX)
+ nbt.putInt(MoveFromYTag, blockPos.getY)
+ nbt.putInt(MoveFromZTag, blockPos.getZ)
case _ =>
}
- nbt.setBoolean(SwingingToolTag, swingingTool)
- nbt.setByte(TurnAxisTag, turnAxis.toByte)
+ nbt.putBoolean(SwingingToolTag, swingingTool)
+ nbt.putByte(TurnAxisTag, turnAxis.toByte)
}
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- load(nbt)
- info.load(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ loadData(nbt)
+ info.loadData(nbt)
updateInventorySize()
- selectedSlot = nbt.getInteger(SelectedSlotTag)
- animationTicksTotal = nbt.getInteger(AnimationTicksTotalTag)
- animationTicksLeft = nbt.getInteger(AnimationTicksLeftTag)
+ selectedSlot = nbt.getInt(SelectedSlotTag)
+ animationTicksTotal = nbt.getInt(AnimationTicksTotalTag)
+ animationTicksLeft = nbt.getInt(AnimationTicksLeftTag)
if (animationTicksLeft > 0) {
- if (nbt.hasKey(MoveFromXTag)) {
- val moveFromX = nbt.getInteger(MoveFromXTag)
- val moveFromY = nbt.getInteger(MoveFromYTag)
- val moveFromZ = nbt.getInteger(MoveFromZTag)
+ if (nbt.contains(MoveFromXTag)) {
+ val moveFromX = nbt.getInt(MoveFromXTag)
+ val moveFromY = nbt.getInt(MoveFromYTag)
+ val moveFromZ = nbt.getInt(MoveFromZTag)
moveFrom = Some(new BlockPos(moveFromX, moveFromY, moveFromZ))
}
swingingTool = nbt.getBoolean(SwingingToolTag)
@@ -509,24 +507,24 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
connectComponents()
}
- override def writeToNBTForClient(nbt: NBTTagCompound): Unit = this.synchronized {
- super.writeToNBTForClient(nbt)
- save(nbt)
- info.save(nbt)
+ override def saveForClient(nbt: CompoundNBT): Unit = this.synchronized {
+ super.saveForClient(nbt)
+ saveData(nbt)
+ info.saveData(nbt)
- nbt.setInteger(SelectedSlotTag, selectedSlot)
+ nbt.putInt(SelectedSlotTag, selectedSlot)
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
- nbt.setInteger(AnimationTicksTotalTag, animationTicksTotal)
- nbt.setInteger(AnimationTicksLeftTag, animationTicksLeft)
+ nbt.putInt(AnimationTicksTotalTag, animationTicksTotal)
+ nbt.putInt(AnimationTicksLeftTag, animationTicksLeft)
moveFrom match {
case Some(blockPos) =>
- nbt.setInteger(MoveFromXTag, blockPos.getX)
- nbt.setInteger(MoveFromYTag, blockPos.getY)
- nbt.setInteger(MoveFromZTag, blockPos.getZ)
+ nbt.putInt(MoveFromXTag, blockPos.getX)
+ nbt.putInt(MoveFromYTag, blockPos.getY)
+ nbt.putInt(MoveFromZTag, blockPos.getZ)
case _ =>
}
- nbt.setBoolean(SwingingToolTag, swingingTool)
- nbt.setByte(TurnAxisTag, turnAxis.toByte)
+ nbt.putBoolean(SwingingToolTag, swingingTool)
+ nbt.putByte(TurnAxisTag, turnAxis.toByte)
}
}
@@ -556,7 +554,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
override protected def onItemAdded(slot: Int, stack: ItemStack) {
if (isServer) {
if (isToolSlot(slot)) {
- player_.getAttributeMap.applyAttributeModifiers(stack.getAttributeModifiers(EntityEquipmentSlot.MAINHAND))
+ player_.getAttributes.addTransientAttributeModifiers(stack.getAttributeModifiers(EquipmentSlotType.MAINHAND))
ServerPacketSender.sendRobotInventory(this, slot, stack)
}
if (isUpgradeSlot(slot)) {
@@ -567,10 +565,10 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
}
if (isComponentSlot(slot, stack)) {
super.onItemAdded(slot, stack)
- getWorld.notifyBlocksOfNeighborChange(position, getBlockType, updateObservers = false)
+ getLevel.notifyBlocksOfNeighborChange(position, getBlockState.getBlock, updateObservers = false)
}
if (isInventorySlot(slot)) {
- machine.signal("inventory_changed", Int.box(slot - equipmentInventory.getSizeInventory + 1))
+ machine.signal("inventory_changed", Int.box(slot - equipmentInventory.getContainerSize + 1))
}
}
else super.onItemAdded(slot, stack)
@@ -580,7 +578,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
super.onItemRemoved(slot, stack)
if (isServer) {
if (isToolSlot(slot)) {
- player_.getAttributeMap.removeAttributeModifiers(stack.getAttributeModifiers(EntityEquipmentSlot.MAINHAND))
+ player_.getAttributes.removeAttributeModifiers(stack.getAttributeModifiers(EquipmentSlotType.MAINHAND))
ServerPacketSender.sendRobotInventory(this, slot, ItemStack.EMPTY)
}
if (isUpgradeSlot(slot)) {
@@ -590,16 +588,16 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
common.Sound.playDiskEject(this)
}
if (isInventorySlot(slot)) {
- machine.signal("inventory_changed", Int.box(slot - equipmentInventory.getSizeInventory + 1))
+ machine.signal("inventory_changed", Int.box(slot - equipmentInventory.getContainerSize + 1))
}
if (isComponentSlot(slot, stack)) {
- getWorld.notifyBlocksOfNeighborChange(position, getBlockType, updateObservers = false)
+ getLevel.notifyBlocksOfNeighborChange(position, getBlockState.getBlock, updateObservers = false)
}
}
}
- override def markDirty() {
- super.markDirty()
+ override def setChanged() {
+ super.setChanged()
// Avoid getting into a bad state on the client when updating before we
// got the descriptor packet from the server. If we manage to open the
// GUI before the descriptor packet arrived, close it again because it is
@@ -608,9 +606,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
updateInventorySize()
}
else if (isClient) {
- Minecraft.getMinecraft.currentScreen match {
- case robotGui: gui.Robot if robotGui.robot == this =>
- Minecraft.getMinecraft.displayGuiScreen(null)
+ Minecraft.getInstance.screen match {
+ case robotGui: gui.Robot if robotGui.inventoryContainer.otherInventory == this =>
+ robotGui.onClose()
case _ =>
}
}
@@ -665,8 +663,8 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
def isInventorySlot(slot: Int): Boolean = inventorySlots contains slot
- def isFloppySlot(slot: Int): Boolean = !getStackInSlot(slot).isEmpty && isComponentSlot(slot, getStackInSlot(slot)) && {
- val stack = getStackInSlot(slot)
+ def isFloppySlot(slot: Int): Boolean = !getItem(slot).isEmpty && isComponentSlot(slot, getItem(slot)) && {
+ val stack = getItem(slot)
Option(Driver.driverFor(stack, getClass)) match {
case Some(driver) => driver.slot(stack) == Slot.Floppy
case _ => false
@@ -679,9 +677,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
override def componentSlot(address: String): Int = components.indexWhere(_.exists(env => env.node != null && env.node.address == address))
- override def hasRedstoneCard: Boolean = (containerSlots ++ componentSlots).exists(slot => StackOption(getStackInSlot(slot)).fold(false)(DriverRedstoneCard.worksWith(_, getClass)))
+ override def hasRedstoneCard: Boolean = (containerSlots ++ componentSlots).exists(slot => StackOption(getItem(slot)).fold(false)(DriverRedstoneCard.worksWith(_, getClass)))
- private def computeInventorySize() = math.min(maxInventorySize, (containerSlots ++ componentSlots).foldLeft(0)((acc, slot) => acc + (StackOption(getStackInSlot(slot)) match {
+ private def computeInventorySize() = math.min(maxInventorySize, (containerSlots ++ componentSlots).foldLeft(0)((acc, slot) => acc + (StackOption(getItem(slot)) match {
case SomeStack(stack) => Option(Driver.driverFor(stack, getClass)) match {
case Some(driver: item.Inventory) => driver.inventoryCapacity(stack)
case _ => 0
@@ -696,23 +694,23 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
val newInventorySize = computeInventorySize()
if (newInventorySize != inventorySize) {
inventorySize = newInventorySize
- val realSize = equipmentInventory.getSizeInventory + mainInventory.getSizeInventory
+ val realSize = equipmentInventory.getContainerSize + mainInventory.getContainerSize
val oldSelected = selectedSlot
val removed = mutable.ArrayBuffer.empty[ItemStack]
- for (slot <- realSize until getSizeInventory - componentCount) {
- val stack = getStackInSlot(slot)
- setInventorySlotContents(slot, ItemStack.EMPTY)
+ for (slot <- realSize until getContainerSize - componentCount) {
+ val stack = getItem(slot)
+ setItem(slot, ItemStack.EMPTY)
if (!stack.isEmpty) removed += stack
}
- val copyComponentCount = math.min(getSizeInventory, componentCount)
- Array.copy(components, getSizeInventory - copyComponentCount, components, realSize, copyComponentCount)
- for (slot <- math.max(0, getSizeInventory - componentCount) until getSizeInventory if slot < realSize || slot >= realSize + componentCount) {
+ val copyComponentCount = math.min(getContainerSize, componentCount)
+ Array.copy(components, getContainerSize - copyComponentCount, components, realSize, copyComponentCount)
+ for (slot <- math.max(0, getContainerSize - componentCount) until getContainerSize if slot < realSize || slot >= realSize + componentCount) {
components(slot) = None
}
- getSizeInventory = realSize + componentCount
- if (getWorld != null && isServer) {
+ getContainerSize = realSize + componentCount
+ if (getLevel != null && isServer) {
for (stack <- removed) {
- player().inventory.addItemStackToInventory(stack)
+ player().inventory.add(stack)
spawnStackInWorld(stack, Option(facing))
}
setSelectedSlot(oldSelected)
@@ -725,36 +723,36 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
// ----------------------------------------------------------------------- //
- var getSizeInventory: Int = actualInventorySize
+ var getContainerSize: Int = actualInventorySize
- override def getInventoryStackLimit = 64
+ override def getMaxStackSize = 64
- override def getStackInSlot(slot: Int): ItemStack = {
- if (slot >= getSizeInventory) null // Required to always show 16 inventory slots in GUI.
- else if (slot >= getSizeInventory - componentCount) {
- info.components(slot - (getSizeInventory - componentCount))
+ override def getItem(slot: Int): ItemStack = {
+ if (slot >= getContainerSize) null // Required to always show 16 inventory slots in GUI.
+ else if (slot >= getContainerSize - componentCount) {
+ info.components(slot - (getContainerSize - componentCount))
}
- else super.getStackInSlot(slot)
+ else super.getItem(slot)
}
- override def setInventorySlotContents(slot: Int, stack: ItemStack) {
- if (slot < getSizeInventory - componentCount && (isItemValidForSlot(slot, stack) || stack.isEmpty)) {
+ override def setItem(slot: Int, stack: ItemStack) {
+ if (slot < getContainerSize - componentCount && (canPlaceItem(slot, stack) || stack.isEmpty)) {
if (!stack.isEmpty && stack.getCount > 1 && isComponentSlot(slot, stack)) {
- super.setInventorySlotContents(slot, stack.splitStack(1))
+ super.setItem(slot, stack.split(1))
if (stack.getCount > 0 && isServer) {
- player().inventory.addItemStackToInventory(stack)
+ player().inventory.add(stack)
spawnStackInWorld(stack, Option(facing))
}
}
- else super.setInventorySlotContents(slot, stack)
+ else super.setItem(slot, stack)
}
- else if (!stack.isEmpty && stack.getCount > 0 && !getWorld.isRemote) spawnStackInWorld(stack, Option(EnumFacing.UP))
+ else if (!stack.isEmpty && stack.getCount > 0 && !getLevel.isClientSide) spawnStackInWorld(stack, Option(Direction.UP))
}
- override def isUsableByPlayer(player: EntityPlayer): Boolean =
- super.isUsableByPlayer(player) && (!isCreative || player.capabilities.isCreativeMode)
+ override def stillValid(player: PlayerEntity): Boolean =
+ super.stillValid(player) && (!isCreative || player.isCreative)
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack, getClass))) match {
case (0, _) => true // Allow anything in the tool slot.
case (i, Some(driver)) if isContainerSlot(i) =>
// Yay special cases! Dynamic screens kind of work, but are pretty derpy
@@ -774,30 +772,51 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
// ----------------------------------------------------------------------- //
- override def dropSlot(slot: Int, count: Int, direction: Option[EnumFacing]): Boolean =
- InventoryUtils.dropSlot(BlockPosition(x, y, z, getWorld), mainInventory, slot, count, direction)
+ override def getDisplayName = StringTextComponent.EMPTY
+
+ override def createMenu(id: Int, playerInventory: PlayerInventory, player: PlayerEntity) =
+ new container.Robot(ContainerTypes.ROBOT, id, playerInventory, this, new container.RobotInfo(this))
+
+ // ----------------------------------------------------------------------- //
+
+ override def forAllLoot(dst: Consumer[ItemStack]) {
+ Option(getItem(0)) match {
+ case Some(stack) if stack.getCount > 0 => dst.accept(stack)
+ case _ =>
+ }
+ for (slot <- containerSlots) {
+ Option(getItem(slot)) match {
+ case Some(stack) if stack.getCount > 0 => dst.accept(stack)
+ case _ =>
+ }
+ }
+ InventoryUtils.forAllSlots(mainInventory, dst)
+ }
+
+ override def dropSlot(slot: Int, count: Int, direction: Option[Direction]): Boolean =
+ InventoryUtils.dropSlot(BlockPosition(x, y, z, getLevel), mainInventory, slot, count, direction)
override def dropAllSlots(): Unit = {
- InventoryUtils.dropSlot(BlockPosition(x, y, z, getWorld), this, 0, Int.MaxValue)
+ InventoryUtils.dropSlot(BlockPosition(x, y, z, getLevel), this, 0, Int.MaxValue)
for (slot <- containerSlots) {
- InventoryUtils.dropSlot(BlockPosition(x, y, z, getWorld), this, slot, Int.MaxValue)
+ InventoryUtils.dropSlot(BlockPosition(x, y, z, getLevel), this, slot, Int.MaxValue)
}
- InventoryUtils.dropAllSlots(BlockPosition(x, y, z, getWorld), mainInventory)
+ InventoryUtils.dropAllSlots(BlockPosition(x, y, z, getLevel), mainInventory)
}
// ----------------------------------------------------------------------- //
- override def canExtractItem(slot: Int, stack: ItemStack, side: EnumFacing): Boolean =
- getSlotsForFace(side).contains(slot)
+ override def canTakeItemThroughFace(slot: Int, stack: ItemStack, side: Direction): Boolean =
+ getSlotsForFace(side).toSeq.contains(slot)
- override def canInsertItem(slot: Int, stack: ItemStack, side: EnumFacing): Boolean =
- getSlotsForFace(side).contains(slot) &&
- isItemValidForSlot(slot, stack)
+ override def canPlaceItemThroughFace(slot: Int, stack: ItemStack, side: Direction): Boolean =
+ getSlotsForFace(side).toSeq.contains(slot) &&
+ canPlaceItem(slot, stack)
- override def getSlotsForFace(side: EnumFacing): Array[Int] =
+ override def getSlotsForFace(side: Direction): Array[Int] =
toLocal(side) match {
- case EnumFacing.WEST => Array(0) // Tool
- case EnumFacing.EAST => containerSlots.toArray
+ case Direction.WEST => Array(0) // Tool
+ case Direction.EAST => containerSlots.toArray
case _ => inventorySlots.toArray
}
@@ -820,43 +839,43 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
// ----------------------------------------------------------------------- //
- override def fill(resource: FluidStack, doFill: Boolean): Int =
+ override def getTanks = tankCount
+
+ override def getFluidInTank(tank: Int): FluidStack =
tryGetTank(selectedTank) match {
case Some(t) =>
- t.fill(resource, doFill)
- case _ => 0
+ t.getFluid
+ case _ => FluidStack.EMPTY
}
- override def drain(resource: FluidStack, doDrain: Boolean): FluidStack =
+ override def getTankCapacity(tank: Int): Int =
tryGetTank(selectedTank) match {
- case Some(t) if t.getFluid != null && t.getFluid.isFluidEqual(resource) =>
- t.drain(resource.amount, doDrain)
- case _ => null
+ case Some(t) =>
+ t.getCapacity
+ case _ => 0
}
- override def drain(maxDrain: Int, doDrain: Boolean): FluidStack = {
+ override def isFluidValid(tank: Int, resource: FluidStack) = true
+
+ override def fill(resource: FluidStack, action: FluidAction): Int =
tryGetTank(selectedTank) match {
case Some(t) =>
- t.drain(maxDrain, doDrain)
- case _ => null
+ t.fill(resource, action)
+ case _ => 0
}
- }
- def canFill(fluid: Fluid): Boolean = {
+ override def drain(resource: FluidStack, action: FluidAction): FluidStack =
tryGetTank(selectedTank) match {
- case Some(t) => t.getFluid == null || t.getFluid.getFluid == fluid
- case _ => false
+ case Some(t) if t.getFluid != null && t.getFluid.isFluidEqual(resource) =>
+ t.drain(resource.getAmount, action)
+ case _ => FluidStack.EMPTY
}
- }
- def canDrain(fluid: Fluid): Boolean = {
+ override def drain(maxDrain: Int, action: FluidAction): FluidStack = {
tryGetTank(selectedTank) match {
- case Some(t) => t.getFluid != null && t.getFluid.getFluid == fluid
- case _ => false
+ case Some(t) =>
+ t.drain(maxDrain, action)
+ case _ => FluidStack.EMPTY
}
}
-
- override def getTankProperties: Array[IFluidTankProperties] = FluidTankProperties.convert(components.collect {
- case Some(t: IFluidTank) => t.getInfo
- }).map(_.asInstanceOf[IFluidTankProperties])
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala b/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala
index 3b41bd9c3b..1e5266f4da 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala
@@ -1,6 +1,7 @@
package li.cil.oc.common.tileentity
import java.util.UUID
+import java.util.function.Consumer
import li.cil.oc.api
import li.cil.oc.api.internal
@@ -15,30 +16,46 @@ import li.cil.oc.common.tileentity.traits.RedstoneAware
import li.cil.oc.server.agent.Player
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraftforge.common.capabilities.Capability
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.common.util.NonNullSupplier
import net.minecraftforge.fluids.capability.CapabilityFluidHandler
import net.minecraftforge.fluids.capability.IFluidHandler
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import net.minecraft.entity.Entity
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.fluid.Fluid
import net.minecraft.inventory.ISidedInventory
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraft.util.math.AxisAlignedBB
-import net.minecraftforge.fluids.Fluid
+import net.minecraft.util.text.ITextComponent
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.IFluidTank
-import net.minecraftforge.fluids.capability.IFluidTankProperties
-class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInformation with traits.RotatableTile with ISidedInventory with IFluidHandler with internal.Robot {
- def this() = this(new Robot())
+class RobotProxy(selfType: TileEntityType[_ <: RobotProxy], val robot: Robot) extends TileEntity(selfType)
+ with traits.Computer with traits.PowerInformation with traits.RotatableTile with ISidedInventory with IFluidHandler with internal.Robot {
+
+ def this(selfType: TileEntityType[_ <: RobotProxy]) = this(selfType, new Robot())
// ----------------------------------------------------------------------- //
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
+ private val wrapper = LazyOptional.of(new NonNullSupplier[IFluidHandler] {
+ override def get = RobotProxy.this
+ })
+
+ override def invalidateCaps() {
+ super.invalidateCaps()
+ wrapper.invalidate()
+ }
+
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
- capability.cast(this.asInstanceOf[T])
+ wrapper.cast[T]
else super.getCapability(capability, facing)
}
@@ -53,7 +70,7 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
override def equipmentInventory: InventoryProxy {
def inventory: Robot
- def getSizeInventory: Int
+ def getContainerSize: Int
} = robot.equipmentInventory
override def mainInventory: InventoryProxy {
@@ -61,7 +78,7 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
def inventory: Robot
- def getSizeInventory: Int
+ def getContainerSize: Int
} = robot.mainInventory
override def tank: MultiTank {
@@ -126,7 +143,7 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
def setName(context: Context, args: Arguments): Array[AnyRef] = {
val oldName = robot.name
val newName: String = args.checkString(0)
- if (machine.isRunning) return result(Unit, "is running")
+ if (machine.isRunning) return result((), "is running")
setName(newName)
ServerPacketSender.sendRobotNameChange(robot)
result(oldName)
@@ -149,20 +166,19 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
robot.updateEntity()
}
- override def validate() {
- super.validate()
+ override def clearRemoved() {
+ super.clearRemoved()
val firstProxy = robot.proxy == null
robot.proxy = this
- robot.setWorld(getWorld)
- robot.setPos(getPos)
+ robot.setLevelAndPosition(getLevel, getBlockPos)
if (firstProxy) {
- robot.validate()
+ robot.clearRemoved()
}
if (isServer) {
// Use the same address we use internally on the outside.
- val nbt = new NBTTagCompound()
- nbt.setString("address", robot.node.address)
- node.load(nbt)
+ val nbt = new CompoundNBT()
+ nbt.putString("address", robot.node.address)
+ node.loadData(nbt)
}
}
@@ -173,37 +189,36 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
}
}
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- robot.info.load(nbt)
- super.readFromNBTForServer(nbt)
- robot.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ robot.info.loadData(nbt)
+ super.loadForServer(nbt)
+ robot.loadForServer(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- robot.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ robot.saveForServer(nbt)
}
- override def save(nbt: NBTTagCompound): Unit = robot.save(nbt)
+ override def saveData(nbt: CompoundNBT): Unit = robot.saveData(nbt)
- override def load(nbt: NBTTagCompound): Unit = robot.load(nbt)
+ override def loadData(nbt: CompoundNBT): Unit = robot.loadData(nbt)
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound): Unit = robot.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT): Unit = robot.loadForClient(nbt)
- override def writeToNBTForClient(nbt: NBTTagCompound): Unit = robot.writeToNBTForClient(nbt)
+ override def saveForClient(nbt: CompoundNBT): Unit = robot.saveForClient(nbt)
- override def getMaxRenderDistanceSquared: Double = robot.getMaxRenderDistanceSquared
+ @OnlyIn(Dist.CLIENT)
+ override def getViewDistance: Double = robot.getViewDistance
override def getRenderBoundingBox: AxisAlignedBB = robot.getRenderBoundingBox
- override def shouldRenderInPass(pass: Int): Boolean = robot.shouldRenderInPass(pass)
-
- override def markDirty(): Unit = robot.markDirty()
+ override def setChanged(): Unit = robot.setChanged()
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = robot.onAnalyze(player, side, hitX, hitY, hitZ)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = robot.onAnalyze(player, side, hitX, hitY, hitZ)
// ----------------------------------------------------------------------- //
@@ -223,89 +238,71 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
override def checkRedstoneInputChanged(): Unit = robot.checkRedstoneInputChanged()
- /* TORO RedLogic
- @Optional.Method(modid = Mods.IDs.RedLogic)
- override def connects(wire: IWire, blockFace: Int, fromDirection: Int) = robot.connects(wire, blockFace, fromDirection)
-
- @Optional.Method(modid = Mods.IDs.RedLogic)
- override def connectsAroundCorner(wire: IWire, blockFace: Int, fromDirection: Int) = robot.connectsAroundCorner(wire, blockFace, fromDirection)
-
- @Optional.Method(modid = Mods.IDs.RedLogic)
- override def getBundledCableStrength(blockFace: Int, toDirection: Int) = robot.getBundledCableStrength(blockFace, toDirection)
-
- @Optional.Method(modid = Mods.IDs.RedLogic)
- override def getEmittedSignalStrength(blockFace: Int, toDirection: Int) = robot.getEmittedSignalStrength(blockFace, toDirection)
-
- @Optional.Method(modid = Mods.IDs.RedLogic)
- override def onBundledInputChanged() = robot.onBundledInputChanged()
-
- @Optional.Method(modid = Mods.IDs.RedLogic)
- override def onRedstoneInputChanged() = robot.onRedstoneInputChanged()
- */
-
// ----------------------------------------------------------------------- //
- override def pitch: EnumFacing = robot.pitch
+ override def pitch: Direction = robot.pitch
- override def pitch_=(value: EnumFacing): Unit = robot.pitch_=(value)
+ override def pitch_=(value: Direction): Unit = robot.pitch_=(value)
- override def yaw: EnumFacing = robot.yaw
+ override def yaw: Direction = robot.yaw
- override def yaw_=(value: EnumFacing): Unit = robot.yaw_=(value)
+ override def yaw_=(value: Direction): Unit = robot.yaw_=(value)
override def setFromEntityPitchAndYaw(entity: Entity): Boolean = robot.setFromEntityPitchAndYaw(entity)
- override def setFromFacing(value: EnumFacing): Boolean = robot.setFromFacing(value)
+ override def setFromFacing(value: Direction): Boolean = robot.setFromFacing(value)
override def invertRotation(): Boolean = robot.invertRotation()
- override def facing: EnumFacing = robot.facing
+ override def facing: Direction = robot.facing
- override def rotate(axis: EnumFacing): Boolean = robot.rotate(axis)
+ override def rotate(axis: Direction): Boolean = robot.rotate(axis)
- override def toLocal(value: EnumFacing): EnumFacing = robot.toLocal(value)
+ override def toLocal(value: Direction): Direction = robot.toLocal(value)
- override def toGlobal(value: EnumFacing): EnumFacing = robot.toGlobal(value)
+ override def toGlobal(value: Direction): Direction = robot.toGlobal(value)
// ----------------------------------------------------------------------- //
- override def getStackInSlot(i: Int): ItemStack = robot.getStackInSlot(i)
+ override def getItem(i: Int): ItemStack = robot.getItem(i)
- override def decrStackSize(slot: Int, amount: Int): ItemStack = robot.decrStackSize(slot, amount)
+ override def removeItem(slot: Int, amount: Int): ItemStack = robot.removeItem(slot, amount)
- override def setInventorySlotContents(slot: Int, stack: ItemStack): Unit = robot.setInventorySlotContents(slot, stack)
+ override def setItem(slot: Int, stack: ItemStack): Unit = robot.setItem(slot, stack)
- override def removeStackFromSlot(slot: Int): ItemStack = robot.removeStackFromSlot(slot)
+ override def removeItemNoUpdate(slot: Int): ItemStack = robot.removeItemNoUpdate(slot)
- override def openInventory(player: EntityPlayer): Unit = robot.openInventory(player)
+ override def startOpen(player: PlayerEntity): Unit = robot.startOpen(player)
- override def closeInventory(player: EntityPlayer): Unit = robot.closeInventory(player)
+ override def stopOpen(player: PlayerEntity): Unit = robot.stopOpen(player)
override def hasCustomName: Boolean = robot.hasCustomName
- override def isUsableByPlayer(player: EntityPlayer): Boolean = robot.isUsableByPlayer(player)
+ override def stillValid(player: PlayerEntity): Boolean = robot.stillValid(player)
+
+ override def forAllLoot(dst: Consumer[ItemStack]): Unit = robot.forAllLoot(dst)
- override def dropSlot(slot: Int, count: Int, direction: Option[EnumFacing]): Boolean = robot.dropSlot(slot, count, direction)
+ override def dropSlot(slot: Int, count: Int, direction: Option[Direction]): Boolean = robot.dropSlot(slot, count, direction)
override def dropAllSlots(): Unit = robot.dropAllSlots()
- override def getInventoryStackLimit: Int = robot.getInventoryStackLimit
+ override def getMaxStackSize: Int = robot.getMaxStackSize
override def componentSlot(address: String): Int = robot.componentSlot(address)
- override def getName: String = robot.getName
+ override def getName: ITextComponent = robot.getName
- override def getSizeInventory: Int = robot.getSizeInventory
+ override def getContainerSize: Int = robot.getContainerSize
- override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = robot.isItemValidForSlot(slot, stack)
+ override def canPlaceItem(slot: Int, stack: ItemStack): Boolean = robot.canPlaceItem(slot, stack)
// ----------------------------------------------------------------------- //
- override def canExtractItem(slot: Int, stack: ItemStack, side: EnumFacing): Boolean = robot.canExtractItem(slot, stack, side)
+ override def canTakeItemThroughFace(slot: Int, stack: ItemStack, side: Direction): Boolean = robot.canTakeItemThroughFace(slot, stack, side)
- override def canInsertItem(slot: Int, stack: ItemStack, side: EnumFacing): Boolean = robot.canInsertItem(slot, stack, side)
+ override def canPlaceItemThroughFace(slot: Int, stack: ItemStack, side: Direction): Boolean = robot.canPlaceItemThroughFace(slot, stack, side)
- override def getSlotsForFace(side: EnumFacing): Array[Int] = robot.getSlotsForFace(side)
+ override def getSlotsForFace(side: Direction): Array[Int] = robot.getSlotsForFace(side)
// ----------------------------------------------------------------------- //
@@ -323,15 +320,17 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.PowerInfo
// ----------------------------------------------------------------------- //
- override def fill(resource: FluidStack, doFill: Boolean): Int = robot.fill(resource, doFill)
+ override def getTanks: Int = robot.getTanks
+
+ override def getFluidInTank(tank: Int): FluidStack = robot.getFluidInTank(tank)
- override def drain(resource: FluidStack, doDrain: Boolean): FluidStack = robot.drain(resource, doDrain)
+ override def getTankCapacity(tank: Int): Int = robot.getTankCapacity(tank)
- override def drain(maxDrain: Int, doDrain: Boolean): FluidStack = robot.drain(maxDrain, doDrain)
+ override def isFluidValid(tank: Int, resource: FluidStack): Boolean = robot.isFluidValid(tank, resource)
- def canFill(fluid: Fluid): Boolean = robot.canFill(fluid)
+ override def fill(resource: FluidStack, action: FluidAction): Int = robot.fill(resource, action)
- def canDrain(fluid: Fluid): Boolean = robot.canDrain(fluid)
+ override def drain(resource: FluidStack, action: FluidAction): FluidStack = robot.drain(resource, action)
- override def getTankProperties: Array[IFluidTankProperties] = robot.getTankProperties
+ override def drain(maxDrain: Int, action: FluidAction): FluidStack = robot.drain(maxDrain, action)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Screen.scala b/src/main/scala/li/cil/oc/common/tileentity/Screen.scala
index 28233912ab..9c229d7992 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Screen.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Screen.scala
@@ -5,30 +5,32 @@ import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network._
import li.cil.oc.client.gui
import li.cil.oc.common.component.TextBuffer
-import li.cil.oc.util.BlockPosition
import li.cil.oc.common.tileentity.traits.RedstoneChangedEventArgs
+import li.cil.oc.util.BlockPosition
import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.client.Minecraft
import net.minecraft.entity.Entity
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.entity.projectile.EntityArrow
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.entity.projectile.ArrowEntity
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
import net.minecraft.util.math.AxisAlignedBB
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import scala.collection.mutable
import scala.language.postfixOps
-class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with traits.Rotatable with traits.RedstoneAware with traits.Colored with Analyzable with Ordered[Screen] {
- def this() = this(0)
+class Screen(selfType: TileEntityType[_ <: Screen], var tier: Int) extends TileEntity(selfType) with traits.TextBuffer with SidedEnvironment with traits.Rotatable with traits.RedstoneAware with traits.Colored with Analyzable with Ordered[Screen] {
+ def this(selfType: TileEntityType[_ <: Screen]) = this(selfType, 0)
// Enable redstone functionality.
_isOutputEnabled = true
- override def validFacings = EnumFacing.values
+ override def validFacings = Direction.values
// ----------------------------------------------------------------------- //
@@ -57,17 +59,17 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
var invertTouchMode = false
- private val arrows = mutable.Set.empty[EntityArrow]
+ private val arrows = mutable.Set.empty[ArrowEntity]
private val lastWalked = mutable.WeakHashMap.empty[Entity, (Int, Int)]
setColor(Color.rgbValues(Color.byTier(tier)))
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing) = side != facing
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction) = side != facing
// Allow connections from front for keyboards, and keyboards only...
- override def sidedNode(side: EnumFacing) = if (side != facing || (getWorld.isBlockLoaded(getPos.offset(side)) && getWorld.getTileEntity(getPos.offset(side)).isInstanceOf[Keyboard])) node else null
+ override def sidedNode(side: Direction) = if (side != facing || (getLevel.isLoaded(getBlockPos.relative(side)) && getLevel.getBlockEntity(getBlockPos.relative(side)).isInstanceOf[Keyboard])) node else null
// ----------------------------------------------------------------------- //
@@ -80,9 +82,9 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
}
def hasKeyboard = screens.exists(screen =>
- EnumFacing.values.map(side => (side, {
+ Direction.values.map(side => (side, {
val blockPos = BlockPosition(screen).offset(side)
- if (getWorld.blockExists(blockPos)) getWorld.getTileEntity(blockPos)
+ if (getLevel.blockExists(blockPos)) getLevel.getBlockEntity(blockPos)
else null
})).exists {
case (side, keyboard: Keyboard) => keyboard.hasNodeOnSide(side.getOpposite)
@@ -102,8 +104,8 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
def toScreenCoordinates(hitX: Double, hitY: Double, hitZ: Double): (Boolean, Option[(Double, Double)]) = {
// Compute absolute position of the click on the face, measured in blocks.
- def dot(f: EnumFacing) = f.getFrontOffsetX * hitX + f.getFrontOffsetY * hitY + f.getFrontOffsetZ * hitZ
- val (hx, hy) = (dot(toGlobal(EnumFacing.EAST)), dot(toGlobal(EnumFacing.UP)))
+ def dot(f: Direction) = f.getStepX * hitX + f.getStepY * hitY + f.getStepZ * hitZ
+ val (hx, hy) = (dot(toGlobal(Direction.EAST)), dot(toGlobal(Direction.UP)))
val tx = if (hx < 0) 1 + hx else hx
val ty = 1 - (if (hy < 0) 1 + hy else hy)
val (lx, ly) = localPosition
@@ -114,7 +116,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
if (ax <= border || ay <= border || ax >= width - border || ay >= height - border) {
return (false, None)
}
- if (!getWorld.isRemote) return (true, None)
+ if (!getLevel.isClientSide) return (true, None)
val (iw, ih) = (width - border * 2, height - border * 2)
val (rx, ry) = ((ax - border) / iw, (ay - border) / ih)
@@ -170,15 +172,15 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
origin.lastWalked.put(entity, localPosition) match {
case Some((oldX, oldY)) if oldX == x && oldY == y => // Ignore
case _ => entity match {
- case player: EntityPlayer if Settings.get.inputUsername =>
- origin.node.sendToReachable("computer.signal", "walk", Int.box(x + 1), Int.box(height - y), player.getName)
+ case player: PlayerEntity if Settings.get.inputUsername =>
+ origin.node.sendToReachable("computer.signal", "walk", Int.box(x + 1), Int.box(height - y), player.getName.getString)
case _ =>
origin.node.sendToReachable("computer.signal", "walk", Int.box(x + 1), Int.box(height - y))
}
}
}
- def shot(arrow: EntityArrow) {
+ def shot(arrow: ArrowEntity) {
arrows.add(arrow)
}
@@ -198,7 +200,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
val lpos = project(current)
def tryQueue(dx: Int, dy: Int) {
val npos = unproject(lpos.x + dx, lpos.y + dy, lpos.z)
- if (getWorld.blockExists(npos)) getWorld.getTileEntity(npos) match {
+ if (getLevel.blockExists(npos)) getLevel.getBlockEntity(npos) match {
case s: Screen if s.pitch == pitch && s.yaw == yaw && pending.add(s) => queue += s
case _ => // Ignore.
}
@@ -218,12 +220,8 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
pending.remove(screen)
queue += screen
}
- if (isClient) {
- val bounds = current.origin.getRenderBoundingBox
- getWorld.markBlockRangeForRenderUpdate(bounds.minX.toInt, bounds.minY.toInt, bounds.minZ.toInt,
- bounds.maxX.toInt, bounds.maxY.toInt, bounds.maxZ.toInt)
- }
}
+ if (isClient) updateMergedModels()
// Update visibility after everything is done, to avoid noise.
queue.foreach(screen => {
val buffer = screen.buffer
@@ -250,11 +248,11 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
}
if (arrows.nonEmpty) {
for (arrow <- arrows) {
- val hitX = arrow.posX - x
- val hitY = arrow.posY - y
- val hitZ = arrow.posZ - z
- arrow.shootingEntity match {
- case player: EntityPlayer if player == Minecraft.getMinecraft.player => click(hitX, hitY, hitZ)
+ val hitX = arrow.getX - x
+ val hitY = arrow.getY - y
+ val hitZ = arrow.getZ - z
+ arrow.getOwner match {
+ case player: PlayerEntity if player == Minecraft.getInstance.player => click(hitX, hitY, hitZ)
case _ =>
}
}
@@ -262,6 +260,16 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
}
}
+ private def updateMergedModels() {
+ if (getLevel == Minecraft.getInstance.level) {
+ val renderer = Minecraft.getInstance.levelRenderer
+ screens.foreach(screen => {
+ val pos = screen.getBlockPos
+ renderer.setSectionDirty(pos.getX >> 4, pos.getY >> 4, pos.getZ >> 4)
+ })
+ }
+ }
+
private def isClientReadyForMultiBlockCheck = if (delayUntilCheckForMultiBlock > 0) {
delayUntilCheckForMultiBlock -= 1
false
@@ -271,9 +279,8 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
super.dispose()
screens.clone().foreach(_.checkMultiBlock())
if (isClient) {
- Minecraft.getMinecraft.currentScreen match {
- case screenGui: gui.Screen if screenGui.buffer == buffer =>
- Minecraft.getMinecraft.displayGuiScreen(null)
+ Minecraft.getInstance.screen match {
+ case screenGui: gui.Screen if screenGui.buffer == buffer => screenGui.onClose()
case _ =>
}
}
@@ -290,37 +297,37 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
private final val HadRedstoneInputTag = Settings.namespace + "hadRedstoneInput"
private final val InvertTouchModeTag = Settings.namespace + "invertTouchMode"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
+ override def loadForServer(nbt: CompoundNBT) {
tier = nbt.getByte(TierTag) max 0 min 2
setColor(Color.rgbValues(Color.byTier(tier)))
- super.readFromNBTForServer(nbt)
+ super.loadForServer(nbt)
hadRedstoneInput = nbt.getBoolean(HadRedstoneInputTag)
invertTouchMode = nbt.getBoolean(InvertTouchModeTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- nbt.setByte(TierTag, tier.toByte)
- super.writeToNBTForServer(nbt)
- nbt.setBoolean(HadRedstoneInputTag, hadRedstoneInput)
- nbt.setBoolean(InvertTouchModeTag, invertTouchMode)
+ override def saveForServer(nbt: CompoundNBT) {
+ nbt.putByte(TierTag, tier.toByte)
+ super.saveForServer(nbt)
+ nbt.putBoolean(HadRedstoneInputTag, hadRedstoneInput)
+ nbt.putBoolean(InvertTouchModeTag, invertTouchMode)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound) {
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT) {
tier = nbt.getByte(TierTag) max 0 min 2
- super.readFromNBTForClient(nbt)
+ super.loadForClient(nbt)
invertTouchMode = nbt.getBoolean(InvertTouchModeTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- nbt.setByte(TierTag, tier.toByte)
- super.writeToNBTForClient(nbt)
- nbt.setBoolean(InvertTouchModeTag, invertTouchMode)
+ override def saveForClient(nbt: CompoundNBT) {
+ nbt.putByte(TierTag, tier.toByte)
+ super.saveForClient(nbt)
+ nbt.putBoolean(InvertTouchModeTag, invertTouchMode)
}
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
override def getRenderBoundingBox =
if ((width == 1 && height == 1) || !isOrigin) super.getRenderBoundingBox
else cachedBounds match {
@@ -338,12 +345,12 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
b
}
- @SideOnly(Side.CLIENT)
- override def getMaxRenderDistanceSquared = if (isOrigin) super.getMaxRenderDistanceSquared else 0
+ @OnlyIn(Dist.CLIENT)
+ override def getViewDistance = if (isOrigin) super.getViewDistance else 0
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(origin.node)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(origin.node)
override protected def onRedstoneInputChanged(args: RedstoneChangedEventArgs) {
super.onRedstoneInputChanged(args)
@@ -374,7 +381,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
val opos = project(origin)
def tryMergeTowards(dx: Int, dy: Int) = {
val npos = unproject(opos.x + dx, opos.y + dy, opos.z)
- getWorld.blockExists(npos) && (getWorld.getTileEntity(npos) match {
+ getLevel.blockExists(npos) && (getLevel.getBlockEntity(npos) match {
case s: Screen if s.tier == tier && s.pitch == pitch && s.getColor == getColor && s.yaw == yaw && !screens.contains(s) =>
val spos = project(s.origin)
val canMergeAlongX = spos.y == opos.y && s.height == height && s.width + width <= Settings.get.maxScreenWidth
@@ -408,12 +415,12 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
}
private def project(t: Screen) = {
- def dot(f: EnumFacing, s: Screen) = f.getFrontOffsetX * s.x + f.getFrontOffsetY * s.y + f.getFrontOffsetZ * s.z
- BlockPosition(dot(toGlobal(EnumFacing.EAST), t), dot(toGlobal(EnumFacing.UP), t), dot(toGlobal(EnumFacing.SOUTH), t))
+ def dot(f: Direction, s: Screen) = f.getStepX * s.x + f.getStepY * s.y + f.getStepZ * s.z
+ BlockPosition(dot(toGlobal(Direction.EAST), t), dot(toGlobal(Direction.UP), t), dot(toGlobal(Direction.SOUTH), t))
}
private def unproject(x: Int, y: Int, z: Int) = {
- def dot(f: EnumFacing) = f.getFrontOffsetX * x + f.getFrontOffsetY * y + f.getFrontOffsetZ * z
- BlockPosition(dot(toLocal(EnumFacing.EAST)), dot(toLocal(EnumFacing.UP)), dot(toLocal(EnumFacing.SOUTH)))
+ def dot(f: Direction) = f.getStepX * x + f.getStepY * y + f.getStepZ * z
+ BlockPosition(dot(toLocal(Direction.EAST)), dot(toLocal(Direction.UP)), dot(toLocal(Direction.SOUTH)))
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/TileEntityTypes.java b/src/main/scala/li/cil/oc/common/tileentity/TileEntityTypes.java
new file mode 100644
index 0000000000..0b3e3de4a0
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/tileentity/TileEntityTypes.java
@@ -0,0 +1,118 @@
+package li.cil.oc.common.tileentity;
+
+import li.cil.oc.OpenComputers;
+import li.cil.oc.Constants;
+import li.cil.oc.api.Items;
+import net.minecraft.tileentity.TileEntityType;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.event.RegistryEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.registries.IForgeRegistry;
+import net.minecraftforge.registries.ObjectHolder;
+
+@ObjectHolder("opencomputers")
+public final class TileEntityTypes {
+ public static final TileEntityType ADAPTER = null;
+ public static final TileEntityType ASSEMBLER = null;
+ public static final TileEntityType CABLE = null;
+ public static final TileEntityType CAPACITOR = null;
+ public static final TileEntityType CARPETED_CAPACITOR = null;
+ public static final TileEntityType CASE = null;
+ public static final TileEntityType CHARGER = null;
+ public static final TileEntityType DISASSEMBLER = null;
+ public static final TileEntityType DISK_DRIVE = null;
+ public static final TileEntityType GEOLYZER = null;
+ public static final TileEntityType HOLOGRAM = null;
+ public static final TileEntityType KEYBOARD = null;
+ public static final TileEntityType MICROCONTROLLER = null;
+ public static final TileEntityType MOTION_SENSOR = null;
+ public static final TileEntityType NET_SPLITTER = null;
+ public static final TileEntityType POWER_CONVERTER = null;
+ public static final TileEntityType POWER_DISTRIBUTOR = null;
+ public static final TileEntityType PRINT = null;
+ public static final TileEntityType PRINTER = null;
+ public static final TileEntityType RACK = null;
+ public static final TileEntityType RAID = null;
+ public static final TileEntityType REDSTONE_IO = null;
+ public static final TileEntityType RELAY = null;
+ // We use the RobotProxy instead of Robot here because those are the ones actually found in the world.
+ // Beware of TileEntityType.create for this as it will construct a new, empty robot.
+ public static final TileEntityType ROBOT = null;
+ public static final TileEntityType SCREEN = null;
+ public static final TileEntityType TRANSPOSER = null;
+ public static final TileEntityType WAYPOINT = null;
+
+ @SubscribeEvent
+ public static void registerTileEntities(RegistryEvent.Register> e) {
+ register(e.getRegistry(), "adapter", TileEntityType.Builder.of(() -> new Adapter(ADAPTER),
+ Items.get(Constants.BlockName$.MODULE$.Adapter()).block()));
+ register(e.getRegistry(), "assembler", TileEntityType.Builder.of(() -> new Assembler(ASSEMBLER),
+ Items.get(Constants.BlockName$.MODULE$.Assembler()).block()));
+ register(e.getRegistry(), "cable", TileEntityType.Builder.of(() -> new Cable(CABLE),
+ Items.get(Constants.BlockName$.MODULE$.Cable()).block()));
+ register(e.getRegistry(), "capacitor", TileEntityType.Builder.of(() -> new Capacitor(CAPACITOR),
+ Items.get(Constants.BlockName$.MODULE$.Capacitor()).block()));
+ register(e.getRegistry(), "carpeted_capacitor", TileEntityType.Builder.of(() -> new CarpetedCapacitor(CARPETED_CAPACITOR),
+ Items.get(Constants.BlockName$.MODULE$.CarpetedCapacitor()).block()));
+ register(e.getRegistry(), "case", TileEntityType.Builder.of(() -> new Case(CASE),
+ Items.get(Constants.BlockName$.MODULE$.CaseCreative()).block(),
+ Items.get(Constants.BlockName$.MODULE$.CaseTier1()).block(),
+ Items.get(Constants.BlockName$.MODULE$.CaseTier2()).block(),
+ Items.get(Constants.BlockName$.MODULE$.CaseTier3()).block()));
+ register(e.getRegistry(), "charger", TileEntityType.Builder.of(() -> new Charger(CHARGER),
+ Items.get(Constants.BlockName$.MODULE$.Charger()).block()));
+ register(e.getRegistry(), "disassembler", TileEntityType.Builder.of(() -> new Disassembler(DISASSEMBLER),
+ Items.get(Constants.BlockName$.MODULE$.Disassembler()).block()));
+ register(e.getRegistry(), "disk_drive", TileEntityType.Builder.of(() -> new DiskDrive(DISK_DRIVE),
+ Items.get(Constants.BlockName$.MODULE$.DiskDrive()).block()));
+ register(e.getRegistry(), "geolyzer", TileEntityType.Builder.of(() -> new Geolyzer(GEOLYZER),
+ Items.get(Constants.BlockName$.MODULE$.Geolyzer()).block()));
+ register(e.getRegistry(), "hologram", TileEntityType.Builder.of(() -> new Hologram(HOLOGRAM),
+ Items.get(Constants.BlockName$.MODULE$.HologramTier1()).block(),
+ Items.get(Constants.BlockName$.MODULE$.HologramTier2()).block()));
+ register(e.getRegistry(), "keyboard", TileEntityType.Builder.of(() -> new Keyboard(KEYBOARD),
+ Items.get(Constants.BlockName$.MODULE$.Keyboard()).block()));
+ register(e.getRegistry(), "microcontroller", TileEntityType.Builder.of(() -> new Microcontroller(MICROCONTROLLER),
+ Items.get(Constants.BlockName$.MODULE$.Microcontroller()).block()));
+ register(e.getRegistry(), "motion_sensor", TileEntityType.Builder.of(() -> new MotionSensor(MOTION_SENSOR),
+ Items.get(Constants.BlockName$.MODULE$.MotionSensor()).block()));
+ register(e.getRegistry(), "net_splitter", TileEntityType.Builder.of(() -> new NetSplitter(NET_SPLITTER),
+ Items.get(Constants.BlockName$.MODULE$.NetSplitter()).block()));
+ register(e.getRegistry(), "power_converter", TileEntityType.Builder.of(() -> new PowerConverter(POWER_CONVERTER),
+ Items.get(Constants.BlockName$.MODULE$.PowerConverter()).block()));
+ register(e.getRegistry(), "power_distributor", TileEntityType.Builder.of(() -> new PowerDistributor(POWER_DISTRIBUTOR),
+ Items.get(Constants.BlockName$.MODULE$.PowerDistributor()).block()));
+ register(e.getRegistry(), "print", TileEntityType.Builder.of(() -> new Print(PRINT),
+ Items.get(Constants.BlockName$.MODULE$.Print()).block()));
+ register(e.getRegistry(), "printer", TileEntityType.Builder.of(() -> new Printer(PRINTER),
+ Items.get(Constants.BlockName$.MODULE$.Printer()).block()));
+ register(e.getRegistry(), "rack", TileEntityType.Builder.of(() -> new Rack(RACK),
+ Items.get(Constants.BlockName$.MODULE$.Rack()).block()));
+ register(e.getRegistry(), "raid", TileEntityType.Builder.of(() -> new Raid(RAID),
+ Items.get(Constants.BlockName$.MODULE$.Raid()).block()));
+ register(e.getRegistry(), "redstone_io", TileEntityType.Builder.of(() -> new Redstone(REDSTONE_IO),
+ Items.get(Constants.BlockName$.MODULE$.Redstone()).block()));
+ register(e.getRegistry(), "relay", TileEntityType.Builder.of(() -> new Relay(RELAY),
+ Items.get(Constants.BlockName$.MODULE$.Relay()).block()));
+ register(e.getRegistry(), "robot", TileEntityType.Builder.of(() -> new RobotProxy(ROBOT),
+ Items.get(Constants.BlockName$.MODULE$.Robot()).block()));
+ register(e.getRegistry(), "screen", TileEntityType.Builder.of(() -> new Screen(SCREEN),
+ Items.get(Constants.BlockName$.MODULE$.ScreenTier1()).block(),
+ Items.get(Constants.BlockName$.MODULE$.ScreenTier2()).block(),
+ Items.get(Constants.BlockName$.MODULE$.ScreenTier3()).block()));
+ register(e.getRegistry(), "transposer", TileEntityType.Builder.of(() -> new Transposer(TRANSPOSER),
+ Items.get(Constants.BlockName$.MODULE$.Transposer()).block()));
+ register(e.getRegistry(), "waypoint", TileEntityType.Builder.of(() -> new Waypoint(WAYPOINT),
+ Items.get(Constants.BlockName$.MODULE$.Waypoint()).block()));
+ }
+
+ private static void register(IForgeRegistry> registry, String name, TileEntityType.Builder> builder) {
+ TileEntityType> type = builder.build(null);
+ type.setRegistryName(new ResourceLocation(OpenComputers.ID(), name));
+ registry.register(type);
+ }
+
+ private TileEntityTypes() {
+ throw new Error();
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala b/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala
index 78a7fc8e9e..a1957e9b54 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Transposer.scala
@@ -1,9 +1,11 @@
package li.cil.oc.common.tileentity
import li.cil.oc.server.component
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
-class Transposer extends traits.Environment {
+class Transposer(selfType: TileEntityType[_ <: Transposer]) extends TileEntity(selfType) with traits.Environment {
val transposer = new component.Transposer.Block(this)
def node = transposer.node
@@ -11,13 +13,13 @@ class Transposer extends traits.Environment {
// Used on client side to check whether to render activity indicators.
var lastOperation = 0L
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- transposer.load(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ transposer.loadData(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- transposer.save(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ transposer.saveData(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Waypoint.scala b/src/main/scala/li/cil/oc/common/tileentity/Waypoint.scala
index 058a291765..0f69894c79 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Waypoint.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Waypoint.scala
@@ -8,19 +8,22 @@ import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.EventHandler
import li.cil.oc.server.network.Waypoints
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.{EnumFacing, EnumParticleTypes}
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
-
-class Waypoint extends traits.Environment with traits.Rotatable with traits.RedstoneAware with traits.Tickable {
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.particles.ParticleTypes
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.tileentity.TileEntityType
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
+
+class Waypoint(selfType: TileEntityType[_ <: Waypoint]) extends TileEntity(selfType) with traits.Environment with traits.Rotatable with traits.RedstoneAware with traits.Tickable {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("waypoint").
create()
var label = ""
- override def validFacings: Array[EnumFacing] = EnumFacing.values
+ override def validFacings: Array[Direction] = Direction.values
// ----------------------------------------------------------------------- //
@@ -39,14 +42,14 @@ class Waypoint extends traits.Environment with traits.Rotatable with traits.Reds
override def updateEntity(): Unit = {
super.updateEntity()
if (isClient) {
- val origin = position.toVec3.addVector(facing.getFrontOffsetX * 0.5, facing.getFrontOffsetY * 0.5, facing.getFrontOffsetZ * 0.5)
- val dx = (getWorld.rand.nextFloat() - 0.5f) * 0.8f
- val dy = (getWorld.rand.nextFloat() - 0.5f) * 0.8f
- val dz = (getWorld.rand.nextFloat() - 0.5f) * 0.8f
- val vx = (getWorld.rand.nextFloat() - 0.5f) * 0.2f + facing.getFrontOffsetX * 0.3f
- val vy = (getWorld.rand.nextFloat() - 0.5f) * 0.2f + facing.getFrontOffsetY * 0.3f - 0.5f
- val vz = (getWorld.rand.nextFloat() - 0.5f) * 0.2f + facing.getFrontOffsetZ * 0.3f
- getWorld.spawnParticle(EnumParticleTypes.PORTAL, origin.x + dx, origin.y + dy, origin.z + dz, vx, vy, vz)
+ val origin = position.toVec3.add(facing.getStepX * 0.5, facing.getStepY * 0.5, facing.getStepZ * 0.5)
+ val dx = (getLevel.random.nextFloat() - 0.5f) * 0.8f
+ val dy = (getLevel.random.nextFloat() - 0.5f) * 0.8f
+ val dz = (getLevel.random.nextFloat() - 0.5f) * 0.8f
+ val vx = (getLevel.random.nextFloat() - 0.5f) * 0.2f + facing.getStepX * 0.3f
+ val vy = (getLevel.random.nextFloat() - 0.5f) * 0.2f + facing.getStepY * 0.3f - 0.5f
+ val vz = (getLevel.random.nextFloat() - 0.5f) * 0.2f + facing.getStepZ * 0.3f
+ getLevel.addParticle(ParticleTypes.PORTAL, origin.x + dx, origin.y + dy, origin.z + dz, vx, vy, vz)
}
}
@@ -64,24 +67,24 @@ class Waypoint extends traits.Environment with traits.Rotatable with traits.Reds
private final val LabelTag = Settings.namespace + "label"
- override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT): Unit = {
+ super.loadForServer(nbt)
label = nbt.getString(LabelTag)
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
- nbt.setString(LabelTag, label)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
+ nbt.putString(LabelTag, label)
}
- @SideOnly(Side.CLIENT) override
- def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT) override
+ def loadForClient(nbt: CompoundNBT): Unit = {
+ super.loadForClient(nbt)
label = nbt.getString(LabelTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForClient(nbt)
- nbt.setString(LabelTag, label)
+ override def saveForClient(nbt: CompoundNBT): Unit = {
+ super.saveForClient(nbt)
+ nbt.putString(LabelTag, label)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala
index ae3e6c75a9..8727a627ef 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala
@@ -3,19 +3,16 @@ package li.cil.oc.common.tileentity.traits
import li.cil.oc.Settings
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.util.ExtendedNBT._
+import li.cil.oc.util.RotationHelper
import li.cil.oc.integration.Mods
import mrtjp.projectred.api.IBundledTile
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.nbt.NBTTagIntArray
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.IntArrayNBT
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.common.Optional
import java.util
-import li.cil.oc.integration.charset.{CapabilitiesCharset, ModCharset}
-import net.minecraftforge.common.capabilities.Capability
-
-trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
+trait BundledRedstoneAware extends RedstoneAware {
protected[tileentity] val _bundledInput: Array[Array[Int]] = Array.fill(6)(Array.fill(16)(-1))
@@ -42,7 +39,7 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
(0 until 6).map(side => (0 until 16).map(color => _bundledInput(side)(color) max _rednetInput(side)(color) max 0).toArray).toArray
}
- private def checkSide(side: EnumFacing): Int = {
+ private def checkSide(side: Direction): Int = {
val index = side.ordinal
if (index >= 6) throw new IndexOutOfBoundsException(s"Bad side $side")
index
@@ -53,14 +50,14 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
color
}
- def getBundledInput(side: EnumFacing): Array[Int] = {
+ def getBundledInput(side: Direction): Array[Int] = {
val sideIndex = checkSide(side)
val bundled = _bundledInput(sideIndex)
val rednet = _rednetInput(sideIndex)
- (bundled, rednet).zipped.map((a, b) => a max b max 0)
+ bundled.lazyZip(rednet).map((a, b) => a max b max 0)
}
- def getBundledInput(side: EnumFacing, color: Int): Int = {
+ def getBundledInput(side: Direction, color: Int): Int = {
val sideIndex = checkSide(side)
val colorIndex = checkColor(color)
val bundled = _bundledInput(sideIndex)(colorIndex)
@@ -68,20 +65,20 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
bundled max rednet max 0
}
- def setBundledInput(side: EnumFacing, color: Int, newValue: Int): Unit = {
+ def setBundledInput(side: Direction, color: Int, newValue: Int): Unit = {
updateInput(_bundledInput, side, color, newValue)
}
- def setBundledInput(side: EnumFacing, newBundledInput: Array[Int]): Unit = {
+ def setBundledInput(side: Direction, newBundledInput: Array[Int]): Unit = {
for (color <- 0 until 16) {
val value = if (newBundledInput == null || color >= newBundledInput.length) 0 else newBundledInput(color)
setBundledInput(side, color, value)
}
}
- def setRednetInput(side: EnumFacing, color: Int, value: Int): Unit = updateInput(_rednetInput, side, color, value)
+ def setRednetInput(side: Direction, color: Int, value: Int): Unit = updateInput(_rednetInput, side, color, value)
- def updateInput(inputs: Array[Array[Int]], side: EnumFacing, color: Int, newValue: Int): Unit = {
+ def updateInput(inputs: Array[Array[Int]], side: Direction, color: Int, newValue: Int): Unit = {
val sideIndex = checkSide(side)
val colorIndex = checkColor(color)
val oldValue = inputs(sideIndex)(colorIndex)
@@ -95,17 +92,17 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
def getBundledOutput: Array[Array[Int]] = _bundledInput
- def getBundledOutput(side: EnumFacing): Array[Int] = _bundledOutput(checkSide(toLocal(side)))
+ def getBundledOutput(side: Direction): Array[Int] = _bundledOutput(checkSide(toLocal(side)))
- def getBundledOutput(side: EnumFacing, color: Int): Int = getBundledOutput(side)(checkColor(color))
+ def getBundledOutput(side: Direction, color: Int): Int = getBundledOutput(side)(checkColor(color))
- def setBundledOutput(side: EnumFacing, color: Int, value: Int): Boolean = if (value != getBundledOutput(side, color)) {
+ def setBundledOutput(side: Direction, color: Int, value: Int): Boolean = if (value != getBundledOutput(side, color)) {
_bundledOutput(checkSide(toLocal(side)))(checkColor(color)) = value
onRedstoneOutputChanged(side)
true
} else false
- def setBundledOutput(side: EnumFacing, values: util.Map[_, _]): Boolean = {
+ def setBundledOutput(side: Direction, values: util.Map[_, _]): Boolean = {
val sideIndex = toLocal(side).ordinal
var changed: Boolean = false
(0 until 16).foreach(color => {
@@ -127,7 +124,7 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
def setBundledOutput(values: util.Map[_, _]): Boolean = {
var changed: Boolean = false
- EnumFacing.values.foreach(side => {
+ Direction.values.foreach(side => {
val sideIndex = toLocal(side).ordinal
// due to a bug in our jnlua layer, I cannot loop the map
getObjectFuzzy(values, sideIndex) match {
@@ -140,7 +137,7 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
// ----------------------------------------------------------------------- //
- override def updateRedstoneInput(side: EnumFacing) {
+ override def updateRedstoneInput(side: Direction) {
super.updateRedstoneInput(side)
setBundledInput(side, BundledRedstone.computeBundledInput(position, side))
}
@@ -151,26 +148,26 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
private final val BundledOutputTag = Settings.namespace + "rs.bundledOutput"
private final val RednetInputTag = Settings.namespace + "rs.rednetInput"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
- nbt.getTagList(BundledInputTag, NBT.TAG_INT_ARRAY).toArray[NBTTagIntArray].
- map(_.getIntArray).zipWithIndex.foreach {
+ nbt.getList(BundledInputTag, NBT.TAG_INT_ARRAY).toTagArray[IntArrayNBT].
+ map(_.getAsIntArray).zipWithIndex.foreach {
case (input, index) if index < _bundledInput.length =>
val safeLength = input.length min _bundledInput(index).length
input.copyToArray(_bundledInput(index), 0, safeLength)
case _ =>
}
- nbt.getTagList(BundledOutputTag, NBT.TAG_INT_ARRAY).toArray[NBTTagIntArray].
- map(_.getIntArray).zipWithIndex.foreach {
+ nbt.getList(BundledOutputTag, NBT.TAG_INT_ARRAY).toTagArray[IntArrayNBT].
+ map(_.getAsIntArray).zipWithIndex.foreach {
case (input, index) if index < _bundledOutput.length =>
val safeLength = input.length min _bundledOutput(index).length
input.copyToArray(_bundledOutput(index), 0, safeLength)
case _ =>
}
- nbt.getTagList(RednetInputTag, NBT.TAG_INT_ARRAY).toArray[NBTTagIntArray].
- map(_.getIntArray).zipWithIndex.foreach {
+ nbt.getList(RednetInputTag, NBT.TAG_INT_ARRAY).toTagArray[IntArrayNBT].
+ map(_.getAsIntArray).zipWithIndex.foreach {
case (input, index) if index < _rednetInput.length =>
val safeLength = input.length min _rednetInput(index).length
input.copyToArray(_rednetInput(index), 0, safeLength)
@@ -178,34 +175,12 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledTile {
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
nbt.setNewTagList(BundledInputTag, _bundledInput.view)
nbt.setNewTagList(BundledOutputTag, _bundledOutput.view)
nbt.setNewTagList(RednetInputTag, _rednetInput.view)
}
-
- override def hasCapability(capability: Capability[_], side: EnumFacing): Boolean = {
- if (capability == CapabilitiesCharset.BUNDLED_EMITTER || capability == CapabilitiesCharset.BUNDLED_RECEIVER) {
- true
- } else {
- super.hasCapability(capability, side)
- }
- }
-
- override def getCapability[T](capability: Capability[T], side: EnumFacing): T = {
- if (capability == CapabilitiesCharset.BUNDLED_EMITTER || capability == CapabilitiesCharset.BUNDLED_RECEIVER) {
- new ModCharset.BundledRedstoneView(getBundledOutput(side), () => setBundledInput(side, BundledRedstone.computeBundledInput(position, side))).asInstanceOf[T]
- } else {
- super.getCapability(capability, side)
- }
- }
-
- @Optional.Method(modid = Mods.IDs.ProjectRedTransmission)
- override def canConnectBundled(side: Int): Boolean = isOutputEnabled
-
- @Optional.Method(modid = Mods.IDs.ProjectRedTransmission)
- override def getBundledSignal(side: Int): Array[Byte] = getBundledOutput(EnumFacing.getFront(side)).map(value => math.min(math.max(value, 0), 255).toByte)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala
index 66129b6e5a..9d68f9b9f9 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Colored.scala
@@ -4,10 +4,10 @@ import li.cil.oc.Settings
import li.cil.oc.api.internal
import li.cil.oc.server.PacketSender
import li.cil.oc.util.Color
-import net.minecraft.item.EnumDyeColor
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.item.DyeColor
+import net.minecraft.nbt.CompoundNBT
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
trait Colored extends TileEntity with internal.Colored {
private var _color = 0
@@ -24,7 +24,7 @@ trait Colored extends TileEntity with internal.Colored {
override def controlsConnectivity = false
protected def onColorChanged() {
- if (getWorld != null && isServer) {
+ if (getLevel != null && isServer) {
PacketSender.sendColorChange(this)
}
}
@@ -34,29 +34,29 @@ trait Colored extends TileEntity with internal.Colored {
private final val RenderColorTag = Settings.namespace + "renderColorRGB"
private final val RenderColorTagCompat = Settings.namespace + "renderColor"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(RenderColorTagCompat)) {
- _color = Color.rgbValues(EnumDyeColor.byMetadata(nbt.getInteger(RenderColorTagCompat)))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ if (nbt.contains(RenderColorTagCompat)) {
+ _color = Color.rgbValues(DyeColor.byId(nbt.getInt(RenderColorTagCompat)))
}
- if (nbt.hasKey(RenderColorTag)) {
- _color = nbt.getInteger(RenderColorTag)
+ if (nbt.contains(RenderColorTag)) {
+ _color = nbt.getInt(RenderColorTag)
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setInteger(RenderColorTag, _color)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.putInt(RenderColorTag, _color)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- _color = nbt.getInteger(RenderColorTag)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ _color = nbt.getInt(RenderColorTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setInteger(RenderColorTag, _color)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putInt(RenderColorTag, _color)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala
index af21bd4945..a8297148e9 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala
@@ -9,12 +9,13 @@ import li.cil.oc.util.ExtendedInventory._
import li.cil.oc.util.StackOption
import li.cil.oc.util.StackOption._
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.common.util.LazyOptional
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import scala.collection.mutable
@@ -26,8 +27,8 @@ trait ComponentInventory extends Environment with Inventory with inventory.Compo
// Cache changes to inventory slots on the client side to avoid recreating
// components when we don't have to and the slots are just cleared by MC
// temporarily.
- private lazy val pendingRemovalsActual = mutable.ArrayBuffer.fill(getSizeInventory)(EmptyStack: StackOption)
- private lazy val pendingAddsActual = mutable.ArrayBuffer.fill(getSizeInventory)(EmptyStack: StackOption)
+ private lazy val pendingRemovalsActual = mutable.ArrayBuffer.fill(getContainerSize)(EmptyStack: StackOption)
+ private lazy val pendingAddsActual = mutable.ArrayBuffer.fill(getContainerSize)(EmptyStack: StackOption)
private var updateScheduled = false
def pendingRemovals = {
adjustSize(pendingRemovalsActual)
@@ -39,12 +40,12 @@ trait ComponentInventory extends Environment with Inventory with inventory.Compo
}
private def adjustSize(buffer: mutable.ArrayBuffer[StackOption]): Unit = {
- val delta = buffer.length - getSizeInventory
+ val delta = buffer.length - getContainerSize
if (delta > 0) {
buffer.remove(buffer.length - delta, delta)
}
else if (delta < 0) {
- buffer.sizeHint(getSizeInventory)
+ buffer.sizeHint(getContainerSize)
for (i <- 0 until -delta) {
buffer += EmptyStack
}
@@ -56,17 +57,17 @@ trait ComponentInventory extends Environment with Inventory with inventory.Compo
for (slot <- this.indices) {
(pendingRemovals(slot), pendingAdds(slot)) match {
case (SomeStack(removed), SomeStack(added)) =>
- if (!removed.isItemEqual(added) || !ItemStack.areItemStackTagsEqual(removed, added)) {
+ if (!removed.sameItem(added) || !ItemStack.tagMatches(removed, added)) {
super.onItemRemoved(slot, removed)
super.onItemAdded(slot, added)
- markDirty()
+ setChanged()
} // else: No change, ignore.
case (SomeStack(removed), EmptyStack) =>
super.onItemRemoved(slot, removed)
- markDirty()
+ setChanged()
case (EmptyStack, SomeStack(added)) =>
super.onItemAdded(slot, added)
- markDirty()
+ setChanged()
case _ => // No change.
}
@@ -86,7 +87,7 @@ trait ComponentInventory extends Environment with Inventory with inventory.Compo
if (isServer) super.onItemAdded(slot, stack)
else {
pendingRemovals(slot) match {
- case SomeStack(removed) if removed.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(removed, stack) =>
+ case SomeStack(removed) if removed.sameItem(stack) && ItemStack.tagMatches(removed, stack) =>
// Reverted to original state.
pendingAdds(slot) = EmptyStack
pendingRemovals(slot) = EmptyStack
@@ -153,37 +154,31 @@ trait ComponentInventory extends Environment with Inventory with inventory.Compo
}
}
- override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
+ override def getCapability[T](capability: Capability[T], facing: Direction): LazyOptional[T] = {
val localFacing = this match {
case rotatable: Rotatable => rotatable.toLocal(facing)
case _ => facing
}
- super.hasCapability(capability, facing) || components.exists {
- case Some(component: ICapabilityProvider) => component.hasCapability(capability, localFacing)
- case _ => false
- }
- }
-
- override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
- val localFacing = this match {
- case rotatable: Rotatable => rotatable.toLocal(facing)
- case _ => facing
+ for (curr <- components) curr match {
+ case Some(comp: ICapabilityProvider) => {
+ val cap = comp.getCapability(capability, localFacing)
+ if (cap.isPresent) return cap
+ }
+ case _ =>
}
- (if (super.hasCapability(capability, facing)) Option(super.getCapability(capability, facing)) else None).orElse(components.collectFirst {
- case Some(component: ICapabilityProvider) if component.hasCapability(capability, localFacing) => component.getCapability(capability, localFacing)
- }).getOrElse(null.asInstanceOf[T])
+ super.getCapability(capability, facing)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
+ override def saveForClient(nbt: CompoundNBT) {
connectComponents()
- super.writeToNBTForClient(nbt)
- save(nbt)
+ super.saveForClient(nbt)
+ saveData(nbt)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- load(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ loadData(nbt)
connectComponents()
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala
index c05425bf82..4baff36ce7 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala
@@ -13,16 +13,16 @@ import li.cil.oc.integration.opencomputers.DriverRedstoneCard
import li.cil.oc.server.agent
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.nbt.NBTTagString
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.nbt.StringNBT
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-import scala.collection.convert.WrapAsJava._
+import scala.collection.convert.ImplicitConversionsToJava._
import scala.collection.mutable
trait Computer extends Environment with ComponentInventory with Rotatable with BundledRedstoneAware with api.network.Analyzable with api.machine.MachineHost with StateAware with Tickable {
@@ -54,18 +54,18 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
if (value) {
hasErrored = false
}
- if (getWorld != null) {
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
- if (getWorld.isRemote) {
+ if (getLevel != null) {
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
+ if (getLevel.isClientSide) {
runSound.foreach(sound =>
- if (_isRunning) Sound.startLoop(this, sound, 0.5f, 50 + getWorld.rand.nextInt(50))
+ if (_isRunning) Sound.startLoop(this, sound, 0.5f, 50 + getLevel.random.nextInt(50))
else Sound.stopLoop(this)
)
}
}
}
- @SideOnly(Side.CLIENT)
+ @OnlyIn(Dist.CLIENT)
def setUsers(list: Iterable[String]) {
_users.clear()
_users ++= list
@@ -78,8 +78,8 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
// ----------------------------------------------------------------------- //
- override def internalComponents(): lang.Iterable[ItemStack] = (0 until getSizeInventory).collect {
- case slot if !getStackInSlot(slot).isEmpty && isComponentSlot(slot, getStackInSlot(slot)) => getStackInSlot(slot)
+ override def internalComponents(): lang.Iterable[ItemStack] = (0 until getContainerSize).collect {
+ case slot if !getItem(slot).isEmpty && isComponentSlot(slot, getItem(slot)) => getItem(slot)
}
@@ -122,7 +122,7 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
}
protected def onRunningChanged(): Unit = {
- markDirty()
+ setChanged()
ServerPacketSender.sendComputerState(this)
}
@@ -140,62 +140,62 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
private final val IsRunningTag = Settings.namespace + "isRunning"
private final val UsersTag = Settings.namespace + "users"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
// God, this is so ugly... will need to rework the robot architecture.
// This is required for loading auxiliary data (kernel state), because the
// coordinates in the actual robot won't be set properly, otherwise.
this match {
- case proxy: RobotProxy => proxy.robot.setPos(getPos)
+ case proxy: RobotProxy => proxy.robot.setLevelAndPosition(getLevel, getBlockPos)
case _ =>
}
- machine.load(nbt.getCompoundTag(ComputerTag))
+ machine.loadData(nbt.getCompound(ComputerTag))
// Kickstart initialization to avoid values getting overwritten by
- // readFromNBTForClient if that packet is handled after a manual
+ // loadForClient if that packet is handled after a manual
// initialization / state change packet.
setRunning(machine.isRunning)
_isOutputEnabled = hasRedstoneCard
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
if (machine != null) {
- nbt.setNewCompoundTag(ComputerTag, machine.save)
+ nbt.setNewCompoundTag(ComputerTag, machine.saveData)
}
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
hasErrored = nbt.getBoolean(HasErroredTag)
setRunning(nbt.getBoolean(IsRunningTag))
_users.clear()
- _users ++= nbt.getTagList(UsersTag, NBT.TAG_STRING).map((tag: NBTTagString) => tag.getString)
- if (_isRunning) runSound.foreach(sound => Sound.startLoop(this, sound, 0.5f, 1000 + getWorld.rand.nextInt(2000)))
+ _users ++= nbt.getList(UsersTag, NBT.TAG_STRING).map((tag: StringNBT) => tag.getAsString)
+ if (_isRunning) runSound.foreach(sound => Sound.startLoop(this, sound, 0.5f, 1000 + getLevel.random.nextInt(2000)))
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setBoolean(HasErroredTag, machine != null && machine.lastError != null)
- nbt.setBoolean(IsRunningTag, isRunning)
- nbt.setNewTagList(UsersTag, machine.users.map(user => new NBTTagString(user)))
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putBoolean(HasErroredTag, machine != null && machine.lastError != null)
+ nbt.putBoolean(IsRunningTag, isRunning)
+ nbt.setNewTagList(UsersTag, machine.users.map(user => StringNBT.valueOf(user)))
}
// ----------------------------------------------------------------------- //
- override def markDirty() {
- super.markDirty()
+ override def setChanged() {
+ super.setChanged()
if (isServer) {
machine.onHostChanged()
setOutputEnabled(hasRedstoneCard)
}
}
- override def isUsableByPlayer(player: EntityPlayer): Boolean =
- super.isUsableByPlayer(player) && (player match {
+ override def stillValid(player: PlayerEntity): Boolean =
+ super.stillValid(player) && (player match {
case fakePlayer: agent.Player => canInteract(fakePlayer.agent.ownerName())
- case _ => canInteract(player.getName)
+ case _ => canInteract(player.getName.getString)
})
override protected def onRotationChanged() {
@@ -211,5 +211,5 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
// ----------------------------------------------------------------------- //
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(machine.node)
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float) = Array(machine.node)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala
index ce5c928a73..9f71cb00e2 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala
@@ -6,13 +6,15 @@ import li.cil.oc.api.network.Connector
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.common.EventHandler
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
+import net.minecraftforge.client.model.data.IModelData
+import net.minecraftforge.client.model.data.ModelProperty
-trait Environment extends TileEntity with network.Environment with network.EnvironmentHost {
+trait Environment extends TileEntity with network.Environment with network.EnvironmentHost with IModelData {
protected var isChangeScheduled = false
- override def world = getWorld
+ override def world = getLevel
override def xPosition = x + 0.5
@@ -20,7 +22,7 @@ trait Environment extends TileEntity with network.Environment with network.Envir
override def zPosition = z + 0.5
- override def markChanged() = if (this.isInstanceOf[Tickable]) isChangeScheduled = true else getWorld.markChunkDirty(getPos, this)
+ override def markChanged() = if (this.isInstanceOf[Tickable]) isChangeScheduled = true else getLevel.blockEntityChanged(getBlockPos, this)
protected def isConnected = node != null && node.address != null && node.network != null
@@ -36,7 +38,7 @@ trait Environment extends TileEntity with network.Environment with network.Envir
override def updateEntity() {
super.updateEntity()
if (isChangeScheduled) {
- getWorld.markChunkDirty(getPos, this)
+ getLevel.blockEntityChanged(getBlockPos, this)
isChangeScheduled = false
}
}
@@ -46,7 +48,7 @@ trait Environment extends TileEntity with network.Environment with network.Envir
if (isServer) {
Option(node).foreach(_.remove)
this match {
- case sidedEnvironment: SidedEnvironment => for (side <- EnumFacing.values) {
+ case sidedEnvironment: SidedEnvironment => for (side <- Direction.values) {
Option(sidedEnvironment.sidedNode(side)).foreach(_.remove())
}
case _ =>
@@ -58,17 +60,17 @@ trait Environment extends TileEntity with network.Environment with network.Envir
private final val NodeTag = Settings.namespace + "node"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
if (node != null && node.host == this) {
- node.load(nbt.getCompoundTag(NodeTag))
+ node.loadData(nbt.getCompound(NodeTag))
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
if (node != null && node.host == this) {
- nbt.setNewCompoundTag(NodeTag, node.save)
+ nbt.setNewCompoundTag(NodeTag, node.saveData)
}
}
@@ -95,4 +97,18 @@ trait Environment extends TileEntity with network.Environment with network.Envir
// ----------------------------------------------------------------------- //
protected def result(args: Any*) = li.cil.oc.util.ResultWrapper.result(args: _*)
+
+ // ----------------------------------------------------------------------- //
+
+ @Deprecated
+ override def getModelData() = this
+
+ @Deprecated
+ override def hasProperty(prop: ModelProperty[_]) = false
+
+ @Deprecated
+ override def getData[T](prop: ModelProperty[T]): T = null.asInstanceOf[T]
+
+ @Deprecated
+ override def setData[T](prop: ModelProperty[T], value: T): T = null.asInstanceOf[T]
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala
index 82ef43ca12..d21fb66f19 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala
@@ -6,11 +6,11 @@ import li.cil.oc.api.network._
import li.cil.oc.common.tileentity.traits
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.MovingAverage
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
import net.minecraftforge.common.util.Constants.NBT
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
import scala.collection.mutable
@@ -23,9 +23,9 @@ trait Hub extends traits.Environment with SidedEnvironment with Tickable {
plug.node.address != null &&
plug.node.network != null)
- protected val plugs = EnumFacing.values.map(side => createPlug(side))
+ protected val plugs = Direction.values.map(side => createPlug(side))
- val queue = mutable.Queue.empty[(Option[EnumFacing], Packet)]
+ val queue = mutable.Queue.empty[(Option[Direction], Packet)]
var maxQueueSize = queueBaseSize
@@ -54,10 +54,10 @@ trait Hub extends traits.Environment with SidedEnvironment with Tickable {
// ----------------------------------------------------------------------- //
- @SideOnly(Side.CLIENT)
- override def canConnect(side: EnumFacing) = side != null
+ @OnlyIn(Dist.CLIENT)
+ override def canConnect(side: Direction) = side != null
- override def sidedNode(side: EnumFacing) = if (side != null) plugs(side.ordinal).node else null
+ override def sidedNode(side: Direction) = if (side != null) plugs(side.ordinal).node else null
// ----------------------------------------------------------------------- //
@@ -79,13 +79,13 @@ trait Hub extends traits.Environment with SidedEnvironment with Tickable {
relayCooldown = relayDelay - 1
}
}
- else if (getWorld.getTotalWorldTime % relayDelay == 0) {
+ else if (getLevel.getGameTime % relayDelay == 0) {
packetsPerCycleAvg += 0
}
}
}
- def tryEnqueuePacket(sourceSide: Option[EnumFacing], packet: Packet) = queue.synchronized {
+ def tryEnqueuePacket(sourceSide: Option[Direction], packet: Packet) = queue.synchronized {
if (packet.ttl > 0 && queue.size < maxQueueSize) {
queue += sourceSide -> packet.hop()
if (relayCooldown < 0) {
@@ -96,8 +96,8 @@ trait Hub extends traits.Environment with SidedEnvironment with Tickable {
else false
}
- protected def relayPacket(sourceSide: Option[EnumFacing], packet: Packet) {
- for (side <- EnumFacing.values) {
+ protected def relayPacket(sourceSide: Option[Direction], packet: Packet) {
+ for (side <- Direction.values) {
if (sourceSide.isEmpty || sourceSide.get != side) {
val node = sidedNode(side)
if (node != null) {
@@ -114,51 +114,51 @@ trait Hub extends traits.Environment with SidedEnvironment with Tickable {
private final val SideTag = "side"
private final val RelayCooldownTag = Settings.namespace + "relayCooldown"
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- nbt.getTagList(PlugsTag, NBT.TAG_COMPOUND).toArray[NBTTagCompound].
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ nbt.getList(PlugsTag, NBT.TAG_COMPOUND).toTagArray[CompoundNBT].
zipWithIndex.foreach {
- case (tag, index) => plugs(index).node.load(tag)
+ case (tag, index) => plugs(index).node.loadData(tag)
}
- nbt.getTagList(QueueTag, NBT.TAG_COMPOUND).foreach(
- (tag: NBTTagCompound) => {
+ nbt.getList(QueueTag, NBT.TAG_COMPOUND).foreach(
+ (tag: CompoundNBT) => {
val side = tag.getDirection(SideTag)
val packet = api.Network.newPacket(tag)
queue += side -> packet
})
- if (nbt.hasKey(RelayCooldownTag)) {
- relayCooldown = nbt.getInteger(RelayCooldownTag)
+ if (nbt.contains(RelayCooldownTag)) {
+ relayCooldown = nbt.getInt(RelayCooldownTag)
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) = queue.synchronized {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) = queue.synchronized {
+ super.saveForServer(nbt)
// Side check for Waila (and other mods that may call this client side).
if (isServer) {
nbt.setNewTagList(PlugsTag, plugs.map(plug => {
- val plugNbt = new NBTTagCompound()
+ val plugNbt = new CompoundNBT()
if (plug.node != null)
- plug.node.save(plugNbt)
+ plug.node.saveData(plugNbt)
plugNbt
}))
nbt.setNewTagList(QueueTag, queue.map {
case (sourceSide, packet) =>
- val tag = new NBTTagCompound()
+ val tag = new CompoundNBT()
tag.setDirection(SideTag, sourceSide)
- packet.save(tag)
+ packet.saveData(tag)
tag
})
if (relayCooldown > 0) {
- nbt.setInteger(RelayCooldownTag, relayCooldown)
+ nbt.putInt(RelayCooldownTag, relayCooldown)
}
}
}
// ----------------------------------------------------------------------- //
- protected def createPlug(side: EnumFacing) = new Plug(side)
+ protected def createPlug(side: Direction) = new Plug(side)
- protected class Plug(val side: EnumFacing) extends api.network.Environment {
+ protected class Plug(val side: Direction) extends api.network.Environment {
val node = createNode(this)
override def onMessage(message: Message) {
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala
index 38ae6cad4e..f08db57d6a 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala
@@ -1,16 +1,18 @@
package li.cil.oc.common.tileentity.traits
+import java.util.function.Consumer
+
import li.cil.oc.common.inventory
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.InventoryUtils
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
import net.minecraft.util.text.ITextComponent
trait Inventory extends TileEntity with inventory.Inventory {
- private lazy val inventory = Array.fill[ItemStack](getSizeInventory)(ItemStack.EMPTY)
+ private lazy val inventory = Array.fill[ItemStack](getContainerSize)(ItemStack.EMPTY)
def items = inventory
@@ -18,29 +20,31 @@ trait Inventory extends TileEntity with inventory.Inventory {
override def getDisplayName: ITextComponent = super[Inventory].getDisplayName
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- load(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ loadData(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- save(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ saveData(nbt)
}
// ----------------------------------------------------------------------- //
- override def isUsableByPlayer(player: EntityPlayer) =
- player.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
+ override def stillValid(player: PlayerEntity) =
+ player.distanceToSqr(x + 0.5, y + 0.5, z + 0.5) <= 64
// ----------------------------------------------------------------------- //
- def dropSlot(slot: Int, count: Int = getInventoryStackLimit, direction: Option[EnumFacing] = None) =
- InventoryUtils.dropSlot(BlockPosition(x, y, z, getWorld), this, slot, count, direction)
+ def forAllLoot(dst: Consumer[ItemStack]): Unit = InventoryUtils.forAllSlots(this, dst)
+
+ def dropSlot(slot: Int, count: Int = getMaxStackSize, direction: Option[Direction] = None) =
+ InventoryUtils.dropSlot(BlockPosition(x, y, z, getLevel), this, slot, count, direction)
def dropAllSlots() =
- InventoryUtils.dropAllSlots(BlockPosition(x, y, z, getWorld), this)
+ InventoryUtils.dropAllSlots(BlockPosition(x, y, z, getLevel), this)
- def spawnStackInWorld(stack: ItemStack, direction: Option[EnumFacing] = None) =
- InventoryUtils.spawnStackInWorld(BlockPosition(x, y, z, getWorld), stack, direction)
+ def spawnStackInWorld(stack: ItemStack, direction: Option[Direction] = None) =
+ InventoryUtils.spawnStackInWorld(BlockPosition(x, y, z, getLevel), stack, direction)
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/NotAnalyzable.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/NotAnalyzable.scala
index ab04a1141a..45f1692a61 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/NotAnalyzable.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/NotAnalyzable.scala
@@ -2,9 +2,9 @@ package li.cil.oc.common.tileentity.traits
import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network.Node
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.util.EnumFacing
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.util.Direction
trait NotAnalyzable extends Analyzable {
- override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = null
+ override def onAnalyze(player: PlayerEntity, side: Direction, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = null
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala
index cc8f3bb63d..389776ac81 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala
@@ -1,50 +1,51 @@
package li.cil.oc.common.tileentity.traits
import li.cil.oc.Settings
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import li.cil.oc.util.RotationHelper
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
/**
* @author Vexatos
*/
trait OpenSides extends TileEntity {
- protected def SideCount = EnumFacing.VALUES.length
+ protected def SideCount = RotationHelper.getNumDirections
protected def defaultState: Boolean = false
var openSides = Array.fill(SideCount)(defaultState)
- def compressSides = (EnumFacing.values(), openSides).zipped.foldLeft(0)((acc, entry) => acc | (if (entry._2) 1 << entry._1.ordinal() else 0)).toByte
+ def compressSides = (Direction.values(), openSides).zipped.foldLeft(0)((acc, entry) => acc | (if (entry._2) 1 << entry._1.ordinal() else 0)).toByte
- def uncompressSides(byte: Byte) = EnumFacing.values().map(d => ((1 << d.ordinal()) & byte) != 0)
+ def uncompressSides(byte: Byte) = Direction.values().map(d => ((1 << d.ordinal()) & byte) != 0)
- def isSideOpen(side: EnumFacing) = side != null && openSides(side.ordinal())
+ def isSideOpen(side: Direction) = side != null && openSides(side.ordinal())
- def setSideOpen(side: EnumFacing, value: Boolean): Unit = if (side != null && openSides(side.ordinal()) != value) {
+ def setSideOpen(side: Direction, value: Boolean): Unit = if (side != null && openSides(side.ordinal()) != value) {
openSides(side.ordinal()) = value
}
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(Settings.namespace + "openSides"))
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
+ if (nbt.contains(Settings.namespace + "openSides"))
openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides"))
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setByte(Settings.namespace + "openSides", compressSides)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
+ nbt.putByte(Settings.namespace + "openSides", compressSides)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides"))
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setByte(Settings.namespace + "openSides", compressSides)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putByte(Settings.namespace + "openSides", compressSides)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala
index 7701b48b0f..885a92b3c9 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala
@@ -1,14 +1,14 @@
package li.cil.oc.common.tileentity.traits
-import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
// Used to get notifications from containers when a player changes a slot in
-// this inventory. Normally the player causing a setInventorySlotContents is
+// this inventory. Normally the player causing a setItem is
// unavailable. Using this we gain access to the causing player, allowing for
// some player-specific logic, such as the disassembler working instantaneously
// when used by a player in creative mode.
trait PlayerInputAware extends IInventory {
- def onSetInventorySlotContents(player: EntityPlayer, slot: Int, stack: ItemStack): Unit
+ def onSetInventorySlotContents(player: PlayerEntity, slot: Int, stack: ItemStack): Unit
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala
index cfdade18dd..dc91b37ad8 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala
@@ -2,5 +2,4 @@ package li.cil.oc.common.tileentity.traits
trait PowerAcceptor
extends power.Common
- with power.IndustrialCraft2Experimental
- with power.AppliedEnergistics2
+ // with power.AppliedEnergistics2
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerBalancer.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerBalancer.scala
index f66269a245..b533f6a1a4 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerBalancer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerBalancer.scala
@@ -3,7 +3,7 @@ package li.cil.oc.common.tileentity.traits
import li.cil.oc.Settings
import li.cil.oc.api.network.Connector
import li.cil.oc.api.network.SidedEnvironment
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
trait PowerBalancer extends PowerInformation with SidedEnvironment with Tickable {
var globalBuffer, globalBufferSize = 0.0
@@ -12,7 +12,7 @@ trait PowerBalancer extends PowerInformation with SidedEnvironment with Tickable
override def updateEntity() {
super.updateEntity()
- if (isServer && isConnected && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (isServer && isConnected && getLevel.getGameTime % Settings.get.tickFrequency == 0) {
val nodes = connectors
def network(connector: Connector) = if (connector != null && connector.network != null) connector.network else this
// Yeeeeah, so that just happened... it's not a beauty, but it works. This
@@ -55,7 +55,7 @@ trait PowerBalancer extends PowerInformation with SidedEnvironment with Tickable
(sumBuffer, sumSize)
}
- private def connectors = EnumFacing.values.view.map(sidedNode(_) match {
+ private def connectors = Direction.values.view.map(sidedNode(_) match {
case connector: Connector => connector
case _ => null
})
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala
index 43dff2cf3c..0bf77a62b4 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala
@@ -2,9 +2,9 @@ package li.cil.oc.common.tileentity.traits
import li.cil.oc.Settings
import li.cil.oc.server.{PacketSender => ServerPacketSender}
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.nbt.CompoundNBT
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
trait PowerInformation extends TileEntity {
private var lastSentRatio = -1.0
@@ -43,17 +43,17 @@ trait PowerInformation extends TileEntity {
private final val GlobalBufferTag = Settings.namespace + "globalBuffer"
private final val GlobalBufferSizeTag = Settings.namespace + "globalBufferSize"
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
globalBuffer = nbt.getDouble(GlobalBufferTag)
globalBufferSize = nbt.getDouble(GlobalBufferSizeTag)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
lastSentRatio = if (globalBufferSize > 0) globalBuffer / globalBufferSize else 0
- nbt.setDouble(GlobalBufferTag, globalBuffer)
- nbt.setDouble(GlobalBufferSizeTag, globalBufferSize)
+ nbt.putDouble(GlobalBufferTag, globalBuffer)
+ nbt.putDouble(GlobalBufferSizeTag, globalBufferSize)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala
index c2a3563220..d2a35706b0 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala
@@ -5,12 +5,12 @@ import li.cil.oc.Settings
import li.cil.oc.common.EventHandler
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.server.{PacketSender => ServerPacketSender}
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
-case class RedstoneChangedEventArgs (side: EnumFacing, oldValue: Int, newValue: Int, color: Int = -1)
+case class RedstoneChangedEventArgs (side: Direction, oldValue: Int, newValue: Int, color: Int = -1)
trait RedstoneAware extends RotationAware {
protected[tileentity] val _input: Array[Int] = Array.fill(6)(-1)
@@ -59,9 +59,9 @@ trait RedstoneAware extends RotationAware {
def getInput: Array[Int] = _input.map(math.max(_, 0))
- def getInput(side: EnumFacing): Int = _input(side.ordinal) max 0
+ def getInput(side: Direction): Int = _input(side.ordinal) max 0
- def setInput(side: EnumFacing, newInput: Int): Unit = {
+ def setInput(side: Direction, newInput: Int): Unit = {
val oldInput = _input(side.ordinal())
_input(side.ordinal()) = newInput
if (oldInput >= 0 && newInput != oldInput) {
@@ -70,7 +70,7 @@ trait RedstoneAware extends RotationAware {
}
def setInput(values: Array[Int]): Unit = {
- for (side <- EnumFacing.values) {
+ for (side <- Direction.values) {
val value = if (side.ordinal <= values.length) values(side.ordinal) else 0
setInput(side, value)
}
@@ -78,13 +78,13 @@ trait RedstoneAware extends RotationAware {
def maxInput: Int = _input.map(math.max(_, 0)).max
- def getOutput: Array[Int] = EnumFacing.values.map{ side: EnumFacing => _output(toLocal(side).ordinal) }
+ def getOutput: Array[Int] = Direction.values.map{ side: Direction => _output(toLocal(side).ordinal) }
- def getOutput(side: EnumFacing) = if (_output != null && _output.length > toLocal(side).ordinal())
+ def getOutput(side: Direction) = if (_output != null && _output.length > toLocal(side).ordinal())
_output(toLocal(side).ordinal())
else 0
- def setOutput(side: EnumFacing, value: Int): Boolean = {
+ def setOutput(side: Direction, value: Int): Boolean = {
if (value == getOutput(side)) return false
_output(toLocal(side).ordinal()) = value
onRedstoneOutputChanged(side)
@@ -93,7 +93,7 @@ trait RedstoneAware extends RotationAware {
def setOutput(values: util.Map[_, _]): Boolean = {
var changed: Boolean = false
- EnumFacing.values.foreach(side => {
+ Direction.values.foreach(side => {
val sideIndex = toLocal(side).ordinal
// due to a bug in our jnlua layer, I cannot loop the map
valueToInt(getObjectFuzzy(values, sideIndex)) match {
@@ -108,7 +108,7 @@ trait RedstoneAware extends RotationAware {
if (this.isInstanceOf[Tickable]) {
shouldUpdateInput = isServer
} else {
- EnumFacing.values().foreach(updateRedstoneInput)
+ Direction.values().foreach(updateRedstoneInput)
}
}
@@ -119,24 +119,24 @@ trait RedstoneAware extends RotationAware {
if (isServer) {
if (shouldUpdateInput) {
shouldUpdateInput = false
- EnumFacing.values().foreach(updateRedstoneInput)
+ Direction.values().foreach(updateRedstoneInput)
}
}
}
- override def validate(): Unit = {
- super.validate()
+ override def clearRemoved(): Unit = {
+ super.clearRemoved()
if (!this.isInstanceOf[Tickable]) {
- EventHandler.scheduleServer(() => EnumFacing.values().foreach(updateRedstoneInput))
+ EventHandler.scheduleServer(() => Direction.values().foreach(updateRedstoneInput))
}
}
- def updateRedstoneInput(side: EnumFacing): Unit = setInput(side, BundledRedstone.computeInput(position, side))
+ def updateRedstoneInput(side: Direction): Unit = setInput(side, BundledRedstone.computeInput(position, side))
// ----------------------------------------------------------------------- //
- override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT): Unit = {
+ super.loadForServer(nbt)
val input = nbt.getIntArray(Settings.namespace + "rs.input")
input.copyToArray(_input, 0, input.length min _input.length)
@@ -144,24 +144,24 @@ trait RedstoneAware extends RotationAware {
output.copyToArray(_output, 0, output.length min _output.length)
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
- nbt.setIntArray(Settings.namespace + "rs.input", _input)
- nbt.setIntArray(Settings.namespace + "rs.output", _output)
+ nbt.putIntArray(Settings.namespace + "rs.input", _input)
+ nbt.putIntArray(Settings.namespace + "rs.output", _output)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
_isOutputEnabled = nbt.getBoolean("isOutputEnabled")
nbt.getIntArray("output").copyToArray(_output)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setBoolean("isOutputEnabled", _isOutputEnabled)
- nbt.setIntArray("output", _output)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putBoolean("isOutputEnabled", _isOutputEnabled)
+ nbt.putIntArray("output", _output)
}
// ----------------------------------------------------------------------- //
@@ -169,19 +169,19 @@ trait RedstoneAware extends RotationAware {
protected def onRedstoneInputChanged(args: RedstoneChangedEventArgs) {}
protected def onRedstoneOutputEnabledChanged() {
- if (getWorld != null) {
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, true)
+ if (getLevel != null) {
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
if (isServer) ServerPacketSender.sendRedstoneState(this)
- else getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ else getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
- protected def onRedstoneOutputChanged(side: EnumFacing) {
- val blockPos = getPos.offset(side)
- getWorld.neighborChanged(blockPos, getBlockType, blockPos)
- getWorld.notifyNeighborsOfStateExcept(blockPos, getWorld.getBlockState(blockPos).getBlock, side.getOpposite)
+ protected def onRedstoneOutputChanged(side: Direction) {
+ val blockPos = getBlockPos.relative(side)
+ getLevel.neighborChanged(blockPos, getBlockState.getBlock, blockPos)
+ getLevel.updateNeighborsAtExceptFromFacing(blockPos, getLevel.getBlockState(blockPos).getBlock, side.getOpposite)
if (isServer) ServerPacketSender.sendRedstoneState(this)
- else getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ else getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala
index 9a223605d9..fab750e853 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala
@@ -1,14 +1,16 @@
package li.cil.oc.common.tileentity.traits
import li.cil.oc.api.internal
+import li.cil.oc.common.block.SimpleBlock
import li.cil.oc.common.block.property.PropertyRotatable
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedEnumFacing._
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.RotationHelper
-import net.minecraft.block.state.IBlockState
+import net.minecraft.block.BlockState
import net.minecraft.entity.Entity
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
+import net.minecraft.util.Rotation
/** TileEntity base class for rotatable blocks. */
trait Rotatable extends RotationAware with internal.Rotatable {
@@ -16,92 +18,98 @@ trait Rotatable extends RotationAware with internal.Rotatable {
// Lookup tables
// ----------------------------------------------------------------------- //
- private val pitch2Direction = Array(EnumFacing.UP, EnumFacing.NORTH, EnumFacing.DOWN)
+ private val pitch2Direction = Array(Direction.UP, Direction.NORTH, Direction.DOWN)
- private val yaw2Direction = Array(EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.NORTH, EnumFacing.EAST)
+ private val yaw2Direction = Array(Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST)
// ----------------------------------------------------------------------- //
// Accessors
// ----------------------------------------------------------------------- //
- def pitch = if (getWorld != null && getWorld.isBlockLoaded(getPos)) getBlockType match {
- case rotatable if getWorld.getBlockState(getPos).getProperties.containsKey(PropertyRotatable.Pitch) => getWorld.getBlockState(getPos).getValue(PropertyRotatable.Pitch)
- case _ => EnumFacing.NORTH
+ def pitch = if (getLevel != null && getLevel.isLoaded(getBlockPos)) getBlockState.getBlock match {
+ case rotatable if getLevel.getBlockState(getBlockPos).getProperties.contains(PropertyRotatable.Pitch) => getLevel.getBlockState(getBlockPos).getValue(PropertyRotatable.Pitch)
+ case _ => Direction.NORTH
} else null
- def pitch_=(value: EnumFacing): Unit =
+ def pitch_=(value: Direction): Unit =
trySetPitchYaw(value match {
- case EnumFacing.DOWN | EnumFacing.UP => value
- case _ => EnumFacing.NORTH
+ case Direction.DOWN | Direction.UP => value
+ case _ => Direction.NORTH
}, yaw)
- def yaw = if (getWorld != null && getWorld.isBlockLoaded(getPos)) getBlockType match {
- case rotatable if getWorld.getBlockState(getPos).getProperties.containsKey(PropertyRotatable.Yaw) => getWorld.getBlockState(getPos).getValue(PropertyRotatable.Yaw)
- case rotatable if getWorld.getBlockState(getPos).getProperties.containsKey(PropertyRotatable.Facing) => getWorld.getBlockState(getPos).getValue(PropertyRotatable.Facing)
- case _ => EnumFacing.SOUTH
+ def yaw = if (getLevel != null && getLevel.isLoaded(getBlockPos)) getBlockState.getBlock match {
+ case rotatable if getLevel.getBlockState(getBlockPos).getProperties.contains(PropertyRotatable.Yaw) => getLevel.getBlockState(getBlockPos).getValue(PropertyRotatable.Yaw)
+ case rotatable if getLevel.getBlockState(getBlockPos).getProperties.contains(PropertyRotatable.Facing) => getLevel.getBlockState(getBlockPos).getValue(PropertyRotatable.Facing)
+ case _ => Direction.SOUTH
} else null
- def yaw_=(value: EnumFacing): Unit =
+ def yaw_=(value: Direction): Unit =
trySetPitchYaw(pitch, value match {
- case EnumFacing.DOWN | EnumFacing.UP => yaw
+ case Direction.DOWN | Direction.UP => yaw
case _ => value
})
def setFromEntityPitchAndYaw(entity: Entity) =
trySetPitchYaw(
- pitch2Direction((entity.rotationPitch / 90).round + 1),
- yaw2Direction((entity.rotationYaw / 360 * 4).round & 3))
+ pitch2Direction((entity.xRot / 90).round + 1),
+ yaw2Direction((entity.yRot / 360 * 4).round & 3))
- def setFromFacing(value: EnumFacing) =
+ def setFromFacing(value: Direction) =
value match {
- case EnumFacing.DOWN | EnumFacing.UP =>
+ case Direction.DOWN | Direction.UP =>
trySetPitchYaw(value, yaw)
case yaw =>
- trySetPitchYaw(EnumFacing.NORTH, yaw)
+ trySetPitchYaw(Direction.NORTH, yaw)
}
def invertRotation() =
trySetPitchYaw(pitch match {
- case EnumFacing.DOWN | EnumFacing.UP => pitch.getOpposite
- case _ => EnumFacing.NORTH
+ case Direction.DOWN | Direction.UP => pitch.getOpposite
+ case _ => Direction.NORTH
}, yaw.getOpposite)
override def facing = pitch match {
- case EnumFacing.DOWN | EnumFacing.UP => pitch
+ case Direction.DOWN | Direction.UP => pitch
case _ => yaw
}
- def rotate(axis: EnumFacing) = {
- val block = getWorld.getBlock(position)
- if (block != null) {
- val valid = block.getValidRotations(getWorld, getPos)
- if (valid != null && valid.contains(axis)) {
- val (newPitch, newYaw) = facing.getRotation(axis) match {
- case value@(EnumFacing.UP | EnumFacing.DOWN) =>
- if (value == pitch) (value, yaw.getRotation(axis))
- else (value, yaw)
- case value => (EnumFacing.NORTH, value)
+ def rotate(axis: Direction) = {
+ val state = getLevel.getBlockState(getBlockPos)
+ state.getBlock match {
+ case simple: SimpleBlock => {
+ val valid = simple.getValidRotations(getLevel, getBlockPos)
+ if (valid != null && valid.contains(axis)) {
+ val (newPitch, newYaw) = facing.getRotation(axis) match {
+ case value@(Direction.UP | Direction.DOWN) =>
+ if (value == pitch) (value, yaw.getRotation(axis))
+ else (value, yaw)
+ case value => (Direction.NORTH, value)
+ }
+ trySetPitchYaw(newPitch, newYaw)
}
- trySetPitchYaw(newPitch, newYaw)
+ else false
}
- else false
+ case _ if axis == Direction.UP || axis == Direction.DOWN => {
+ val updated = state.rotate(getLevel, getBlockPos, if (axis == Direction.DOWN) Rotation.COUNTERCLOCKWISE_90 else Rotation.CLOCKWISE_90)
+ updated != state && getLevel.setBlockAndUpdate(getBlockPos, updated)
+ }
+ case _ => false
}
- else false
}
- override def toLocal(value: EnumFacing) = if (value == null) null else {
+ override def toLocal(value: Direction) = if (value == null) null else {
val p = pitch
val y = yaw
if (p != null && y != null) RotationHelper.toLocal(pitch, yaw, value) else null
}
- override def toGlobal(value: EnumFacing) = if (value == null) null else {
+ override def toGlobal(value: Direction) = if (value == null) null else {
val p = pitch
val y = yaw
if (p != null && y != null) RotationHelper.toGlobal(pitch, yaw, value) else null
}
- def validFacings = Array(EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.EAST)
+ def validFacings = Array(Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
// ----------------------------------------------------------------------- //
@@ -110,36 +118,36 @@ trait Rotatable extends RotationAware with internal.Rotatable {
ServerPacketSender.sendRotatableState(this)
}
else {
- getWorld.notifyBlockUpdate(getPos)
+ getLevel.notifyBlockUpdate(getBlockPos)
}
- getWorld.notifyNeighborsOfStateChange(getPos, getBlockType, false)
+ getLevel.updateNeighborsAt(getBlockPos, getBlockState.getBlock)
}
// ----------------------------------------------------------------------- //
/** Updates cached translation array and sends notification to clients. */
protected def updateTranslation(): Unit = {
- if (getWorld != null) {
+ if (getLevel != null) {
onRotationChanged()
}
}
/** Validates new values against the allowed rotations as set in our block. */
- protected def trySetPitchYaw(pitch: EnumFacing, yaw: EnumFacing) = {
- val oldState = getWorld.getBlockState(getPos)
- def setState(newState: IBlockState): Boolean = {
+ protected def trySetPitchYaw(pitch: Direction, yaw: Direction) = {
+ val oldState = getLevel.getBlockState(getBlockPos)
+ def setState(newState: BlockState): Boolean = {
if (oldState.hashCode() != newState.hashCode()) {
- getWorld.setBlockState(getPos, newState)
+ getLevel.setBlockAndUpdate(getBlockPos, newState)
updateTranslation()
true
}
else false
}
- getBlockType match {
- case rotatable if oldState.getProperties.containsKey(PropertyRotatable.Pitch) && oldState.getProperties.containsKey(PropertyRotatable.Yaw) =>
- setState(oldState.withProperty(PropertyRotatable.Pitch, pitch).withProperty(PropertyRotatable.Yaw, yaw))
- case rotatable if oldState.getProperties.containsKey(PropertyRotatable.Facing) =>
- setState(oldState.withProperty(PropertyRotatable.Facing, yaw))
+ getBlockState.getBlock match {
+ case rotatable if oldState.hasProperty(PropertyRotatable.Pitch) && oldState.hasProperty(PropertyRotatable.Yaw) =>
+ setState(oldState.setValue(PropertyRotatable.Pitch, pitch).setValue(PropertyRotatable.Yaw, yaw))
+ case rotatable if oldState.hasProperty(PropertyRotatable.Facing) =>
+ setState(oldState.setValue(PropertyRotatable.Facing, yaw))
case _ => false
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/RotatableTile.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/RotatableTile.scala
index 0ea62e3c16..c7979fa09e 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/RotatableTile.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/RotatableTile.scala
@@ -1,10 +1,11 @@
package li.cil.oc.common.tileentity.traits
import li.cil.oc.Settings
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import li.cil.oc.util.RotationHelper
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
/**
* Like Rotatable, but stores the rotation information in the TE's NBT instead
@@ -16,10 +17,10 @@ trait RotatableTile extends Rotatable {
// ----------------------------------------------------------------------- //
/** One of Up, Down and North (where north means forward/no pitch). */
- private var _pitch = EnumFacing.NORTH
+ private var _pitch = Direction.NORTH
/** One of the four cardinal directions. */
- private var _yaw = EnumFacing.SOUTH
+ private var _yaw = Direction.SOUTH
// ----------------------------------------------------------------------- //
// Accessors
@@ -34,43 +35,43 @@ trait RotatableTile extends Rotatable {
private final val PitchTag = Settings.namespace + "pitch"
private final val YawTag = Settings.namespace + "yaw"
- override def readFromNBTForServer(nbt: NBTTagCompound) = {
- super.readFromNBTForServer(nbt)
- if (nbt.hasKey(PitchTag)) {
- pitch = EnumFacing.getFront(nbt.getInteger(PitchTag))
+ override def loadForServer(nbt: CompoundNBT) = {
+ super.loadForServer(nbt)
+ if (nbt.contains(PitchTag)) {
+ pitch = Direction.from3DDataValue(nbt.getInt(PitchTag))
}
- if (nbt.hasKey(YawTag)) {
- yaw = EnumFacing.getFront(nbt.getInteger(YawTag))
+ if (nbt.contains(YawTag)) {
+ yaw = Direction.from3DDataValue(nbt.getInt(YawTag))
}
validatePitchAndYaw()
}
- override def writeToNBTForServer(nbt: NBTTagCompound) = {
- super.writeToNBTForServer(nbt)
- nbt.setInteger(PitchTag, pitch.ordinal)
- nbt.setInteger(YawTag, yaw.ordinal)
+ override def saveForServer(nbt: CompoundNBT) = {
+ super.saveForServer(nbt)
+ nbt.putInt(PitchTag, pitch.ordinal)
+ nbt.putInt(YawTag, yaw.ordinal)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- pitch = EnumFacing.getFront(nbt.getInteger(PitchTag))
- yaw = EnumFacing.getFront(nbt.getInteger(YawTag))
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ pitch = Direction.from3DDataValue(nbt.getInt(PitchTag))
+ yaw = Direction.from3DDataValue(nbt.getInt(YawTag))
validatePitchAndYaw()
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- nbt.setInteger(PitchTag, pitch.ordinal)
- nbt.setInteger(YawTag, yaw.ordinal)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ nbt.putInt(PitchTag, pitch.ordinal)
+ nbt.putInt(YawTag, yaw.ordinal)
}
private def validatePitchAndYaw() {
if (!_pitch.getAxis.isVertical) {
- _pitch = EnumFacing.NORTH
+ _pitch = Direction.NORTH
}
if (!_yaw.getAxis.isHorizontal) {
- _yaw = EnumFacing.SOUTH
+ _yaw = Direction.SOUTH
}
updateTranslation()
}
@@ -78,7 +79,7 @@ trait RotatableTile extends Rotatable {
// ----------------------------------------------------------------------- //
/** Validates new values against the allowed rotations as set in our block. */
- override protected def trySetPitchYaw(pitch: EnumFacing, yaw: EnumFacing) = {
+ override protected def trySetPitchYaw(pitch: Direction, yaw: Direction) = {
var changed = false
if (pitch != _pitch) {
changed = true
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/RotationAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/RotationAware.scala
index 908f8d52d8..8c134796ab 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/RotationAware.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/RotationAware.scala
@@ -1,9 +1,9 @@
package li.cil.oc.common.tileentity.traits
-import net.minecraft.util.EnumFacing
+import net.minecraft.util.Direction
trait RotationAware extends TileEntity {
- def toLocal(value: EnumFacing) = value
+ def toLocal(value: Direction) = value
- def toGlobal(value: EnumFacing) = value
+ def toGlobal(value: Direction) = value
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/TextBuffer.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/TextBuffer.scala
index bc0ae7798f..59212aba8f 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/TextBuffer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/TextBuffer.scala
@@ -5,9 +5,9 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.api.network.Node
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.nbt.CompoundNBT
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
trait TextBuffer extends Environment with Tickable {
lazy val buffer: internal.TextBuffer = {
@@ -32,24 +32,24 @@ trait TextBuffer extends Environment with Tickable {
// ----------------------------------------------------------------------- //
- override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
- super.readFromNBTForServer(nbt)
- buffer.load(nbt)
+ override def loadForServer(nbt: CompoundNBT): Unit = {
+ super.loadForServer(nbt)
+ buffer.loadData(nbt)
}
- override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- super.writeToNBTForServer(nbt)
- buffer.save(nbt)
+ override def saveForServer(nbt: CompoundNBT): Unit = {
+ super.saveForServer(nbt)
+ buffer.saveData(nbt)
}
- @SideOnly(Side.CLIENT)
- override def readFromNBTForClient(nbt: NBTTagCompound) {
- super.readFromNBTForClient(nbt)
- buffer.load(nbt)
+ @OnlyIn(Dist.CLIENT)
+ override def loadForClient(nbt: CompoundNBT) {
+ super.loadForClient(nbt)
+ buffer.loadData(nbt)
}
- override def writeToNBTForClient(nbt: NBTTagCompound) {
- super.writeToNBTForClient(nbt)
- buffer.save(nbt)
+ override def saveForClient(nbt: CompoundNBT) {
+ super.saveForClient(nbt)
+ buffer.saveData(nbt)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Tickable.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Tickable.scala
index 9632cb67e9..b7e65db5b4 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Tickable.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Tickable.scala
@@ -1,7 +1,7 @@
package li.cil.oc.common.tileentity.traits
-import net.minecraft.util.ITickable
+import net.minecraft.tileentity.ITickableTileEntity
-trait Tickable extends TileEntity with ITickable {
- override def update(): Unit = updateEntity()
+trait Tickable extends TileEntity with ITickableTileEntity {
+ override def tick(): Unit = updateEntity()
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala
index 4607894d4d..a4e96ff011 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala
@@ -6,50 +6,50 @@ import li.cil.oc.client.Sound
import li.cil.oc.common.SaveHandler
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.SideTracker
-import net.minecraft.block.state.IBlockState
-import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.block.BlockState
+import net.minecraft.nbt.CompoundNBT
import net.minecraft.network.NetworkManager
-import net.minecraft.network.play.server.SPacketUpdateTileEntity
+import net.minecraft.network.play.server.SUpdateTileEntityPacket
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
trait TileEntity extends net.minecraft.tileentity.TileEntity {
private final val IsServerDataTag = Settings.namespace + "isServerData"
- def x: Int = getPos.getX
+ def x: Int = getBlockPos.getX
- def y: Int = getPos.getY
+ def y: Int = getBlockPos.getY
- def z: Int = getPos.getZ
+ def z: Int = getBlockPos.getZ
- def position = BlockPosition(x, y, z, getWorld)
+ def position = BlockPosition(x, y, z, getLevel)
def isClient: Boolean = !isServer
- def isServer: Boolean = if (getWorld != null) !getWorld.isRemote else SideTracker.isServer
+ def isServer: Boolean = if (getLevel != null) !getLevel.isClientSide else SideTracker.isServer
// ----------------------------------------------------------------------- //
def updateEntity() {
- if (Settings.get.periodicallyForceLightUpdate && getWorld.getTotalWorldTime % 40 == 0 && getBlockType.getLightValue(getWorld.getBlockState(getPos), getWorld, getPos) > 0) {
- getWorld.notifyBlockUpdate(getPos, getWorld.getBlockState(getPos), getWorld.getBlockState(getPos), 3)
+ if (Settings.get.periodicallyForceLightUpdate && getLevel.getGameTime % 40 == 0 && getBlockState.getBlock.getLightValue(getLevel.getBlockState(getBlockPos), getLevel, getBlockPos) > 0) {
+ getLevel.sendBlockUpdated(getBlockPos, getLevel.getBlockState(getBlockPos), getLevel.getBlockState(getBlockPos), 3)
}
}
- override def validate() {
- super.validate()
+ override def clearRemoved() {
+ super.clearRemoved()
initialize()
}
- override def invalidate() {
- super.invalidate()
+ override def setRemoved() {
+ super.setRemoved()
dispose()
}
- override def onChunkUnload() {
- super.onChunkUnload()
+ override def onChunkUnloaded() {
+ super.onChunkUnloaded()
try dispose() catch {
case t: Throwable => OpenComputers.log.error("Failed properly disposing a tile entity, things may leak and or break.", t)
}
@@ -67,53 +67,52 @@ trait TileEntity extends net.minecraft.tileentity.TileEntity {
// ----------------------------------------------------------------------- //
- override def shouldRefresh(world: World, pos: BlockPos, oldState: IBlockState, newSate: IBlockState): Boolean = oldState.getBlock != newSate.getBlock
+ def loadForServer(nbt: CompoundNBT) {}
- def readFromNBTForServer(nbt: NBTTagCompound): Unit = super.readFromNBT(nbt)
-
- def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
- nbt.setBoolean(IsServerDataTag, true)
- super.writeToNBT(nbt)
+ def saveForServer(nbt: CompoundNBT): Unit = {
+ nbt.putBoolean(IsServerDataTag, true)
+ super.save(nbt)
}
- @SideOnly(Side.CLIENT)
- def readFromNBTForClient(nbt: NBTTagCompound) {}
+ @OnlyIn(Dist.CLIENT)
+ def loadForClient(nbt: CompoundNBT) {}
- def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
- nbt.setBoolean(IsServerDataTag, false)
+ def saveForClient(nbt: CompoundNBT): Unit = {
+ nbt.putBoolean(IsServerDataTag, false)
}
// ----------------------------------------------------------------------- //
- override def readFromNBT(nbt: NBTTagCompound): Unit = {
+ override def load(state: BlockState, nbt: CompoundNBT): Unit = {
+ super.load(state, nbt)
if (isServer || nbt.getBoolean(IsServerDataTag)) {
- readFromNBTForServer(nbt)
+ loadForServer(nbt)
}
else {
- readFromNBTForClient(nbt)
+ loadForClient(nbt)
}
}
- override def writeToNBT(nbt: NBTTagCompound): NBTTagCompound = {
+ override def save(nbt: CompoundNBT): CompoundNBT = {
if (isServer) {
- writeToNBTForServer(nbt)
+ saveForServer(nbt)
}
nbt
}
- override def getUpdatePacket: SPacketUpdateTileEntity = {
+ override def getUpdatePacket: SUpdateTileEntityPacket = {
// Obfuscation workaround. If it works.
val te = this.asInstanceOf[net.minecraft.tileentity.TileEntity]
- new SPacketUpdateTileEntity(te.getPos, te.getBlockMetadata, te.getUpdateTag)
+ new SUpdateTileEntityPacket(te.getBlockPos, 0, te.getUpdateTag)
}
- override def getUpdateTag: NBTTagCompound = {
+ override def getUpdateTag: CompoundNBT = {
val nbt = super.getUpdateTag
// See comment on savingForClients variable.
SaveHandler.savingForClients = true
try {
- try writeToNBTForClient(nbt) catch {
+ try saveForClient(nbt) catch {
case e: Throwable => OpenComputers.log.warn("There was a problem writing a TileEntity description packet. Please report this if you see it!", e)
}
} finally {
@@ -123,8 +122,8 @@ trait TileEntity extends net.minecraft.tileentity.TileEntity {
nbt
}
- override def onDataPacket(manager: NetworkManager, packet: SPacketUpdateTileEntity) {
- try readFromNBTForClient(packet.getNbtCompound) catch {
+ override def onDataPacket(manager: NetworkManager, packet: SUpdateTileEntityPacket) {
+ try loadForClient(packet.getTag) catch {
case e: Throwable => OpenComputers.log.warn("There was a problem reading a TileEntity description packet. Please report this if you see it!", e)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/AppliedEnergistics2.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/AppliedEnergistics2.scala
index 9d31151b8a..5e78937a19 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/AppliedEnergistics2.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/power/AppliedEnergistics2.scala
@@ -1,7 +1,7 @@
package li.cil.oc.common.tileentity.traits.power
import java.util
-import appeng.api.AEApi
+import appeng.api._
import appeng.api.config.Actionable
import appeng.api.config.PowerMultiplier
import appeng.api.networking._
@@ -10,14 +10,16 @@ import appeng.api.util.{AECableType, AEColor, AEPartLocation, DimensionalCoord}
import li.cil.oc.Settings
import li.cil.oc.common.EventHandler
import li.cil.oc.integration.Mods
+import li.cil.oc.integration.appeng.AEUtil
import li.cil.oc.integration.util.Power
import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
+import net.minecraft.nbt.CompoundNBT
+import net.minecraft.util.Direction
+import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import net.minecraftforge.fml.common._
-import scala.collection.JavaConversions
+import scala.collection.JavaConverters
trait AppliedEnergistics2 extends Common with IGridHost {
private lazy val useAppliedEnergistics2Power = isServer && Mods.AppliedEnergistics2.isModAvailable
@@ -27,12 +29,11 @@ trait AppliedEnergistics2 extends Common with IGridHost {
override def updateEntity() {
super.updateEntity()
- if (useAppliedEnergistics2Power && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
+ if (useAppliedEnergistics2Power && getLevel.getGameTime % Settings.get.tickFrequency == 0) {
updateEnergy()
}
}
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
private def updateEnergy() {
tryAllSides((demand, _) => {
val grid = getGridNode(AEPartLocation.INTERNAL).getGrid
@@ -47,37 +48,36 @@ trait AppliedEnergistics2 extends Common with IGridHost {
}, Power.fromAE, Power.toAE)
}
- override def validate() {
- super.validate()
- if (useAppliedEnergistics2Power) EventHandler.scheduleAE2Add(this)
+ override def clearRemoved() {
+ super.clearRemoved()
+ if (useAppliedEnergistics2Power) EventHandler.AE2.scheduleAE2Add(this)
}
- override def invalidate() {
- super.invalidate()
+ override def setRemoved() {
+ super.setRemoved()
if (useAppliedEnergistics2Power) securityBreak()
}
- override def onChunkUnload() {
- super.onChunkUnload()
+ override def onChunkUnloaded() {
+ super.onChunkUnloaded()
if (useAppliedEnergistics2Power) securityBreak()
}
// ----------------------------------------------------------------------- //
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
+ override def loadForServer(nbt: CompoundNBT) {
+ super.loadForServer(nbt)
if (useAppliedEnergistics2Power) loadNode(nbt)
}
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
- private def loadNode(nbt: NBTTagCompound): Unit = {
+ private def loadNode(nbt: CompoundNBT): Unit = {
getGridNode(AEPartLocation.INTERNAL).loadFromNBT(Settings.namespace + "ae2power", nbt)
}
- override def setWorld(worldIn: World): Unit = {
- if (getWorld == worldIn)
+ override def setLevelAndPosition(worldIn: World, pos: BlockPos): Unit = {
+ if (getLevel == worldIn)
return
- super.setWorld(worldIn)
+ super.setLevelAndPosition(worldIn, pos)
if (worldIn != null && isServer && useAppliedEnergistics2Power) {
val gridNode = getGridNode(AEPartLocation.INTERNAL)
if (gridNode != null) {
@@ -86,32 +86,28 @@ trait AppliedEnergistics2 extends Common with IGridHost {
}
}
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
+ override def saveForServer(nbt: CompoundNBT) {
+ super.saveForServer(nbt)
if (useAppliedEnergistics2Power) saveNode(nbt)
}
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
- private def saveNode(nbt: NBTTagCompound): Unit = {
+ private def saveNode(nbt: CompoundNBT): Unit = {
getGridNode(AEPartLocation.INTERNAL).saveToNBT(Settings.namespace + "ae2power", nbt)
}
// ----------------------------------------------------------------------- //
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
def getGridNode(side: AEPartLocation): IGridNode = node match {
case Some(gridNode: IGridNode) => gridNode
case _ if isServer =>
- val gridNode = AEApi.instance.grid.createGridNode(new AppliedEnergistics2GridBlock(this))
+ val gridNode = AEUtil.aeApi.get.grid.createGridNode(new AppliedEnergistics2GridBlock(this))
node = Option(gridNode)
gridNode
case _ => null
}
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
def getCableConnectionType(side: AEPartLocation): AECableType = AECableType.SMART
- @Optional.Method(modid = Mods.IDs.AppliedEnergistics2)
def securityBreak() {
getGridNode(AEPartLocation.INTERNAL).destroy()
}
@@ -130,12 +126,10 @@ class AppliedEnergistics2GridBlock(val tileEntity: AppliedEnergistics2) extends
override def onGridNotification(p1: GridNotification): Unit = {}
- override def setNetworkStatus(p1: IGrid, p2: Int): Unit = {}
-
- override def getConnectableSides: util.EnumSet[EnumFacing] = {
- val connectableSides = JavaConversions.asJavaCollection(EnumFacing.values.filter(tileEntity.canConnectPower))
+ override def getConnectableSides: util.EnumSet[Direction] = {
+ val connectableSides = JavaConverters.asJavaCollection(Direction.values.filter(tileEntity.canConnectPower))
if (connectableSides.isEmpty) {
- val s = util.EnumSet.copyOf(JavaConversions.asJavaCollection(EnumFacing.values))
+ val s = util.EnumSet.copyOf(JavaConverters.asJavaCollection(Direction.values))
s.clear()
s
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Common.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Common.scala
index fc240c9d95..c25351b9b9 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Common.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Common.scala
@@ -3,25 +3,25 @@ package li.cil.oc.common.tileentity.traits.power
import li.cil.oc.Settings
import li.cil.oc.api.network.Connector
import li.cil.oc.common.tileentity.traits.TileEntity
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.relauncher.Side
-import net.minecraftforge.fml.relauncher.SideOnly
+import net.minecraft.util.Direction
+import net.minecraftforge.api.distmarker.Dist
+import net.minecraftforge.api.distmarker.OnlyIn
trait Common extends TileEntity {
- @SideOnly(Side.CLIENT)
- protected def hasConnector(side: EnumFacing) = false
+ @OnlyIn(Dist.CLIENT)
+ protected def hasConnector(side: Direction) = false
- protected def connector(side: EnumFacing): Option[Connector] = None
+ protected def connector(side: Direction): Option[Connector] = None
// ----------------------------------------------------------------------- //
def energyThroughput: Double
- protected def tryAllSides(provider: (Double, EnumFacing) => Double, fromOther: Double => Double, toOther: Double => Double) {
+ protected def tryAllSides(provider: (Double, Direction) => Double, fromOther: Double => Double, toOther: Double => Double) {
// We make sure to only call this every `Settings.get.tickFrequency` ticks,
// but our throughput is per tick, so multiply this up for actual budget.
var budget = energyThroughput * Settings.get.tickFrequency
- for (side <- EnumFacing.values) {
+ for (side <- Direction.values) {
val demand = toOther(math.min(budget, globalDemand(side)))
if (demand > 1) {
val energy = fromOther(provider(demand, side))
@@ -34,7 +34,7 @@ trait Common extends TileEntity {
// ----------------------------------------------------------------------- //
- def canConnectPower(side: EnumFacing) =
+ def canConnectPower(side: Direction) =
!Settings.get.ignorePower && (if (isClient) hasConnector(side) else connector(side).isDefined)
/**
@@ -45,7 +45,7 @@ trait Common extends TileEntity {
* @param doReceive whether to actually inject energy or only simulate it.
* @return the amount of energy that was actually injected.
*/
- def tryChangeBuffer(side: EnumFacing, amount: Double, doReceive: Boolean = true): Double =
+ def tryChangeBuffer(side: Direction, amount: Double, doReceive: Boolean = true): Double =
if (isClient || Settings.get.ignorePower) 0
else connector(side) match {
case Some(node) =>
@@ -55,19 +55,19 @@ trait Common extends TileEntity {
case _ => 0
}
- def globalBuffer(side: EnumFacing): Double =
+ def globalBuffer(side: Direction): Double =
if (isClient) 0
else connector(side) match {
case Some(node) => node.globalBuffer
case _ => 0
}
- def globalBufferSize(side: EnumFacing): Double =
+ def globalBufferSize(side: Direction): Double =
if (isClient) 0
else connector(side) match {
case Some(node) => node.globalBufferSize
case _ => 0
}
- def globalDemand(side: EnumFacing) = math.max(0, math.min(energyThroughput, globalBufferSize(side) - globalBuffer(side)))
+ def globalDemand(side: Direction) = math.max(0, math.min(energyThroughput, globalBufferSize(side) - globalBuffer(side)))
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Factorization.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Factorization.scala
deleted file mode 100644
index 2d2371c4f1..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Factorization.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-/* TODO Factorization
-
-import cpw.mods.fml.common.Optional
-import factorization.api.Charge
-import factorization.api.Coord
-import factorization.api.IChargeConductor
-import li.cil.oc.OpenComputers
-import li.cil.oc.Settings
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.Power
-import net.minecraft.nbt.NBTTagCompound
-
-@Injectable.Interface(value = "factorization.api.IChargeConductor", modid = Mods.IDs.Factorization)
-trait Factorization extends Common {
- private lazy val useFactorizationPower = isServer && Mods.Factorization.isAvailable
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- private lazy val charge: AnyRef = this match {
- case conductor: IChargeConductor => new Charge(conductor)
- case _ =>
- OpenComputers.log.warn("Failed setting up Factorization power, which most likely means the class transformer did not run. You're probably running in an incorrectly configured development environment. Try adding `-Dfml.coreMods.load=li.cil.oc.common.launch.TransformerLoader` to the VM options of your run configuration.")
- null
- }
-
- // ----------------------------------------------------------------------- //
-
- override def updateEntity() {
- if (useFactorizationPower) updateEnergy()
- super.updateEntity()
- }
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- private def updateEnergy() {
- getCharge.update()
- if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
- tryAllSides((demand, _) => getCharge.deplete(demand.toInt), Power.fromCharge, Power.toCharge)
- }
- }
-
- override def invalidate() {
- if (useFactorizationPower) invalidateCharge()
- super.invalidate()
- }
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- private def invalidateCharge() {
- getCharge.invalidate()
- }
-
- override def onChunkUnload() {
- if (useFactorizationPower) removeCharge()
- super.onChunkUnload()
- }
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- private def removeCharge() {
- if (!isInvalid) getCharge.remove()
- }
-
- // ----------------------------------------------------------------------- //
-
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- if (useFactorizationPower) loadCharge(nbt)
- }
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- private def loadCharge(nbt: NBTTagCompound) {
- getCharge.readFromNBT(nbt, "fzpower")
- }
-
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- if (useFactorizationPower) saveCharge(nbt)
- }
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- private def saveCharge(nbt: NBTTagCompound) {
- getCharge.writeToNBT(nbt, "fzpower")
- }
-
- // ----------------------------------------------------------------------- //
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- def getCharge = if (Mods.Factorization.isAvailable) charge.asInstanceOf[Charge] else null
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- def getInfo = ""
-
- @Optional.Method(modid = Mods.IDs.Factorization)
- def getCoord = new Coord(this)
-}
-*/
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala
deleted file mode 100644
index 449c1be224..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-/* TODO Galacticraft
-
-import cpw.mods.fml.common.Optional
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.Power
-import micdoodle8.mods.galacticraft.api.power.EnergySource
-import micdoodle8.mods.galacticraft.api.transmission.NetworkType
-import net.minecraftforge.common.util.ForgeDirection
-
-import scala.language.implicitConversions
-
-@Injectable.InterfaceList(Array(
- new Injectable.Interface(value = "micdoodle8.mods.galacticraft.api.power.IEnergyHandlerGC", modid = Mods.IDs.Galacticraft),
- new Injectable.Interface(value = "micdoodle8.mods.galacticraft.api.transmission.tile.IConnector", modid = Mods.IDs.Galacticraft)
-))
-trait Galacticraft extends Common {
- private implicit def toDirection(source: EnergySource): ForgeDirection = source match {
- case adjacent: EnergySource.EnergySourceAdjacent => adjacent.direction
- case _ => ForgeDirection.UNKNOWN
- }
-
- @Optional.Method(modid = Mods.IDs.Galacticraft)
- def nodeAvailable(from: EnergySource) = Mods.Galacticraft.isAvailable && canConnectPower(from)
-
- @Optional.Method(modid = Mods.IDs.Galacticraft)
- def receiveEnergyGC(from: EnergySource, amount: Float, simulate: Boolean) =
- if (!Mods.Galacticraft.isAvailable) 0f
- else Power.toGC(tryChangeBuffer(from, Power.fromGC(amount), !simulate))
-
- @Optional.Method(modid = Mods.IDs.Galacticraft)
- def getEnergyStoredGC(from: EnergySource) = Power.toGC(globalBuffer(from))
-
- @Optional.Method(modid = Mods.IDs.Galacticraft)
- def getMaxEnergyStoredGC(from: EnergySource) = Power.toGC(globalBufferSize(from))
-
- @Optional.Method(modid = Mods.IDs.Galacticraft)
- def extractEnergyGC(from: EnergySource, amount: Float, simulate: Boolean) = 0f
-
- @Optional.Method(modid = Mods.IDs.Galacticraft)
- def canConnect(from: ForgeDirection, networkType: NetworkType): Boolean = networkType == NetworkType.POWER && canConnectPower(from)
-}
-*/
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Classic.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Classic.scala
deleted file mode 100644
index 52d32871ac..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Classic.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-/* TODO IC2 Classic
-
-import cpw.mods.fml.common.Optional
-import cpw.mods.fml.common.eventhandler.Event
-import ic2classic.api.Direction
-import li.cil.oc.OpenComputers
-import li.cil.oc.Settings
-import li.cil.oc.common.EventHandler
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.Power
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.tileentity.TileEntity
-import net.minecraftforge.common.MinecraftForge
-import net.minecraftforge.common.util.ForgeDirection
-
-@Injectable.Interface(value = "ic2classic.api.energy.tile.IEnergySink", modid = Mods.IDs.IndustrialCraft2Classic)
-trait IndustrialCraft2Classic extends Common with IndustrialCraft2Common {
- private var conversionBuffer = 0.0
-
- private lazy val useIndustrialCraft2ClassicPower = isServer && Mods.IndustrialCraft2Classic.isAvailable
-
- // ----------------------------------------------------------------------- //
-
- override def updateEntity() {
- super.updateEntity()
- if (useIndustrialCraft2ClassicPower && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
- updateEnergy()
- }
- }
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2Classic)
- private def updateEnergy() {
- tryAllSides((demand, _) => {
- val result = math.min(demand, conversionBuffer)
- conversionBuffer -= result
- result
- }, Power.fromEU, Power.toEU)
- }
-
- override def validate() {
- super.validate()
- if (useIndustrialCraft2ClassicPower && !addedToIC2PowerGrid) EventHandler.scheduleIC2Add(this)
- }
-
- override def invalidate() {
- super.invalidate()
- if (useIndustrialCraft2ClassicPower && addedToIC2PowerGrid) removeFromIC2Grid()
- }
-
- override def onChunkUnload() {
- super.onChunkUnload()
- if (useIndustrialCraft2ClassicPower && addedToIC2PowerGrid) removeFromIC2Grid()
- }
-
- private def removeFromIC2Grid() {
- try MinecraftForge.EVENT_BUS.post(Class.forName("ic2classic.api.energy.event.EnergyTileUnloadEvent").getConstructor(Class.forName("ic2classic.api.energy.tile.IEnergyTile")).newInstance(this).asInstanceOf[Event]) catch {
- case t: Throwable => OpenComputers.log.warn("Error removing node from IC2 grid.", t)
- }
- addedToIC2PowerGrid = false
- }
-
- // ----------------------------------------------------------------------- //
-
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- conversionBuffer = nbt.getDouble(Settings.namespace + "ic2cpower")
- }
-
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setDouble(Settings.namespace + "ic2cpower", conversionBuffer)
- }
-
- // ----------------------------------------------------------------------- //
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2Classic)
- def isAddedToEnergyNet: Boolean = addedToIC2PowerGrid
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2Classic)
- def getMaxSafeInput: Int = Int.MaxValue
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2Classic)
- def acceptsEnergyFrom(emitter: TileEntity, direction: Direction) = useIndustrialCraft2ClassicPower && canConnectPower(direction.toForgeDirection)
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2Classic)
- def injectEnergy(directionFrom: Direction, amount: Int): Boolean = {
- conversionBuffer += amount
- true
- }
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2Classic)
- def demandsEnergy: Int = {
- if (!useIndustrialCraft2ClassicPower) 0
- else if (conversionBuffer < energyThroughput * Settings.get.tickFrequency)
- math.min(ForgeDirection.VALID_DIRECTIONS.map(globalDemand).max, Power.toEU(energyThroughput)).toInt
- else 0
- }
-}
-*/
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Common.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Common.scala
deleted file mode 100644
index 368b2ff19b..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Common.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-
-trait IndustrialCraft2Common {
- var addedToIC2PowerGrid = false
-}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala
deleted file mode 100644
index b1b7eecea8..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-
-import ic2.api.energy.tile.IEnergyEmitter
-import li.cil.oc.OpenComputers
-import li.cil.oc.Settings
-import li.cil.oc.common.EventHandler
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.common.tileentity.traits
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.Power
-import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.common.MinecraftForge
-import net.minecraftforge.fml.common.Optional
-import net.minecraftforge.fml.common.eventhandler.Event
-
-@Injectable.Interface(value = "ic2.api.energy.tile.IEnergySink", modid = Mods.IDs.IndustrialCraft2)
-trait IndustrialCraft2Experimental extends Common with IndustrialCraft2Common with traits.Tickable {
- private var conversionBuffer = 0.0
-
- private lazy val useIndustrialCraft2Power = isServer && Mods.IndustrialCraft2.isModAvailable
-
- // ----------------------------------------------------------------------- //
-
- override def updateEntity() {
- super.updateEntity()
- if (useIndustrialCraft2Power && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) {
- updateEnergy()
- }
- }
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- private def updateEnergy() {
- tryAllSides((demand, _) => {
- val result = math.min(demand, conversionBuffer)
- conversionBuffer -= result
- result
- }, Power.fromEU, Power.toEU)
- }
-
- override def validate() {
- super.validate()
- if (useIndustrialCraft2Power && !addedToIC2PowerGrid) EventHandler.scheduleIC2Add(this)
- }
-
- override def invalidate() {
- super.invalidate()
- if (useIndustrialCraft2Power && addedToIC2PowerGrid) removeFromIC2Grid()
- }
-
- override def onChunkUnload() {
- super.onChunkUnload()
- if (useIndustrialCraft2Power && addedToIC2PowerGrid) removeFromIC2Grid()
- }
-
- private def removeFromIC2Grid() {
- try MinecraftForge.EVENT_BUS.post(Class.forName("ic2.api.energy.event.EnergyTileUnloadEvent").getConstructor(Class.forName("ic2.api.energy.tile.IEnergyTile")).newInstance(this).asInstanceOf[Event]) catch {
- case t: Throwable => OpenComputers.log.warn("Error removing node from IC2 grid.", t)
- }
- addedToIC2PowerGrid = false
- }
-
- // ----------------------------------------------------------------------- //
-
- override def readFromNBTForServer(nbt: NBTTagCompound) {
- super.readFromNBTForServer(nbt)
- conversionBuffer = nbt.getDouble(Settings.namespace + "ic2power")
- }
-
- override def writeToNBTForServer(nbt: NBTTagCompound) {
- super.writeToNBTForServer(nbt)
- nbt.setDouble(Settings.namespace + "ic2power", conversionBuffer)
- }
-
- // ----------------------------------------------------------------------- //
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- def getSinkTier: Int = Int.MaxValue
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- def acceptsEnergyFrom(emitter: IEnergyEmitter, direction: EnumFacing): Boolean = useIndustrialCraft2Power && canConnectPower(direction)
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- def injectEnergy(directionFrom: EnumFacing, amount: Double, voltage: Double): Double = {
- conversionBuffer += amount
- 0.0
- }
-
- @Optional.Method(modid = Mods.IDs.IndustrialCraft2)
- def getDemandedEnergy: Double = {
- if (!useIndustrialCraft2Power) 0.0
- else if (conversionBuffer < energyThroughput * Settings.get.tickFrequency)
- math.min(EnumFacing.VALUES.map(globalDemand).max, Power.toEU(energyThroughput))
- else 0
- }
-}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala
deleted file mode 100644
index f41d755fe8..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-/* TODO Mekanism
-
-import cpw.mods.fml.common.Optional
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.Power
-import net.minecraftforge.common.util.ForgeDirection
-
-@Injectable.Interface(value = "mekanism.api.energy.IStrictEnergyAcceptor", modid = Mods.IDs.Mekanism)
-trait Mekanism extends Common {
- @Optional.Method(modid = Mods.IDs.Mekanism)
- def canReceiveEnergy(side: ForgeDirection) = Mods.Mekanism.isAvailable && canConnectPower(side)
-
- @Optional.Method(modid = Mods.IDs.Mekanism)
- def transferEnergyToAcceptor(side: ForgeDirection, amount: Double) =
- if (!Mods.Mekanism.isAvailable) 0
- else Power.toJoules(tryChangeBuffer(side, Power.fromJoules(amount)))
-
- @Optional.Method(modid = Mods.IDs.Mekanism)
- def getMaxEnergy = Power.toJoules(ForgeDirection.VALID_DIRECTIONS.map(globalBufferSize).max)
-
- @Optional.Method(modid = Mods.IDs.Mekanism)
- def getEnergy = Power.toJoules(ForgeDirection.VALID_DIRECTIONS.map(globalBuffer).max)
-
- @Optional.Method(modid = Mods.IDs.Mekanism)
- def setEnergy(energy: Double) {}
-}
-*/
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/RotaryCraft.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/RotaryCraft.scala
deleted file mode 100644
index 576757427d..0000000000
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/RotaryCraft.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-package li.cil.oc.common.tileentity.traits.power
-/* TODO RotaryCraft
-import li.cil.oc.OpenComputers
-import li.cil.oc.Settings
-import li.cil.oc.common.asm.Injectable
-import li.cil.oc.integration.Mods
-import li.cil.oc.integration.util.Power
-import net.minecraft.util.EnumFacing
-import net.minecraftforge.fml.common.Optional
-
-@Injectable.Interface(value = "Reika.RotaryCraft.API.Power.ShaftPowerReceiver", modid = Mods.IDs.RotaryCraft)
-trait RotaryCraft extends Common {
- private lazy val useRotaryCraftPower = isServer && Mods.RotaryCraft.isAvailable
-
- private var omega = 0
- private var torque = 0
- private var power = 0L
- private var alpha = 0
-
- // ----------------------------------------------------------------------- //
-
- override def updateEntity() {
- if (useRotaryCraftPower) updateEnergy()
- super.updateEntity()
- }
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- private def updateEnergy() {
- if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
- tryAllSides((demand, _) => {
- val consumed = demand.toLong min power
- power -= consumed
- consumed
- }, Power.fromWA, Power.toWA)
- }
- }
-
- // ----------------------------------------------------------------------- //
- // ShaftMachine
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def getOmega: Int = omega
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def getTorque: Int = torque
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def getPower: Long = power
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def getName: String = OpenComputers.Name
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def getIORenderAlpha: Int = alpha
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def setIORenderAlpha(value: Int): Unit = alpha = value
-
- // ----------------------------------------------------------------------- //
- // ShaftPowerReceiver
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def setOmega(value: Int): Unit = omega = value
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def setTorque(value: Int): Unit = torque = value
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def setPower(value: Long): Unit = power = value
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def noInputMachine(): Unit = {
- omega = 0
- torque = 0
- power = 0
- }
-
- // ----------------------------------------------------------------------- //
- // PowerAcceptor
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def canReadFrom(forgeDirection: EnumFacing): Boolean = true
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def isReceiving: Boolean = true
-
- @Optional.Method(modid = Mods.IDs.RotaryCraft)
- def getMinTorque(available: Int): Int = 0
-}
-*/
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/integration/ModProxy.java b/src/main/scala/li/cil/oc/integration/ModProxy.java
index a33ed4bdc5..fed1dbd932 100644
--- a/src/main/scala/li/cil/oc/integration/ModProxy.java
+++ b/src/main/scala/li/cil/oc/integration/ModProxy.java
@@ -3,5 +3,11 @@
public interface ModProxy {
Mod getMod();
- void initialize();
+ default void preInitialize()
+ {
+ }
+
+ default void initialize()
+ {
+ }
}
diff --git a/src/main/scala/li/cil/oc/integration/Mods.scala b/src/main/scala/li/cil/oc/integration/Mods.scala
index d961d8d763..1c5c330ed9 100644
--- a/src/main/scala/li/cil/oc/integration/Mods.scala
+++ b/src/main/scala/li/cil/oc/integration/Mods.scala
@@ -1,17 +1,20 @@
package li.cil.oc.integration
+import java.util.Optional
+
import li.cil.oc.Settings
import li.cil.oc.integration
-import net.minecraftforge.fml.common.Loader
-import net.minecraftforge.fml.common.ModAPIManager
-import net.minecraftforge.fml.common.versioning.ArtifactVersion
-import net.minecraftforge.fml.common.versioning.VersionParser
+import net.minecraftforge.fml.ModList
+import net.minecraftforge.fml.ModContainer
+import net.minecraftforge.forgespi.language.MavenVersionAdapter
+import org.apache.maven.artifact.versioning.ArtifactVersion
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
object Mods {
- private val handlers = mutable.Set.empty[ModProxy]
+ private var preInited = false
+ private var inited = false
private val knownMods = mutable.ArrayBuffer.empty[ModBase]
@@ -20,57 +23,66 @@ object Mods {
def All: ArrayBuffer[ModBase] = knownMods.clone()
val AppliedEnergistics2 = new ClassBasedMod(IDs.AppliedEnergistics2, "appeng.api.storage.channels.IItemStorageChannel")
val ComputerCraft = new SimpleMod(IDs.ComputerCraft)
- val ExtraCells = new SimpleMod(IDs.ExtraCells, version = "@[2.5.2,)")
- val Forestry = new SimpleMod(IDs.Forestry, version = "@[5.2,)")
- val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2)
val Forge = new SimpleMod(IDs.Forge)
val JustEnoughItems = new SimpleMod(IDs.JustEnoughItems)
val Mekanism = new SimpleMod(IDs.Mekanism)
- val MekanismGas = new SimpleMod(IDs.MekanismGas)
val Minecraft = new SimpleMod(IDs.Minecraft)
val OpenComputers = new SimpleMod(IDs.OpenComputers)
- val TIS3D = new SimpleMod(IDs.TIS3D, version = "@[0.9,)")
- val Waila = new SimpleMod(IDs.Waila)
- val ProjectRedBase = new SimpleMod((IDs.ProjectRedCore))
+ val TIS3D = new SimpleMod(IDs.TIS3D, version = "[0.9,)")
val ProjectRedTransmission = new SimpleMod((IDs.ProjectRedTransmission))
val DraconicEvolution = new SimpleMod(IDs.DraconicEvolution)
val EnderStorage = new SimpleMod(IDs.EnderStorage)
- val Thaumcraft = new SimpleMod(IDs.Thaumcraft)
- val Charset = new SimpleMod(IDs.Charset)
- val WirelessRedstoneCBE = new SimpleMod(IDs.WirelessRedstoneCBE)
// ----------------------------------------------------------------------- //
val Proxies = Array(
integration.appeng.ModAppEng,
- integration.ec.ModExtraCells,
- integration.forestry.ModForestry,
- integration.ic2.ModIndustrialCraft2,
integration.minecraftforge.ModMinecraftForge,
integration.tis3d.ModTIS3D,
integration.mekanism.ModMekanism,
- integration.mekanism.gas.ModMekanismGas,
integration.minecraft.ModMinecraft,
- integration.waila.ModWaila,
integration.projectred.ModProjectRed,
integration.computercraft.ModComputerCraft,
integration.enderstorage.ModEnderStorage,
- integration.thaumcraft.ModThaumcraft,
- integration.charset.ModCharset,
- integration.wrcbe.ModWRCBE,
// We go late to ensure all other mod integration is done, e.g. to
// allow properly checking if wireless redstone is present.
integration.opencomputers.ModOpenComputers
)
+ def preInit(): Unit = {
+ if (!preInited) {
+ preInited = true
+ for (proxy <- Proxies) {
+ tryPreInit(proxy)
+ }
+ }
+ }
+
+ private def tryPreInit(mod: ModProxy) {
+ val handlers = mutable.Set.empty[ModProxy]
+ val isBlacklisted = Settings.get.modBlacklist.contains(mod.getMod.id)
+ val alwaysEnabled = mod.getMod == null || mod.getMod == Mods.Minecraft
+ if (!isBlacklisted && (alwaysEnabled || mod.getMod.isModAvailable) && handlers.add(mod)) {
+ li.cil.oc.OpenComputers.log.debug(s"Pre-initializing mod integration for '${mod.getMod.id}'.")
+ try mod.preInitialize() catch {
+ case e: Throwable =>
+ li.cil.oc.OpenComputers.log.warn(s"Error pre-initializing integration for '${mod.getMod.id}'", e)
+ }
+ }
+ }
+
def init(): Unit = {
- for (proxy <- Proxies) {
- tryInit(proxy)
+ if (!inited) {
+ inited = true
+ for (proxy <- Proxies) {
+ tryInit(proxy)
+ }
}
}
private def tryInit(mod: ModProxy) {
+ val handlers = mutable.Set.empty[ModProxy]
val isBlacklisted = Settings.get.modBlacklist.contains(mod.getMod.id)
val alwaysEnabled = mod.getMod == null || mod.getMod == Mods.Minecraft
if (!isBlacklisted && (alwaysEnabled || mod.getMod.isModAvailable) && handlers.add(mod)) {
@@ -87,28 +99,22 @@ object Mods {
object IDs {
final val AppliedEnergistics2 = "appliedenergistics2"
final val ComputerCraft = "computercraft"
- final val ExtraCells = "extracells"
- final val Forestry = "forestry"
final val Forge = "forge"
- final val IndustrialCraft2 = "ic2"
final val JustEnoughItems = "jei"
final val Mekanism = "mekanism"
- final val MekanismGas = "MekanismAPI|gas"
final val Minecraft = "minecraft"
final val OpenComputers = "opencomputers"
final val TIS3D = "tis3d"
final val Waila = "waila"
- final val ProjectRedCore = "projectred-core"
final val ProjectRedTransmission = "projectred-transmission"
final val DraconicEvolution = "draconicevolution"
final val EnderStorage = "enderstorage"
- final val Thaumcraft = "thaumcraft"
- final val Charset = "charset"
- final val WirelessRedstoneCBE = "wrcbe"
}
// ----------------------------------------------------------------------- //
+ private def optionToScala[T](opt: Optional[T]): Option[T] = if (opt.isPresent) Some(opt.get) else None
+
trait ModBase extends Mod {
knownMods += this
@@ -116,24 +122,22 @@ object Mods {
def id: String
- def container = Option(Loader.instance.getIndexedModList.get(id))
+ def container: Option[ModContainer] = optionToScala(ModList.get.getModContainerById(id))
- def version: Option[ArtifactVersion] = container.map(_.getProcessedVersion)
+ def version: Option[ArtifactVersion] = container.map(_.getModInfo.getVersion)
}
class SimpleMod(val id: String, version: String = "") extends ModBase {
- private lazy val isModAvailable_ = {
- val version = VersionParser.parseVersionReference(id + this.version)
- if (Loader.isModLoaded(version.getLabel))
- version.containsVersion(Loader.instance.getIndexedModList.get(version.getLabel).getProcessedVersion)
- else ModAPIManager.INSTANCE.hasAPI(version.getLabel)
+ private lazy val isModAvailable_ = optionToScala(ModList.get.getModContainerById(id)) match {
+ case Some(container) => version.isEmpty || MavenVersionAdapter.createFromVersionSpec(version).containsVersion(container.getModInfo.getVersion)
+ case _ => false
}
def isModAvailable: Boolean = isModAvailable_
}
class ClassBasedMod(val id: String, val classNames: String*) extends ModBase {
- private lazy val isModAvailable_ = Loader.isModLoaded(id) && classNames.forall(className => try Class.forName(className) != null catch {
+ private lazy val isModAvailable_ = ModList.get.isLoaded(id) && classNames.forall(className => try Class.forName(className) != null catch {
case _: Throwable => false
})
diff --git a/src/main/scala/li/cil/oc/integration/appeng/AEUtil.scala b/src/main/scala/li/cil/oc/integration/appeng/AEUtil.scala
index a912105dcf..9e4bea2e64 100644
--- a/src/main/scala/li/cil/oc/integration/appeng/AEUtil.scala
+++ b/src/main/scala/li/cil/oc/integration/appeng/AEUtil.scala
@@ -1,8 +1,9 @@
package li.cil.oc.integration.appeng
+import java.util.Optional
import javax.annotation.Nonnull
-import appeng.api.AEApi
+import appeng.api._
import appeng.api.networking.IGrid
import appeng.api.networking.crafting.ICraftingGrid
import appeng.api.networking.energy.IEnergyGrid
@@ -12,57 +13,61 @@ import appeng.api.storage.data.{IAEFluidStack, IAEItemStack}
import appeng.api.storage.IStorageHelper
import li.cil.oc.integration.Mods
import net.minecraft.item.ItemStack
-import net.minecraftforge.fml.common.versioning.VersionRange
-import net.minecraftforge.fml.common.Loader
+import net.minecraftforge.fml.ModList
+import net.minecraftforge.forgespi.language.MavenVersionAdapter
+import org.apache.maven.artifact.versioning.VersionRange
+
+@AEAddon
+class AEUtil extends IAEAddon {
+ override def onAPIAvailable(aeApi: IAppEngApi) = AEUtil.onAPIAvailable(aeApi)
+}
object AEUtil {
- val versionsWithNewItemDefinitionAPI: VersionRange = VersionRange.createFromVersionSpec("[rv6-stable-5,)")
+ var aeApi: Option[IAppEngApi] = None
- val itemStorageChannel: IItemStorageChannel = AEApi.instance.storage.getStorageChannel[IAEItemStack, IItemStorageChannel](classOf[IItemStorageChannel])
- val fluidStorageChannel: IFluidStorageChannel = AEApi.instance.storage.getStorageChannel[IAEFluidStack, IFluidStorageChannel](classOf[IFluidStorageChannel])
+ private def optionToScala[T](opt: Optional[T]): Option[T] = if (opt.isPresent) Some(opt.get) else None
+
+ private def onAPIAvailable(aeApi: IAppEngApi) {
+ AEUtil.aeApi = Some(aeApi)
+ itemStorageChannel = aeApi.storage.getStorageChannel[IAEItemStack, IItemStorageChannel](classOf[IItemStorageChannel])
+ fluidStorageChannel = aeApi.storage.getStorageChannel[IAEFluidStack, IFluidStorageChannel](classOf[IFluidStorageChannel])
+ }
- def useNewItemDefinitionAPI: Boolean = versionsWithNewItemDefinitionAPI.containsVersion(
- Loader.instance.getIndexedModList.get(Mods.AppliedEnergistics2.id).getProcessedVersion)
+ val versionsWithNewItemDefinitionAPI: VersionRange = MavenVersionAdapter.createFromVersionSpec("[rv6-stable-5,)")
+
+ var itemStorageChannel: IItemStorageChannel = null
+ var fluidStorageChannel: IFluidStorageChannel = null
+
+ def useNewItemDefinitionAPI: Boolean = optionToScala(ModList.get.getModContainerById(Mods.AppliedEnergistics2.id)).
+ filter(container => versionsWithNewItemDefinitionAPI.containsVersion(container.getModInfo.getVersion)).isDefined
// ----------------------------------------------------------------------- //
- def controllerClass: Class[_] = {
- if (AEApi.instance != null) {
- val maybe = AEApi.instance.definitions.blocks.controller.maybeEntity
- if (maybe.isPresent)
- maybe.get()
- else
- null: Class[_]
- }
- else null: Class[_]
- }
+ def controllerClass: Class[_] = aeApi.flatMap(api => optionToScala(api.definitions.blocks.controller.maybeEntity)).orNull
// ----------------------------------------------------------------------- //
- def interfaceClass: Class[_] =
- if (AEApi.instance != null)
- AEApi.instance.definitions.blocks.iface.maybeEntity.get()
- else null: Class[_]
+ def interfaceClass: Class[_] = aeApi.map(api => api.definitions.blocks.iface.maybeEntity.get).orNull
// ----------------------------------------------------------------------- //
- def isController(stack: ItemStack): Boolean = stack != null && AEApi.instance != null && AEApi.instance.definitions.blocks.controller.isSameAs(stack)
+ def isController(stack: ItemStack): Boolean = stack != null && aeApi.filter(_.definitions.blocks.controller.isSameAs(stack)).isDefined
// ----------------------------------------------------------------------- //
- def isExportBus(stack: ItemStack): Boolean = stack != null && AEApi.instance != null && AEApi.instance.definitions.parts.exportBus.isSameAs(stack)
+ def isExportBus(stack: ItemStack): Boolean = stack != null && aeApi.filter(_.definitions.parts.exportBus.isSameAs(stack)).isDefined
// ----------------------------------------------------------------------- //
- def isImportBus(stack: ItemStack): Boolean = stack != null && AEApi.instance != null && AEApi.instance.definitions.parts.importBus.isSameAs(stack)
+ def isImportBus(stack: ItemStack): Boolean = stack != null && aeApi.filter(_.definitions.parts.importBus.isSameAs(stack)).isDefined
// ----------------------------------------------------------------------- //
- def isBlockInterface(stack: ItemStack): Boolean = stack != null && AEApi.instance != null && AEApi.instance.definitions.blocks.iface.isSameAs(stack)
+ def isBlockInterface(stack: ItemStack): Boolean = stack != null && aeApi.filter(_.definitions.blocks.iface.isSameAs(stack)).isDefined
// ----------------------------------------------------------------------- //
- def isPartInterface(stack: ItemStack): Boolean = stack != null && AEApi.instance != null && AEApi.instance.definitions.parts.iface.isSameAs(stack)
+ def isPartInterface(stack: ItemStack): Boolean = stack != null && aeApi.filter(_.definitions.parts.iface.isSameAs(stack)).isDefined
// ----------------------------------------------------------------------- //
diff --git a/src/main/scala/li/cil/oc/integration/appeng/ConverterCellInventory.java b/src/main/scala/li/cil/oc/integration/appeng/ConverterCellInventory.java
index d3499f887e..c6abf036cb 100644
--- a/src/main/scala/li/cil/oc/integration/appeng/ConverterCellInventory.java
+++ b/src/main/scala/li/cil/oc/integration/appeng/ConverterCellInventory.java
@@ -1,10 +1,8 @@
package li.cil.oc.integration.appeng;
-import appeng.api.AEApi;
import appeng.api.implementations.items.IStorageCell;
-import appeng.api.storage.ICellInventory;
-import appeng.api.storage.ICellInventoryHandler;
-import appeng.api.storage.IMEInventoryHandler;
+import appeng.api.storage.cells.ICellInventory;
+import appeng.api.storage.cells.ICellInventoryHandler;
import appeng.api.storage.channels.IItemStorageChannel;
import li.cil.oc.api.driver.Converter;
import net.minecraft.item.ItemStack;
@@ -22,7 +20,7 @@ public void convert(final Object value, final Map