1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-22 17:37:38 +00:00

Compare commits

..

8 Commits

Author SHA1 Message Date
SquidDev
0f3c44c926 Merge branch 'master' into mc-1.13.x 2019-06-08 08:21:08 +01:00
SquidDev
a0e7c4a74c Add a little bit of source code checking to Gradle
- Adds a CheckStyle configuration which is pretty similar to CC's
   existing one.
 - Add the Gradle license plugin.
 - Ensure the existing source code is compatible with these additional
   checks.

See #239
2019-06-08 00:28:03 +01:00
Lignum
7d428030df Fix some warnings (#235)
Remove some unused code and fix a bunch of warnings
2019-06-07 14:35:17 +01:00
JakobDev
00c395f689 Add Check to delete.lua (#236) 2019-06-06 16:43:48 +01:00
SquidDev
d8e1c73d26 Ensure files cannot be closed multiple times
Also fix an NPE if we try to close them twice.

Fixes #230
2019-06-04 21:34:19 +01:00
SquidDev
ffa4cc241b Add a test utility for capturing program output
- Make mcfly's stubbing system a little more fault-tolerant.
 - Add a small utility function which redirects print, printError and
   write to capture their output, rather than printing to the terminal.
   This can then be matched against in order to determine a program's
   output.
   It's a little flakey - you can't use it multiple times in an it
   block, etc... but it's a nice feature.
 - Add a small couple of tests to delete as a proof-of-concept.
2019-06-03 20:33:09 +01:00
SquidDev
6f1b740c8f Un-localise paths in mount error messages
This is probably a little more complex than it needs to be, as we try to
handle the mounts as well (which generally don't error).

Fixes #229
2019-06-03 19:58:16 +01:00
SquidDev
3406ba3ebf Fix a build from a clean state failing 2019-06-02 18:48:36 +01:00
351 changed files with 6507 additions and 5783 deletions

6
.gitignore vendored
View File

@@ -15,3 +15,9 @@
.idea
.gradle
*.DS_Store
.classpath
.project
.settings/
bin/
*.launch

View File

@@ -1,17 +1,28 @@
buildscript {
repositories {
jcenter()
mavenCentral()
maven {
name = "forge"
url = "http://files.minecraftforge.net/maven"
}
}
dependencies {
classpath 'com.google.code.gson:gson:2.8.1'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.117'
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
}
}
plugins {
id 'fabric-loom' version '0.2.3-SNAPSHOT'
id 'com.matthewprenger.cursegradle' version '1.2.0'
id "checkstyle"
id "com.github.hierynomus.license" version "0.15.0"
id "com.matthewprenger.cursegradle" version "1.3.0"
id "com.github.breadmoirai.github-release" version "2.2.4"
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.ajoberstar.grgit'
apply plugin: 'maven-publish'
apply plugin: 'maven'
@@ -22,10 +33,38 @@ group = "org.squiddev"
archivesBaseName = "cc-tweaked-${mc_version}"
minecraft {
runs {
client {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
mods {
computercraft {
source sourceSets.main
}
}
}
server {
workingDirectory project.file('run')
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
property 'forge.logging.console.level', 'debug'
mods {
computercraft {
source sourceSets.main
}
}
}
}
mappings channel: 'snapshot', version: "${mappings_version}".toString()
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
}
repositories {
mavenCentral()
maven {
name "JEI"
url "http://dvs1.progwml6.com/files/maven"
@@ -51,15 +90,17 @@ configurations {
}
dependencies {
minecraft "com.mojang:minecraft:${mc_version}"
mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}"
modCompile "net.fabricmc:fabric-loader:0.4.8+build.153"
modCompile "net.fabricmc.fabric-api:fabric-api:0.3.0+build.175"
checkstyle "com.puppycrawl.tools:checkstyle:8.21"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
compileOnly fg.deobf("mezz.jei:jei-1.13.2:5.0.0.20:api")
// deobfProvided "pl.asie:Charset-Lib:0.5.4.6"
// deobfProvided "MCMultiPart2:MCMultiPart:2.5.3"
runtimeOnly fg.deobf("mezz.jei:jei-1.13.2:5.0.0.20")
shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT'
shade 'javax.vecmath:vecmath:1.5.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.0'
@@ -70,7 +111,8 @@ dependencies {
sourceSets {
main {
java {
exclude 'dan200/computercraft/shared/integration'
exclude 'dan200/computercraft/shared/integration/mcmp'
exclude 'dan200/computercraft/shared/integration/charset'
}
}
}
@@ -105,6 +147,8 @@ import java.util.zip.*
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import com.hierynomus.gradle.license.tasks.LicenseCheck
import com.hierynomus.gradle.license.tasks.LicenseFormat
import org.ajoberstar.grgit.Grgit
import proguard.gradle.ProGuardTask
@@ -112,11 +156,8 @@ task proguard(type: ProGuardTask, dependsOn: jar) {
description "Removes unused shadowed classes from the jar"
group "compact"
afterEvaluate {
// Fabric changes the jar's classifier so we to do this after evaluating!
injars jar.archivePath
outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"
}
injars jar.archivePath
outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"
// Add the main runtime jar and all non-shadowed dependencies
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
@@ -140,7 +181,7 @@ task proguard(type: ProGuardTask, dependsOn: jar) {
// LWJGL and Apache bundle Java 9 versions, which is great, but rather breaks Proguard
dontwarn 'module-info'
dontwarn 'org.apache.**,org.lwjgl.**,javax.crypto.SecretKey'
dontwarn 'org.apache.**,org.lwjgl.**'
}
task proguardMove(dependsOn: proguard) {
@@ -156,7 +197,7 @@ task proguardMove(dependsOn: proguard) {
}
}
remapJar.dependsOn proguardMove
processResources {
inputs.property "version", mod_version
@@ -178,7 +219,7 @@ processResources {
inputs.property "commithash", hash
from(sourceSets.main.resources.srcDirs) {
include 'fabric.mod.json'
include 'META-INF/mods.toml'
include 'data/computercraft/lua/rom/help/credits.txt'
expand 'version': mod_version,
@@ -187,12 +228,12 @@ processResources {
}
from(sourceSets.main.resources.srcDirs) {
exclude 'fabric.mod.json'
exclude 'META-INF/mods.toml'
exclude 'data/computercraft/lua/rom/help/credits.txt'
}
}
task compressJson(dependsOn: remapJar) {
task compressJson(dependsOn: jar) {
group "compact"
description "Minifies all JSON files, stripping whitespace"
@@ -207,6 +248,7 @@ task compressJson(dependsOn: remapJar) {
// Copy over all files in the current jar to the new one, running json files from GSON. As pretty printing
// is turned off, they should be minified.
new ZipFile(jarPath).withCloseable { inJar ->
tempPath.getParentFile().mkdirs()
new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(tempPath))).withCloseable { outJar ->
inJar.entries().each { entry ->
if(entry.directory) {
@@ -234,6 +276,42 @@ task compressJson(dependsOn: remapJar) {
assemble.dependsOn compressJson
/* Check tasks */
license {
mapping("java", "SLASHSTAR_STYLE")
strictCheck true
ext.year = Calendar.getInstance().get(Calendar.YEAR)
}
[licenseMain, licenseFormatMain].forEach {
it.configure {
include("**/*.java")
exclude("dan200/computercraft/api/**")
header rootProject.file('config/license/main.txt')
}
}
[licenseTest, licenseFormatTest].forEach {
it.configure {
include("**/*.java")
header rootProject.file('config/license/main.txt')
}
}
task licenseAPI(type: LicenseCheck);
task licenseFormatAPI(type: LicenseFormat);
[licenseAPI, licenseFormatAPI].forEach {
it.configure {
source = sourceSets.main.java
include("dan200/computercraft/api/**")
header rootProject.file('config/license/api.txt')
}
}
/* Upload tasks */
task checkRelease {
group "upload"
description "Verifies that everything is ready for a release"
@@ -273,27 +351,16 @@ task checkRelease {
}
}
curseforge {
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
project {
id = '282001'
addGameVersion '1.14.2'
releaseType = 'beta'
releaseType = 'release'
changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
relations {
incompatible "computercraft"
requiredDependency "fabric"
}
afterEvaluate {
mainArtifact(remapJar.output)
uploadTask.dependsOn(remapJar)
}
}
options {
forgeGradleIntegration = false
}
}
@@ -370,7 +437,7 @@ githubRelease {
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease }
task uploadAll(dependsOn: [remapJar] + uploadTasks) {
task uploadAll(dependsOn: uploadTasks) {
group "upload"
description "Uploads to all repositories (Maven, Curse, GitHub release)"
}
@@ -383,8 +450,14 @@ test {
}
gradle.projectsEvaluated {
reobfJar.dependsOn proguardMove
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint" << "-Xlint:-processing" // Causes Forge build to fail << "-Werror"
}
tasks.withType(LicenseFormat) {
outputs.upToDateWhen { false }
}
}

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="tabWidth" value="4"/>
<property name="charset" value="UTF-8" />
<module name="SuppressionFilter">
<property name="file" value="config/checkstyle/suppressions.xml" />
</module>
<module name="TreeWalker">
<!-- Annotations -->
<module name="AnnotationLocation" />
<module name="AnnotationUseStyle" />
<module name="MissingDeprecated">
<property name="skipNoJavadoc" value="true" />
</module>
<module name="MissingOverride" />
<!-- Blocks -->
<module name="EmptyBlock" />
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="ignored" />
</module>
<module name="LeftCurly">
<property name="option" value="nl" />
<!-- The defaults, minus lambdas. -->
<property name="tokens" value="ANNOTATION_DEF,CLASS_DEF,CTOR_DEF,ENUM_CONSTANT_DEF,ENUM_DEF,INTERFACE_DEF,LITERAL_CASE,LITERAL_CATCH,LITERAL_DEFAULT,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,METHOD_DEF,OBJBLOCK,STATIC_INIT" />
</module>
<module name="NeedBraces">
<property name="allowSingleLineStatement" value="true"/>
</module>
<module name="RightCurly">
<property name="option" value="alone" />
</module>
<!-- Class design. As if we've ever followed good practice here. -->
<module name="FinalClass" />
<module name="InterfaceIsType" />
<module name="MutableException" />
<module name="OneTopLevelClass" />
<!-- Coding -->
<module name="ArrayTrailingComma" />
<module name="EqualsHashCode" />
<!-- FallThrough does not handle unreachable code well -->
<module name="IllegalInstantiation" />
<module name="IllegalThrows" />
<module name="ModifiedControlVariable" />
<module name="NoClone" />
<module name="NoFinalizer" />
<module name="OneStatementPerLine" />
<module name="PackageDeclaration" />
<module name="SimplifyBooleanExpression" />
<module name="SimplifyBooleanReturn" />
<module name="StringLiteralEquality" />
<module name="UnnecessaryParentheses" />
<!-- Imports -->
<module name="CustomImportOrder" />
<module name="IllegalImport" />
<module name="RedundantImport" />
<module name="UnusedImports" />
<!-- Javadoc -->
<module name="AtclauseOrder" />
<!-- TODO: Cleanup our documentation before enabling JavadocMethod, JavadocStyle, JavadocType and SummaryJavadoc. -->
<module name="NonEmptyAtclauseDescription" />
<module name="SingleLineJavadoc" />
<!-- Misc -->
<module name="ArrayTypeStyle" />
<module name="CommentsIndentation" />
<module name="Indentation" />
<module name="OuterTypeFilename" />
<!-- Modifiers -->
<module name="ModifierOrder" />
<module name="RedundantModifier" />
<!-- Naming -->
<module name="ClassTypeParameterName" />
<module name="InterfaceTypeParameterName" />
<module name="LambdaParameterName" />
<module name="LocalFinalVariableName" />
<module name="LocalVariableName" />
<!-- Allow an optional m_ on private members -->
<module name="MemberName">
<property name="applyToPrivate" value="false" />
<property name="applyToPackage" value="false" />
</module>
<module name="MemberName">
<property name="format" value="^(m_)?[a-z][a-zA-Z0-9]*$" />
<property name="applyToPrivate" value="true" />
<property name="applyToPackage" value="true" />
</module>
<module name="MethodName" />
<module name="MethodTypeParameterName" />
<module name="PackageName">
<property name="format" value="^dan200\.computercraf(\.[a-z][a-z0-9]*)*" />
</module>
<module name="ParameterName" />
<module name="StaticVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z]+)?$" />
<property name="applyToPrivate" value="false" />
</module>
<module name="StaticVariableName">
<property name="format" value="^(s_)?[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z]+)?$" />
<property name="applyToPrivate" value="true" />
</module>
<module name="TypeName" />
<!-- Whitespace -->
<module name="EmptyForInitializerPad"/>
<module name="EmptyForIteratorPad">
<property name="option" value="space"/>
</module>
<module name="GenericWhitespace" />
<module name="MethodParamPad" />
<module name="NoLineWrap" />
<module name="NoWhitespaceAfter">
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP" />
</module>
<module name="NoWhitespaceBefore" />
<!-- TODO: Decide on an OperatorWrap style. -->
<module name="ParenPad">
<property name="option" value="space" />
<property name="tokens" value="ANNOTATION,ANNOTATION_FIELD_DEF,CTOR_CALL,CTOR_DEF,ENUM_CONSTANT_DEF,LITERAL_CATCH,LITERAL_DO,LITERAL_FOR,LITERAL_IF,LITERAL_NEW,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_WHILE,METHOD_CALL,METHOD_DEF,RESOURCE_SPECIFICATION,SUPER_CTOR_CALL,LAMBDA" />
</module>
<module name="ParenPad">
<property name="option" value="nospace" />
<property name="tokens" value="DOT,EXPR,QUESTION" />
</module>
<module name="SeparatorWrap">
<property name="option" value="eol" />
<property name="tokens" value="COMMA,SEMI,ELLIPSIS,ARRAY_DECLARATOR,RBRACK,METHOD_REF" />
</module>
<module name="SeparatorWrap">
<property name="option" value="nl" />
<property name="tokens" value="DOT,AT" />
</module>
<module name="SingleSpaceSeparator" />
<module name="TypecastParenPad" />
<module name="WhitespaceAfter">
<property name="tokens" value="COMMA" />
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true" />
<property name="ignoreEnhancedForColon" value="false" />
<property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,DO_WHILE,EQUAL,GE,GT,LAMBDA,LAND,LCURLY,LE,LITERAL_RETURN,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND" />
</module>
</module>
<module name="FileTabCharacter" />
<module name="NewlineAtEndOfFile" />
</module>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<!-- Has a public m_label field. We need to check if this is used in other projects before renaming it. -->
<suppress checks="MemberName" files=".*[\\/]TileComputerBase.java"
message="Name 'm_label' must match pattern .*" />
<!-- All the config options and method fields. -->
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraft.java" />
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraftAPI.java" />
</suppressions>

3
config/license/api.txt Normal file
View File

@@ -0,0 +1,3 @@
This file is part of the public ComputerCraft API - http://www.computercraft.info
Copyright Daniel Ratcliffe, 2011-${year}. This API may be redistributed unmodified and in full only.
For help using the API, and posting your mods, visit the forums at computercraft.info.

3
config/license/main.txt Normal file
View File

@@ -0,0 +1,3 @@
This file is part of ComputerCraft - http://www.computercraft.info
Copyright Daniel Ratcliffe, 2011-${year}. Do not distribute without permission.
Send enquiries to dratcliffe@gmail.com

View File

@@ -2,5 +2,6 @@
mod_version=1.83.1
# Minecraft properties
mc_version=1.14.2
mappings_version=2
mc_version=1.13.2
forge_version=25.0.219
mappings_version=20190530-1.13.2

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,12 +1 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
rootProject.name = "cc-tweaked-${mc_version}-fabric"
rootProject.name = "cc-tweaked-${mc_version}"

View File

@@ -8,10 +8,10 @@ package dan200.computercraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.client.proxy.ComputerCraftProxyClient;
import dan200.computercraft.core.apis.AddressPredicate;
import dan200.computercraft.core.apis.http.websocket.Websocket;
import dan200.computercraft.core.filesystem.ResourceMount;
import dan200.computercraft.shared.Config;
import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
@@ -30,15 +30,13 @@ import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.turtle.upgrades.*;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.resource.ReloadableResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -47,7 +45,8 @@ import java.io.InputStream;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
public final class ComputerCraft implements ModInitializer
@Mod( ComputerCraft.MOD_ID )
public final class ComputerCraft
{
public static final String MOD_ID = "computercraft";
@@ -185,22 +184,9 @@ public final class ComputerCraft implements ModInitializer
// Logging
public static final Logger log = LogManager.getLogger( MOD_ID );
// Implementation
public static ComputerCraft instance;
public ComputerCraft()
{
instance = this;
}
@Override
public void onInitialize()
{
ComputerCraftProxyCommon.setup();
if( FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT )
{
ComputerCraftProxyClient.setup();
}
Config.load();
}
public static String getVersion()
@@ -210,17 +196,17 @@ public final class ComputerCraft implements ModInitializer
static IMount createResourceMount( String domain, String subPath )
{
ReloadableResourceManager manager = ComputerCraftProxyCommon.getServer().getDataManager();
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
ResourceMount mount = new ResourceMount( domain, subPath, manager );
return mount.exists( "" ) ? mount : null;
}
public static InputStream getResourceFile( String domain, String subPath )
{
ReloadableResourceManager manager = ComputerCraftProxyCommon.getServer().getDataManager();
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
try
{
return manager.getResource( new Identifier( domain, subPath ) ).getInputStream();
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
}
catch( IOException ignored )
{

View File

@@ -21,19 +21,18 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.core.apis.ApiFactories;
import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.shared.*;
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import dan200.computercraft.shared.wired.WiredNode;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
@@ -54,7 +53,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
@Override
public int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath )
{
return IDAssigner.getNextId( world, parentSubPath );
return IDAssigner.getNextId( parentSubPath );
}
@Override
@@ -62,7 +61,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
try
{
return new FileMount( new File( IDAssigner.getDir( world ), subPath ), capacity );
return new FileMount( new File( IDAssigner.getDir(), subPath ), capacity );
}
catch( Exception e )
{
@@ -95,7 +94,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
}
@Override
public int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
public int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
return BundledRedstone.getDefaultOutput( world, pos, side );
}
@@ -132,19 +131,11 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
return new WiredNode( element );
}
@Nullable
@Nonnull
@Override
public IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side )
public LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
BlockEntity tile = world.getBlockEntity( pos );
if( tile instanceof TileCable )
{
return ((TileCable) tile).getElement( side );
}
else if( tile instanceof TileWiredModemFull )
{
return ((TileWiredModemFull) tile).getElement();
}
return null;
TileEntity tile = world.getTileEntity( pos );
return tile == null ? LazyOptional.empty() : tile.getCapability( CapabilityWiredElement.CAPABILITY, side );
}
}

View File

@@ -1,17 +1,16 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleUpgradeType;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.SystemUtil;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
@@ -22,12 +21,12 @@ import javax.annotation.Nonnull;
*/
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
{
private final Identifier id;
private final ResourceLocation id;
private final TurtleUpgradeType type;
private final String adjective;
private final ItemStack stack;
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
{
this.id = id;
this.type = type;
@@ -35,24 +34,24 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
this.stack = stack;
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, IItemProvider item )
{
this( id, type, adjective, new ItemStack( item ) );
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
{
this( id, type, SystemUtil.createTranslationKey( "upgrade", id ) + ".adjective", stack );
this( id, type, Util.makeTranslationKey( "upgrade", id ) + ".adjective", stack );
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, IItemProvider item )
{
this( id, type, new ItemStack( item ) );
}
@Nonnull
@Override
public final Identifier getUpgradeID()
public final ResourceLocation getUpgradeID()
{
return id;
}

View File

@@ -20,10 +20,11 @@ import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -182,7 +183,7 @@ public final class ComputerCraftAPI
* If there is no block capable of emitting bundled redstone at the location, -1 will be returned.
* @see IBundledRedstoneProvider
*/
public static int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
public static int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
return getInstance().getBundledRedstoneOutput( world, pos, side );
}
@@ -240,8 +241,8 @@ public final class ComputerCraftAPI
* @return The element's node
* @see IWiredElement#getNode()
*/
@Nullable
public static IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side )
@Nonnull
public static LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
return getInstance().getWiredElementAt( world, pos, side );
}
@@ -283,7 +284,7 @@ public final class ComputerCraftAPI
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side );
void registerMediaProvider( @Nonnull IMediaProvider provider );
@@ -297,7 +298,7 @@ public final class ComputerCraftAPI
@Nonnull
IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element );
@Nullable
IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side );
@Nonnull
LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull EnumFacing side );
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.filesystem;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Objects;
/**
* An {@link IOException} which occurred on a specific file.
*
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
*/
public class FileOperationException extends IOException
{
private static final long serialVersionUID = -8809108200853029849L;
private final String filename;
public FileOperationException( @Nullable String filename, @Nonnull String message )
{
super( Objects.requireNonNull( message, "message cannot be null" ) );
this.filename = filename;
}
public FileOperationException( String message )
{
super( Objects.requireNonNull( message, "message cannot be null" ) );
this.filename = null;
}
@Nullable
public String getFilename()
{
return filename;
}
}

View File

@@ -90,7 +90,6 @@ public interface IMount
* @throws IOException If the file does not exist, or could not be opened.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForRead( path ) );

View File

@@ -67,7 +67,6 @@ public interface IWritableMount extends IMount
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForWrite( path ) );
@@ -94,7 +93,6 @@ public interface IWritableMount extends IMount
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForAppend( path ) );

View File

@@ -9,7 +9,7 @@ package dan200.computercraft.api.media;
import dan200.computercraft.api.filesystem.IMount;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.World;
import javax.annotation.Nonnull;

View File

@@ -6,9 +6,9 @@
package dan200.computercraft.api.peripheral;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -17,8 +17,7 @@ import javax.annotation.Nullable;
/**
* This interface is used to create peripheral implementations for blocks.
*
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively implement
* {@link IPeripheralTile}.
* If you have a {@link TileEntity} which acts as a peripheral, you may alternatively implement {@link IPeripheralTile}.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@@ -35,5 +34,5 @@ public interface IPeripheralProvider
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@Nullable
IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side );
}

View File

@@ -5,15 +5,15 @@
*/
package dan200.computercraft.api.peripheral;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A {@link net.minecraft.block.entity.BlockEntity} which may act as a peripheral.
* A {@link net.minecraft.tileentity.TileEntity} which may act as a peripheral.
*
* If you need more complex capabilities (such as handling TEs not belonging to your mod), you should use
* {@link IPeripheralProvider}.
@@ -25,8 +25,8 @@ public interface IPeripheralTile
*
* @param side The side to get the peripheral from.
* @return A peripheral, or {@code null} if there is not a peripheral here.
* @see IPeripheralProvider#getPeripheral(World, BlockPos, Direction)
* @see IPeripheralProvider#getPeripheral(World, BlockPos, EnumFacing)
*/
@Nullable
IPeripheral getPeripheral( @Nonnull Direction side );
IPeripheral getPeripheral( @Nonnull EnumFacing side );
}

View File

@@ -1,9 +1,8 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;

View File

@@ -1,15 +1,14 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.pocket;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.SystemUtil;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
@@ -20,30 +19,30 @@ import javax.annotation.Nonnull;
*/
public abstract class AbstractPocketUpgrade implements IPocketUpgrade
{
private final Identifier id;
private final ResourceLocation id;
private final String adjective;
private final ItemStack stack;
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemStack stack )
{
this.id = id;
this.adjective = adjective;
this.stack = stack;
}
protected AbstractPocketUpgrade( Identifier identifier, String adjective, ItemConvertible item )
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, IItemProvider item )
{
this( identifier, adjective, new ItemStack( item ) );
this( id, adjective, new ItemStack( item ) );
}
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
protected AbstractPocketUpgrade( ResourceLocation id, IItemProvider item )
{
this( id, SystemUtil.createTranslationKey( "upgrade", id ) + ".adjective", new ItemStack( item ) );
this( id, Util.makeTranslationKey( "upgrade", id ) + ".adjective", new ItemStack( item ) );
}
@Nonnull
@Override
public final Identifier getUpgradeID()
public final ResourceLocation getUpgradeID()
{
return id;
}

View File

@@ -8,8 +8,8 @@ package dan200.computercraft.api.pocket;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -75,7 +75,7 @@ public interface IPocketAccess
* @see #updateUpgradeNBTData()
*/
@Nonnull
CompoundTag getUpgradeNBTData();
NBTTagCompound getUpgradeNBTData();
/**
* Mark the upgrade-specific NBT as dirty.
@@ -95,5 +95,5 @@ public interface IPocketAccess
* @return A collection of all upgrade names.
*/
@Nonnull
Map<Identifier, IPeripheral> getUpgrades();
Map<ResourceLocation, IPeripheral> getUpgrades();
}

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -36,7 +36,7 @@ public interface IPocketUpgrade
* @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade)
*/
@Nonnull
Identifier getUpgradeID();
ResourceLocation getUpgradeID();
/**
* Return an unlocalised string to describe the type of pocket computer this upgrade provides.

View File

@@ -6,8 +6,8 @@
package dan200.computercraft.api.redstone;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -30,5 +30,5 @@ public interface IBundledRedstoneProvider
* handle this block.
* @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider)
*/
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side );
}

View File

@@ -10,12 +10,13 @@ import com.mojang.authlib.GameProfile;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.inventory.Inventory;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -82,10 +83,10 @@ public interface ITurtleAccess
* Returns the world direction the turtle is currently facing.
*
* @return The world direction the turtle is currently facing.
* @see #setDirection(Direction)
* @see #setDirection(EnumFacing)
*/
@Nonnull
Direction getDirection();
EnumFacing getDirection();
/**
* Set the direction the turtle is facing. Note that this will not play a rotation animation, you will also need to
@@ -94,7 +95,7 @@ public interface ITurtleAccess
* @param dir The new direction to set. This should be on either the x or z axis (so north, south, east or west).
* @see #getDirection()
*/
void setDirection( @Nonnull Direction dir );
void setDirection( @Nonnull EnumFacing dir );
/**
* Get the currently selected slot in the turtle's inventory.
@@ -146,9 +147,21 @@ public interface ITurtleAccess
* Get the inventory of this turtle
*
* @return This turtle's inventory
* @see #getItemHandler()
*/
@Nonnull
Inventory getInventory();
IInventory getInventory();
/**
* Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
*
* @return This turtle's inventory
* @see #getInventory()
* @see IItemHandlerModifiable
* @see net.minecraftforge.items.CapabilityItemHandler#ITEM_HANDLER_CAPABILITY
*/
@Nonnull
IItemHandlerModifiable getItemHandler();
/**
* Determine whether this turtle will require fuel when performing actions.
@@ -277,7 +290,7 @@ public interface ITurtleAccess
* @see #updateUpgradeNBTData(TurtleSide)
*/
@Nonnull
CompoundTag getUpgradeNBTData( @Nullable TurtleSide side );
NBTTagCompound getUpgradeNBTData( @Nullable TurtleSide side );
/**
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the

View File

@@ -10,13 +10,15 @@ import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.world.BlockEvent;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
@@ -40,7 +42,7 @@ public interface ITurtleUpgrade
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
@Nonnull
Identifier getUpgradeID();
ResourceLocation getUpgradeID();
/**
* Return an unlocalised string to describe this type of turtle in turtle item names.
@@ -96,8 +98,8 @@ public interface ITurtleUpgrade
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
* by the turtle, and the tool is required to do some work.
*
* Conforming implementations should fire {@code BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
* {@code AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
* Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
* {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
*
* @param turtle Access to the turtle that the tool resides on.
* @param side Which side of the turtle (left or right) the tool resides on.
@@ -111,7 +113,7 @@ public interface ITurtleUpgrade
* to be called.
*/
@Nonnull
default TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction )
default TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull EnumFacing direction )
{
return TurtleCommandResult.failure();
}
@@ -119,8 +121,8 @@ public interface ITurtleUpgrade
/**
* Called to obtain the model to be used when rendering a turtle peripheral.
*
* This can be obtained from {@link net.minecraft.client.render.item.ItemModels#getModel(ItemStack)},
* {@link net.minecraft.client.render.model.BakedModelManager#getModel(ModelIdentifier)} or any other
* This can be obtained from {@link net.minecraft.client.renderer.ItemModelMesher#getItemModel(ItemStack)},
* {@link net.minecraft.client.renderer.model.ModelManager#getModel(ModelResourceLocation)} or any other
* source.
*
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models!
@@ -129,8 +131,8 @@ public interface ITurtleUpgrade
* a transformation of {@code null} has the same effect as the identify matrix.
*/
@Nonnull
@Environment( EnvType.CLIENT )
Pair<BakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
@OnlyIn( Dist.CLIENT )
Pair<IBakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
/**
* Called once per tick for each turtle which has the upgrade equipped.

View File

@@ -6,7 +6,7 @@
package dan200.computercraft.api.turtle;
import net.minecraft.util.math.Direction;
import net.minecraft.util.EnumFacing;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -15,7 +15,7 @@ import javax.annotation.Nullable;
* Used to indicate the result of executing a turtle command.
*
* @see ITurtleCommand#execute(ITurtleAccess)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)
*/
public final class TurtleCommandResult
{

View File

@@ -6,14 +6,14 @@
package dan200.computercraft.api.turtle;
import net.minecraft.util.math.Direction;
import net.minecraft.util.EnumFacing;
/**
* An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by
* a turtle.
*
* @see ITurtleUpgrade#getType()
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)
*/
public enum TurtleVerb
{

View File

@@ -1,286 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle.event;
import com.mojang.authlib.GameProfile;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.command.arguments.EntityAnchorArgumentType;
import net.minecraft.container.Container;
import net.minecraft.container.NameableContainerProvider;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.passive.HorseBaseEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.NetworkState;
import net.minecraft.network.Packet;
import net.minecraft.network.chat.ChatMessageType;
import net.minecraft.network.chat.Component;
import net.minecraft.recipe.Recipe;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.network.packet.RequestCommandCompletionsC2SPacket;
import net.minecraft.server.network.packet.VehicleMoveC2SPacket;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Hand;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.TraderOfferList;
import net.minecraft.world.GameMode;
import net.minecraft.world.dimension.DimensionType;
import javax.annotation.Nullable;
import javax.crypto.SecretKey;
import java.util.Collection;
import java.util.OptionalInt;
/**
* A wrapper for {@link ServerPlayerEntity} which denotes a "fake" player.
*
* Please note that this does not implement any of the traditional fake player behaviour. It simply exists to prevent
* me passing in normal players.
*/
public class FakePlayer extends ServerPlayerEntity
{
public FakePlayer( ServerWorld world, GameProfile gameProfile )
{
super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) );
networkHandler = new FakeNetHandler( this );
}
// region Direct networkHandler access
@Override
public void method_6000() { }
@Override
public void method_6044() { }
@Override
public void tick() { }
@Override
public void method_14226() { }
@Override
public void onDeath( DamageSource damage ) { }
@Nullable
@Override
public Entity changeDimension( DimensionType dimension )
{
return this;
}
@Override
public void wakeUp( boolean resetTimer, boolean notify, boolean setSpawn ) { }
@Override
public boolean startRiding( Entity entity, boolean flag )
{
return false;
}
@Override
public void stopRiding() { }
@Override
public void openEditSignScreen( SignBlockEntity tile ) { }
@Override
public OptionalInt openContainer( @Nullable NameableContainerProvider container )
{
return OptionalInt.empty();
}
@Override
public void sendTradeOffers( int id, TraderOfferList list, int level, int experience, boolean levelled ) { }
@Override
public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) { }
@Override
public void openEditBookScreen( ItemStack stack, Hand hand ) { }
@Override
public void openCommandBlockScreen( CommandBlockBlockEntity block ) { }
@Override
public void onContainerSlotUpdate( Container container, int slot, ItemStack stack ) { }
@Override
public void onContainerRegistered( Container container, DefaultedList<ItemStack> defaultedList ) { }
@Override
public void onContainerPropertyUpdate( Container container, int key, int value ) { }
@Override
public void closeContainer() { }
@Override
public void method_14241() { }
@Override
public void addChatMessage( Component textComponent, boolean status ) { }
@Override
protected void method_6040() { }
@Override
public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) { }
@Override
public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) { }
@Override
protected void method_6020( StatusEffectInstance statusEffectInstance ) { }
@Override
protected void method_6009( StatusEffectInstance statusEffectInstance, boolean particles ) { }
@Override
protected void method_6129( StatusEffectInstance statusEffectInstance ) { }
@Override
public void requestTeleport( double x, double y, double z ) { }
@Override
public void setGameMode( GameMode gameMode ) { }
@Override
public void sendChatMessage( Component textComponent, ChatMessageType chatMessageType ) { }
@Override
public String getServerBrand()
{
return "[Fake Player]";
}
@Override
public void method_14255( String url, String hash ) { }
@Override
public void onStoppedTracking( Entity entity ) { }
@Override
public void setCameraEntity( Entity entity ) { }
@Override
public void teleport( ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw ) { }
@Override
public void sendInitialChunkPackets( ChunkPos chunkPos, Packet<?> packet, Packet<?> packet2 ) { }
@Override
public void sendUnloadChunkPacket( ChunkPos chunkPos ) { }
@Override
public void playSound( SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch ) { }
// endregion
// Indirect
@Override
public int lockRecipes( Collection<Recipe<?>> recipes )
{
return 0;
}
@Override
public int unlockRecipes( Collection<Recipe<?>> recipes )
{
return 0;
}
//
private static class FakeNetHandler extends ServerPlayNetworkHandler
{
FakeNetHandler( ServerPlayerEntity player )
{
super( player.server, new FakeConnection(), player );
}
@Override
public void disconnect( Component message ) { }
@Override
public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) { }
@Override
public void sendPacket( Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener ) { }
@Override
public void onVehicleMove( VehicleMoveC2SPacket move ) { }
}
private static class FakeConnection extends ClientConnection
{
FakeConnection()
{
super( NetworkSide.CLIENTBOUND );
}
@Override
public void channelActive( ChannelHandlerContext active )
{
}
@Override
public void setState( NetworkState state )
{
}
@Override
public void disconnect( Component message )
{
}
@Override
public void exceptionCaught( ChannelHandlerContext context, Throwable err )
{
}
@Override
protected void method_10770( ChannelHandlerContext context, Packet<?> packet )
{
}
@Override
public void tick()
{
}
@Override
public void setupEncryption( SecretKey key )
{
}
@Override
public void disableAutoRead()
{
}
@Override
public void setMinCompressedSize( int size )
{
}
@Override
public void send( Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener )
{
}
}
}

View File

@@ -8,6 +8,7 @@ package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import net.minecraftforge.eventbus.api.Cancelable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -16,11 +17,11 @@ import java.util.Objects;
/**
* An event fired when a turtle is performing a known action.
*/
@Cancelable
public class TurtleActionEvent extends TurtleEvent
{
private final TurtleAction action;
private String failureMessage;
private boolean cancelled = false;
public TurtleActionEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action )
{
@@ -44,6 +45,7 @@ public class TurtleActionEvent extends TurtleEvent
* @see TurtleCommandResult#failure()
* @deprecated Use {@link #setCanceled(boolean, String)} instead.
*/
@Override
@Deprecated
public void setCanceled( boolean cancel )
{
@@ -61,7 +63,7 @@ public class TurtleActionEvent extends TurtleEvent
*/
public void setCanceled( boolean cancel, @Nullable String failureMessage )
{
this.cancelled = true;
super.setCanceled( cancel );
this.failureMessage = cancel ? failureMessage : null;
}
@@ -77,15 +79,4 @@ public class TurtleActionEvent extends TurtleEvent
{
return failureMessage;
}
/**
* Determine if this event is cancelled
*
* @return If this event is cancelled
* @see #setCanceled(boolean, String)
*/
public boolean isCancelled()
{
return cancelled;
}
}

View File

@@ -11,7 +11,9 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Direction;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import javax.annotation.Nonnull;
import java.util.Objects;
@@ -19,11 +21,10 @@ import java.util.Objects;
/**
* Fired when a turtle attempts to attack an entity.
*
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)},
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)},
* as the base {@code turtle.attack()} command does not fire it.
*
* Note that such commands should also fire {@link net.fabricmc.fabric.api.event.player.AttackEntityCallback}, so you do
* not need to listen to both.
* Note that such commands should also fire {@link AttackEntityEvent}, so you do not need to listen to both.
*
* @see TurtleAction#ATTACK
*/

View File

@@ -12,11 +12,13 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.world.BlockEvent;
import javax.annotation.Nonnull;
import java.util.Map;
@@ -73,21 +75,20 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
/**
* Fired when a turtle attempts to dig a block.
*
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)},
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)},
* as the base {@code turtle.dig()} command does not fire it.
*
* Note that such commands should also fire {@link net.fabricmc.fabric.api.event.player.AttackBlockCallback}, so you
* do not need to listen to both.
* Note that such commands should also fire {@link BlockEvent.BreakEvent}, so you do not need to listen to both.
*
* @see TurtleAction#DIG
*/
public static class Dig extends TurtleBlockEvent
{
private final BlockState block;
private final IBlockState block;
private final ITurtleUpgrade upgrade;
private final TurtleSide side;
public Dig( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState block, @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side )
public Dig( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState block, @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side )
{
super( turtle, TurtleAction.DIG, player, world, pos );
@@ -105,7 +106,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return The block which is going to be broken.
*/
@Nonnull
public BlockState getBlock()
public IBlockState getBlock()
{
return block;
}
@@ -184,10 +185,10 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
*/
public static class Inspect extends TurtleBlockEvent
{
private final BlockState state;
private final IBlockState state;
private final Map<String, Object> data;
public Inspect( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull Map<String, Object> data )
public Inspect( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Map<String, Object> data )
{
super( turtle, TurtleAction.INSPECT, player, world, pos );
@@ -203,7 +204,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return The inspected block state.
*/
@Nonnull
public BlockState getState()
public IBlockState getState()
{
return state;
}

View File

@@ -6,8 +6,8 @@
package dan200.computercraft.api.turtle.event;
import com.google.common.eventbus.EventBus;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraftforge.eventbus.api.Event;
import javax.annotation.Nonnull;
import java.util.Objects;
@@ -20,10 +20,8 @@ import java.util.Objects;
*
* @see TurtleActionEvent
*/
public abstract class TurtleEvent
public abstract class TurtleEvent extends Event
{
public static final EventBus EVENT_BUS = new EventBus();
private final ITurtleAccess turtle;
protected TurtleEvent( @Nonnull ITurtleAccess turtle )
@@ -42,10 +40,4 @@ public abstract class TurtleEvent
{
return turtle;
}
public static boolean post( TurtleActionEvent event )
{
EVENT_BUS.post( event );
return event.isCancelled();
}
}

View File

@@ -1,9 +1,8 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.lua.ILuaContext;

View File

@@ -7,10 +7,11 @@
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -21,9 +22,9 @@ import java.util.Objects;
*/
public abstract class TurtleInventoryEvent extends TurtleBlockEvent
{
private final Inventory handler;
private final IItemHandler handler;
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler )
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler )
{
super( turtle, action, player, world, pos );
this.handler = handler;
@@ -35,7 +36,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
* @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world.
*/
@Nullable
public Inventory getItemHandler()
public IItemHandler getItemHandler()
{
return handler;
}
@@ -47,7 +48,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
*/
public static class Suck extends TurtleInventoryEvent
{
public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler )
public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler )
{
super( turtle, TurtleAction.SUCK, player, world, pos, handler );
}
@@ -62,7 +63,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
{
private final ItemStack stack;
public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler, @Nonnull ItemStack stack )
public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.DROP, player, world, pos, handler );

View File

@@ -7,6 +7,7 @@
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraftforge.common.util.FakePlayer;
import javax.annotation.Nonnull;
import java.util.Objects;

View File

@@ -1,9 +1,8 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;

View File

@@ -7,28 +7,36 @@
package dan200.computercraft.client;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.fabricmc.fabric.api.client.render.ColorProviderRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.ModelRotation;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.IUnbakedModel;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.client.renderer.model.ModelRotation;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.HashSet;
import java.util.function.Consumer;
import java.util.Map;
/**
* Registers textures and models for items.
*/
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ClientRegistry
{
private static final String[] EXTRA_MODELS = new String[] {
@@ -62,30 +70,69 @@ public final class ClientRegistry
private ClientRegistry() {}
public static void onTextureStitchEvent( SpriteAtlasTexture atlasTexture, ClientSpriteRegistryCallback.Registry registry )
@SubscribeEvent
public static void registerModels( ModelRegistryEvent event )
{
ModelLoaderRegistry.registerLoader( TurtleModelLoader.INSTANCE );
}
@SubscribeEvent
public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
{
IResourceManager manager = Minecraft.getInstance().getResourceManager();
for( String extra : EXTRA_TEXTURES )
{
registry.register( new Identifier( ComputerCraft.MOD_ID, extra ) );
event.getMap().registerSprite( manager, new ResourceLocation( ComputerCraft.MOD_ID, extra ) );
}
}
public static void onModelBakeEvent( ResourceManager manager, Consumer<ModelIdentifier> out )
@SubscribeEvent
public static void onModelBakeEvent( ModelBakeEvent event )
{
// Load all extra models
ModelLoader loader = event.getModelLoader();
Map<ModelResourceLocation, IBakedModel> registry = event.getModelRegistry();
for( String model : EXTRA_MODELS )
{
out.accept( new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, model ), "inventory" ) );
IBakedModel bakedModel = bake( loader, loader.getUnbakedModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/" + model ) ) );
if( bakedModel != null )
{
registry.put(
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ),
bakedModel
);
}
}
// And load the custom turtle models in too.
registry.put(
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_normal" ), "inventory" ),
bake( loader, TurtleModelLoader.INSTANCE.loadModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/turtle_normal" ) ) )
);
registry.put(
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ), "inventory" ),
bake( loader, TurtleModelLoader.INSTANCE.loadModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/turtle_advanced" ) ) )
);
}
public static void onItemColours()
@SubscribeEvent
public static void onItemColours( ColorHandlerEvent.Item event )
{
ColorProviderRegistry.ITEM.register(
if( ComputerCraft.Items.disk == null || ComputerCraft.Blocks.turtleNormal == null )
{
ComputerCraft.log.warn( "Block/item registration has failed. Skipping registration of item colours." );
return;
}
event.getItemColors().register(
( stack, layer ) -> layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF,
ComputerCraft.Items.disk
);
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
event.getItemColors().register( ( stack, layer ) -> {
switch( layer )
{
case 0:
@@ -102,16 +149,20 @@ public final class ClientRegistry
}, ComputerCraft.Items.pocketComputerNormal, ComputerCraft.Items.pocketComputerAdvanced );
// Setup turtle colours
ColorProviderRegistry.ITEM.register(
event.getItemColors().register(
( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
ComputerCraft.Blocks.turtleNormal, ComputerCraft.Blocks.turtleAdvanced
);
}
private static BakedModel bake( ModelLoader loader, UnbakedModel model )
private static IBakedModel bake( ModelLoader loader, IUnbakedModel model )
{
model.getTextureDependencies( loader::getOrLoadModel, new HashSet<>() );
SpriteAtlasTexture sprite = MinecraftClient.getInstance().getSpriteAtlas();
return model.bake( loader, sprite::getSprite, ModelRotation.X0_Y0 );
model.getTextures( loader::getUnbakedModel, new HashSet<>() );
return model.bake(
loader::getUnbakedModel,
ModelLoader.defaultTextureGetter(),
ModelRotation.X0_Y0, false, DefaultVertexFormats.BLOCK
);
}
}

View File

@@ -10,13 +10,13 @@ import dan200.computercraft.shared.command.text.ChatHelpers;
import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.command.text.TableFormatter;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.minecraft.ChatFormat;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.util.TextComponentUtil;
import net.minecraft.network.chat.Component;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiNewChat;
import net.minecraft.client.gui.GuiUtilRenderComponents;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
@@ -28,25 +28,25 @@ public class ClientTableFormatter implements TableFormatter
private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
private static TextRenderer renderer()
private static FontRenderer renderer()
{
return MinecraftClient.getInstance().textRenderer;
return Minecraft.getInstance().fontRenderer;
}
@Override
@Nullable
public Component getPadding( Component component, int width )
public ITextComponent getPadding( ITextComponent component, int width )
{
int extraWidth = width - getWidth( component );
if( extraWidth <= 0 ) return null;
TextRenderer renderer = renderer();
FontRenderer renderer = renderer();
float spaceWidth = renderer.getCharWidth( ' ' );
float spaceWidth = renderer.getStringWidth( " " );
int spaces = MathHelper.floor( extraWidth / spaceWidth );
int extra = extraWidth - (int) (spaces * spaceWidth);
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), ChatFormat.GRAY );
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), TextFormatting.GRAY );
}
@Override
@@ -56,34 +56,34 @@ public class ClientTableFormatter implements TableFormatter
}
@Override
public int getWidth( Component component )
public int getWidth( ITextComponent component )
{
return renderer().getStringWidth( component.getFormattedText() );
}
@Override
public void writeLine( int id, Component component )
public void writeLine( int id, ITextComponent component )
{
MinecraftClient mc = MinecraftClient.getInstance();
ChatHud chat = mc.inGameHud.getChatHud();
Minecraft mc = Minecraft.getInstance();
GuiNewChat chat = mc.ingameGUI.getChatGUI();
// Trim the text if it goes over the allowed length
int maxWidth = MathHelper.floor( chat.getWidth() / chat.getScale() );
List<Component> list = TextComponentUtil.wrapLines( component, maxWidth, mc.textRenderer, false, false );
if( !list.isEmpty() ) chat.addMessage( list.get( 0 ), id );
int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
List<ITextComponent> list = GuiUtilRenderComponents.splitText( component, maxWidth, mc.fontRenderer, false, false );
if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
}
@Override
public int display( TableBuilder table )
{
ChatHud chat = MinecraftClient.getInstance().inGameHud.getChatHud();
GuiNewChat chat = Minecraft.getInstance().ingameGUI.getChatGUI();
int lastHeight = lastHeights.get( table.getId() );
int height = TableFormatter.super.display( table );
lastHeights.put( table.getId(), height );
for( int i = height; i < lastHeight; i++ ) chat.removeMessage( i + table.getId() );
for( int i = height; i < lastHeight; i++ ) chat.deleteChatLine( i + table.getId() );
return height;
}
}

View File

@@ -6,6 +6,13 @@
package dan200.computercraft.client;
import dan200.computercraft.ComputerCraft;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.gameevent.TickEvent;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class FrameInfo
{
private static int tick;
@@ -25,13 +32,15 @@ public final class FrameInfo
return renderFrame;
}
public static void onTick()
@SubscribeEvent
public static void onTick( TickEvent.ClientTickEvent event )
{
tick++;
if( event.phase == TickEvent.Phase.START ) tick++;
}
public static void onRenderFrame()
@SubscribeEvent
public static void onRenderTick( TickEvent.RenderTickEvent event )
{
renderFrame++;
if( event.phase == TickEvent.Phase.START ) renderFrame++;
}
}

View File

@@ -6,23 +6,23 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.util.Identifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import java.util.Arrays;
public final class FixedWidthFontRenderer
{
private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" );
public static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/term_background.png" );
private static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
public static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/term_background.png" );
public static final int FONT_HEIGHT = 9;
public static final int FONT_WIDTH = 6;
@@ -39,7 +39,7 @@ public final class FixedWidthFontRenderer
private FixedWidthFontRenderer()
{
m_textureManager = MinecraftClient.getInstance().getTextureManager();
m_textureManager = Minecraft.getInstance().getTextureManager();
}
private static void greyscaleify( double[] rgb )
@@ -64,12 +64,12 @@ public final class FixedWidthFontRenderer
int xStart = 1 + column * (FONT_WIDTH + 2);
int yStart = 1 + row * (FONT_HEIGHT + 2);
renderer.vertex( x, y, 0.0 ).texture( xStart / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).texture( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + FONT_WIDTH, y, 0.0 ).texture( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + FONT_WIDTH, y, 0.0 ).texture( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).texture( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + FONT_WIDTH, y + FONT_HEIGHT, 0.0 ).texture( (xStart + FONT_WIDTH) / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.pos( x, y, 0.0 ).tex( xStart / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + FONT_WIDTH, y + FONT_HEIGHT, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex();
}
private void drawQuad( BufferBuilder renderer, double x, double y, int color, double width, Palette p, boolean greyscale )
@@ -83,12 +83,12 @@ public final class FixedWidthFontRenderer
float g = (float) colour[1];
float b = (float) colour[2];
renderer.vertex( x, y, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + width, y, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + width, y, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + width, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.pos( x, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + width, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + width, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + width, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
}
private boolean isGreyScale( int colour )
@@ -100,8 +100,8 @@ public final class FixedWidthFontRenderer
{
// Draw the quads
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBufferBuilder();
renderer.begin( GL11.GL_TRIANGLES, VertexFormats.POSITION_COLOR );
BufferBuilder renderer = tessellator.getBuffer();
renderer.begin( GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR );
if( leftMarginSize > 0.0 )
{
int colour1 = "0123456789abcdef".indexOf( backgroundColour.charAt( 0 ) );
@@ -129,17 +129,17 @@ public final class FixedWidthFontRenderer
}
drawQuad( renderer, x + i * FONT_WIDTH, y, colour, FONT_WIDTH, p, greyScale );
}
GlStateManager.disableTexture();
GlStateManager.disableTexture2D();
tessellator.draw();
GlStateManager.enableTexture();
GlStateManager.enableTexture2D();
}
public void drawStringTextPart( int x, int y, TextBuffer s, TextBuffer textColour, boolean greyScale, Palette p )
{
// Draw the quads
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBufferBuilder();
renderer.begin( GL11.GL_TRIANGLES, VertexFormats.POSITION_UV_COLOR );
BufferBuilder renderer = tessellator.getBuffer();
renderer.begin( GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_COLOR );
for( int i = 0; i < s.length(); i++ )
{
// Switch colour
@@ -195,6 +195,6 @@ public final class FixedWidthFontRenderer
public void bindFont()
{
m_textureManager.bindTexture( FONT );
GlStateManager.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
GlStateManager.texParameteri( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
}
}

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
@@ -14,19 +13,17 @@ import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.inventory.Container;
import net.minecraft.util.ResourceLocation;
public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
public class GuiComputer extends GuiContainer
{
public static final Identifier BACKGROUND_NORMAL = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" );
public static final Identifier BACKGROUND_ADVANCED = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
public static final Identifier BACKGROUND_COMMAND = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final Identifier BACKGROUND_COLOUR = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
public static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" );
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
private final ComputerFamily m_family;
private final ClientComputer m_computer;
@@ -36,11 +33,9 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper;
public GuiComputer( T container, PlayerInventory player, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight )
public GuiComputer( Container container, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight )
{
super( container, player, new TextComponent( "" ) );
super( container );
m_family = family;
m_computer = computer;
m_termWidth = termWidth;
@@ -48,10 +43,10 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
terminal = null;
}
public static GuiComputer<ContainerComputer> create( int id, TileComputer computer, PlayerInventory player )
public GuiComputer( TileComputer computer )
{
return new GuiComputer<>(
new ContainerComputer( id, computer ), player,
this(
new ContainerComputer( computer ),
computer.getFamily(),
computer.createClientComputer(),
ComputerCraft.terminalWidth_computer,
@@ -60,32 +55,32 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
}
@Override
protected void init()
protected void initGui()
{
minecraft.keyboard.enableRepeatEvents( true );
mc.keyboardListener.enableRepeatEvents( true );
int termPxWidth = m_termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = m_termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
containerWidth = termPxWidth + 4 + 24;
containerHeight = termPxHeight + 4 + 24;
xSize = termPxWidth + 4 + 24;
ySize = termPxHeight + 4 + 24;
super.init();
super.initGui();
terminal = new WidgetTerminal( minecraft, () -> m_computer, m_termWidth, m_termHeight, 2, 2, 2, 2 );
terminalWrapper = new WidgetWrapper( terminal, 2 + 12 + left, 2 + 12 + top, termPxWidth, termPxHeight );
terminal = new WidgetTerminal( mc, () -> m_computer, m_termWidth, m_termHeight, 2, 2, 2, 2 );
terminalWrapper = new WidgetWrapper( terminal, 2 + 12 + guiLeft, 2 + 12 + guiTop, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
}
@Override
public void removed()
public void onGuiClosed()
{
super.removed();
super.onGuiClosed();
children.remove( terminal );
terminal = null;
minecraft.keyboard.enableRepeatEvents( false );
mc.keyboardListener.enableRepeatEvents( false );
}
@Override
@@ -96,7 +91,7 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
}
@Override
public void drawBackground( float partialTicks, int mouseX, int mouseY )
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
// Work out where to draw
int startX = terminalWrapper.getX() - 2;
@@ -113,48 +108,39 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
{
case Normal:
default:
minecraft.getTextureManager().bindTexture( BACKGROUND_NORMAL );
mc.getTextureManager().bindTexture( BACKGROUND_NORMAL );
break;
case Advanced:
minecraft.getTextureManager().bindTexture( BACKGROUND_ADVANCED );
mc.getTextureManager().bindTexture( BACKGROUND_ADVANCED );
break;
case Command:
minecraft.getTextureManager().bindTexture( BACKGROUND_COMMAND );
mc.getTextureManager().bindTexture( BACKGROUND_COMMAND );
break;
}
blit( startX - 12, startY - 12, 12, 28, 12, 12 );
blit( startX - 12, endY, 12, 40, 12, 12 );
blit( endX, startY - 12, 24, 28, 12, 12 );
blit( endX, endY, 24, 40, 12, 12 );
drawTexturedModalRect( startX - 12, startY - 12, 12, 28, 12, 12 );
drawTexturedModalRect( startX - 12, endY, 12, 40, 12, 12 );
drawTexturedModalRect( endX, startY - 12, 24, 28, 12, 12 );
drawTexturedModalRect( endX, endY, 24, 40, 12, 12 );
blit( startX, startY - 12, 0, 0, endX - startX, 12 );
blit( startX, endY, 0, 12, endX - startX, 12 );
drawTexturedModalRect( startX, startY - 12, 0, 0, endX - startX, 12 );
drawTexturedModalRect( startX, endY, 0, 12, endX - startX, 12 );
blit( startX - 12, startY, 0, 28, 12, endY - startY );
blit( endX, startY, 36, 28, 12, endY - startY );
drawTexturedModalRect( startX - 12, startY, 0, 28, 12, endY - startY );
drawTexturedModalRect( endX, startY, 36, 28, 12, endY - startY );
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
{
renderBackground( 0 );
drawDefaultBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
}
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
// When pressing tab, send it to the computer first
return (key == GLFW.GLFW_KEY_TAB && getFocused() == terminalWrapper && terminalWrapper.keyPressed( key, scancode, modifiers ))
|| super.keyPressed( key, scancode, modifiers );
renderHoveredToolTip( mouseX, mouseY );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
// Make sure drag events are propagated to children
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@@ -162,7 +148,6 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
@Override
public boolean mouseReleased( double x, double y, int button )
{
// Make sure release events are propagated to children
return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
|| super.mouseReleased( x, y, button );
}

View File

@@ -6,44 +6,45 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ResourceLocation;
public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
public class GuiDiskDrive extends GuiContainer
{
private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" );
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/disk_drive.png" );
public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory inventory )
private final ContainerDiskDrive m_container;
public GuiDiskDrive( ContainerDiskDrive container )
{
super( container, inventory, ComputerCraft.Blocks.diskDrive.getTextComponent() );
super( container );
m_container = container;
}
@Override
protected void drawForeground( int par1, int par2 )
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
{
String title = getTitle().getFormattedText();
font.draw( title, (containerWidth - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.draw( I18n.translate( "container.inventory" ), 8, (containerHeight - 96) + 2, 0x404040 );
String title = m_container.getDiskDrive().getDisplayName().getString();
fontRenderer.drawString( title, (xSize - fontRenderer.getStringWidth( title )) / 2.0f, 6, 0x404040 );
fontRenderer.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 );
}
@Override
protected void drawBackground( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( BACKGROUND );
blit( left, top, 0, 0, containerWidth, containerHeight );
mc.getTextureManager().bindTexture( BACKGROUND );
drawTexturedModalRect( guiLeft, guiTop, 0, 0, xSize, ySize );
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
{
renderBackground();
drawDefaultBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -10,16 +10,15 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class GuiPocketComputer extends GuiComputer<ContainerPocketComputer>
public class GuiPocketComputer extends GuiComputer
{
public GuiPocketComputer( ContainerPocketComputer container, PlayerInventory player )
public GuiPocketComputer( ContainerPocketComputer container )
{
super(
container, player,
container,
getFamily( container.getStack() ),
ItemPocketComputer.createClientComputer( container.getStack() ),
ComputerCraft.terminalWidth_pocketComputer,

View File

@@ -6,46 +6,47 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ResourceLocation;
public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
public class GuiPrinter extends GuiContainer
{
private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" );
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printer.png" );
public GuiPrinter( ContainerPrinter container, PlayerInventory player )
private final ContainerPrinter container;
public GuiPrinter( ContainerPrinter container )
{
super( container, player, ComputerCraft.Blocks.printer.getTextComponent() );
super( container );
this.container = container;
}
@Override
protected void drawForeground( int mouseX, int mouseY )
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
{
String title = getTitle().getFormattedText();
font.draw( title, (containerWidth - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.draw( I18n.translate( "container.inventory" ), 8, containerHeight - 96 + 2, 0x404040 );
String title = container.getPrinter().getDisplayName().getString();
fontRenderer.drawString( title, (xSize - fontRenderer.getStringWidth( title )) / 2.0f, 6, 0x404040 );
fontRenderer.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 );
}
@Override
protected void drawBackground( float f, int i, int j )
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( BACKGROUND );
blit( left, top, 0, 0, containerWidth, containerHeight );
mc.getTextureManager().bindTexture( BACKGROUND );
drawTexturedModalRect( guiLeft, guiTop, 0, 0, xSize, ySize );
if( container.isPrinting() ) blit( left + 34, top + 21, 176, 0, 25, 45 );
if( container.isPrinting() ) drawTexturedModalRect( guiLeft + 34, guiTop + 21, 176, 0, 25, 45 );
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
{
renderBackground();
drawDefaultBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -6,17 +6,16 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.media.items.ItemPrintout;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import org.lwjgl.glfw.GLFW;
import static dan200.computercraft.client.render.PrintoutRenderer.*;
public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
public class GuiPrintout extends GuiContainer
{
private final boolean m_book;
private final int m_pages;
@@ -24,11 +23,11 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
private final TextBuffer[] m_colours;
private int m_page;
public GuiPrintout( ContainerHeldItem container, PlayerInventory player )
public GuiPrintout( ContainerHeldItem container )
{
super( container, player, container.getStack().getDisplayName() );
super( container );
containerHeight = Y_SIZE;
ySize = Y_SIZE;
String[] text = ItemPrintout.getText( container.getStack() );
m_text = new TextBuffer[text.length];
@@ -64,9 +63,9 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
}
@Override
public boolean mouseScrolled( double x, double y, double delta )
public boolean mouseScrolled( double delta )
{
if( super.mouseScrolled( x, y, delta ) ) return true;
if( super.mouseScrolled( delta ) ) return true;
if( delta < 0 )
{
// Scroll up goes to the next page
@@ -85,25 +84,25 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
}
@Override
public void drawBackground( float partialTicks, int mouseX, int mouseY )
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
// Draw the printout
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
GlStateManager.enableDepthTest();
drawBorder( left, top, blitOffset, m_page, m_pages, m_book );
drawText( left + X_TEXT_MARGIN, top + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
drawBorder( guiLeft, guiTop, zLevel, m_page, m_pages, m_book );
drawText( guiLeft + X_TEXT_MARGIN, guiTop + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
{
// We must take the background further back in order to not overlap with our printed pages.
blitOffset--;
renderBackground();
blitOffset++;
zLevel--;
drawDefaultBackground();
zLevel++;
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
@@ -14,15 +13,14 @@ import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
public class GuiTurtle extends GuiContainer
{
private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" );
private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" );
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( "computercraft", "textures/gui/turtle_normal.png" );
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.png" );
private ContainerTurtle m_container;
@@ -32,46 +30,45 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper;
public GuiTurtle( TileTurtle turtle, ContainerTurtle container, PlayerInventory player )
public GuiTurtle( TileTurtle turtle, ContainerTurtle container )
{
super( container, player, turtle.getDisplayName() );
super( container );
m_container = container;
m_family = turtle.getFamily();
m_computer = turtle.getClientComputer();
containerWidth = 254;
containerHeight = 217;
xSize = 254;
ySize = 217;
}
@Override
protected void init()
protected void initGui()
{
super.init();
minecraft.keyboard.enableRepeatEvents( true );
super.initGui();
mc.keyboardListener.enableRepeatEvents( true );
int termPxWidth = ComputerCraft.terminalWidth_turtle * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = ComputerCraft.terminalHeight_turtle * FixedWidthFontRenderer.FONT_HEIGHT;
terminal = new WidgetTerminal(
minecraft, () -> m_computer,
mc, () -> m_computer,
ComputerCraft.terminalWidth_turtle,
ComputerCraft.terminalHeight_turtle,
2, 2, 2, 2
);
terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + left, 2 + 8 + top, termPxWidth, termPxHeight );
terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + guiLeft, 2 + 8 + guiTop, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
}
@Override
public void removed()
public void onGuiClosed()
{
super.removed();
children.remove( terminal );
terminal = null;
minecraft.keyboard.enableRepeatEvents( false );
mc.keyboardListener.enableRepeatEvents( false );
}
@Override
@@ -90,13 +87,13 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
int slotX = slot % 4;
int slotY = slot / 4;
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
blit( left + m_container.m_turtleInvStartX - 2 + slotX * 18, top + m_container.m_playerInvStartY - 2 + slotY * 18, 0, 217, 24, 24 );
mc.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
drawTexturedModalRect( guiLeft + m_container.turtleInvStartX - 2 + slotX * 18, guiTop + m_container.playerInvStartY - 2 + slotY * 18, 0, 217, 24, 24 );
}
}
@Override
protected void drawBackground( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
// Draw term
boolean advanced = m_family == ComputerFamily.Advanced;
@@ -104,8 +101,8 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
// Draw border/inventory
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
blit( left, top, 0, 0, containerWidth, containerHeight );
mc.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
drawTexturedModalRect( guiLeft, guiTop, 0, 0, xSize, ySize );
drawSelectionSlot( advanced );
}
@@ -113,29 +110,8 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
@Override
public void render( int mouseX, int mouseY, float partialTicks )
{
renderBackground();
drawDefaultBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
}
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
return (key == GLFW.GLFW_KEY_TAB && getFocused() == terminalWrapper && terminalWrapper.keyPressed( key, scancode, modifiers ))
|| super.keyPressed( key, scancode, modifiers );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
public boolean mouseReleased( double x, double y, int button )
{
return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
|| super.mouseReleased( x, y, button );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.client.gui.widgets;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.Terminal;
@@ -15,12 +14,13 @@ import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.SharedConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.SharedConstants;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
@@ -29,18 +29,16 @@ import java.util.function.Supplier;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.BACKGROUND;
public class WidgetTerminal implements Element
public class WidgetTerminal implements IGuiEventListener
{
private static final float TERMINATE_TIME = 0.5f;
private final MinecraftClient minecraft;
private final Minecraft client;
private final Supplier<ClientComputer> computer;
private final int termWidth;
private final int termHeight;
private boolean focused;
private float terminateTimer = -1;
private float rebootTimer = -1;
private float shutdownTimer = -1;
@@ -56,9 +54,9 @@ public class WidgetTerminal implements Element
private final BitSet keysDown = new BitSet( 256 );
public WidgetTerminal( MinecraftClient minecraft, Supplier<ClientComputer> computer, int termWidth, int termHeight, int leftMargin, int rightMargin, int topMargin, int bottomMargin )
public WidgetTerminal( Minecraft client, Supplier<ClientComputer> computer, int termWidth, int termHeight, int leftMargin, int rightMargin, int topMargin, int bottomMargin )
{
this.minecraft = minecraft;
this.client = client;
this.computer = computer;
this.termWidth = termWidth;
this.termHeight = termHeight;
@@ -100,7 +98,7 @@ public class WidgetTerminal implements Element
case GLFW.GLFW_KEY_V:
// Ctrl+V for paste
String clipboard = minecraft.keyboard.getClipboard();
String clipboard = client.keyboardListener.getClipboardString();
if( clipboard != null )
{
// Clip to the first occurrence of \r or \n
@@ -120,7 +118,7 @@ public class WidgetTerminal implements Element
}
// Filter the string
clipboard = SharedConstants.stripInvalidChars( clipboard );
clipboard = SharedConstants.filterAllowedCharacters( clipboard );
if( !clipboard.isEmpty() )
{
// Clip to 512 characters and queue the event
@@ -252,23 +250,14 @@ public class WidgetTerminal implements Element
}
@Override
public boolean mouseScrolled( double mouseX, double mouseY, double delta )
public boolean mouseScrolled( double delta )
{
ClientComputer computer = this.computer.get();
if( computer == null || !computer.isColour() || delta == 0 ) return false;
if( computer == null || !computer.isColour() ) return false;
Terminal term = computer.getTerminal();
if( term != null )
if( lastMouseX >= 0 && lastMouseY >= 0 && delta != 0 )
{
int charX = (int) (mouseX / FixedWidthFontRenderer.FONT_WIDTH);
int charY = (int) (mouseY / FixedWidthFontRenderer.FONT_HEIGHT);
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
computer.mouseScroll( delta < 0 ? 1 : -1, charX + 1, charY + 1 );
lastMouseX = charX;
lastMouseY = charY;
queueEvent( "mouse_scroll", delta < 0 ? 1 : -1, lastMouseX + 1, lastMouseY + 1 );
}
return true;
@@ -295,9 +284,9 @@ public class WidgetTerminal implements Element
}
@Override
public boolean changeFocus( boolean reverse )
public void focusChanged( boolean focused )
{
if( focused )
if( !focused )
{
// When blurring, we should make all keys go up
for( int key = 0; key < keysDown.size(); key++ )
@@ -316,9 +305,6 @@ public class WidgetTerminal implements Element
shutdownTimer = terminateTimer = rebootTimer = -1;
}
focused = !focused;
return true;
}
public void draw( int originX, int originY )
@@ -398,15 +384,15 @@ public class WidgetTerminal implements Element
int width = termWidth * FixedWidthFontRenderer.FONT_WIDTH + leftMargin + rightMargin;
int height = termHeight * FixedWidthFontRenderer.FONT_HEIGHT + topMargin + bottomMargin;
minecraft.getTextureManager().bindTexture( BACKGROUND );
client.getTextureManager().bindTexture( BACKGROUND );
Tessellator tesslector = Tessellator.getInstance();
BufferBuilder buffer = tesslector.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_UV );
buffer.vertex( x, y + height, 0 ).texture( 0 / 256.0, height / 256.0 ).next();
buffer.vertex( x + width, y + height, 0 ).texture( width / 256.0, height / 256.0 ).next();
buffer.vertex( x + width, y, 0 ).texture( width / 256.0, 0 / 256.0 ).next();
buffer.vertex( x, y, 0 ).texture( 0 / 256.0, 0 / 256.0 ).next();
BufferBuilder buffer = tesslector.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX );
buffer.pos( x, y + height, 0 ).tex( 0 / 256.0, height / 256.0 ).endVertex();
buffer.pos( x + width, y + height, 0 ).tex( width / 256.0, height / 256.0 ).endVertex();
buffer.pos( x + width, y, 0 ).tex( width / 256.0, 0 / 256.0 ).endVertex();
buffer.pos( x, y, 0 ).tex( 0 / 256.0, 0 / 256.0 ).endVertex();
tesslector.draw();
}
finally

View File

@@ -6,17 +6,17 @@
package dan200.computercraft.client.gui.widgets;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.IGuiEventListener;
public class WidgetWrapper implements Element
public class WidgetWrapper implements IGuiEventListener
{
private final Element listener;
private final IGuiEventListener listener;
private final int x;
private final int y;
private final int width;
private final int height;
public WidgetWrapper( Element listener, int x, int y, int width, int height )
public WidgetWrapper( IGuiEventListener listener, int x, int y, int width, int height )
{
this.listener = listener;
this.x = x;
@@ -26,16 +26,15 @@ public class WidgetWrapper implements Element
}
@Override
public void mouseMoved( double x, double y )
public void focusChanged( boolean b )
{
double dx = x - this.x, dy = y - this.y;
if( dx >= 0 && dx < width && dy >= 0 && dy < height ) listener.mouseMoved( dx, dy );
listener.focusChanged( b );
}
@Override
public boolean changeFocus( boolean reverse )
public boolean canFocus()
{
return listener.changeFocus( reverse );
return listener.canFocus();
}
@Override
@@ -60,10 +59,9 @@ public class WidgetWrapper implements Element
}
@Override
public boolean mouseScrolled( double x, double y, double delta )
public boolean mouseScrolled( double delta )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseScrolled( dx, dy, delta );
return listener.mouseScrolled( delta );
}
@Override
@@ -103,11 +101,4 @@ public class WidgetWrapper implements Element
{
return height;
}
@Override
public boolean isMouseOver( double x, double y )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height;
}
}

View File

@@ -7,78 +7,80 @@
package dan200.computercraft.client.proxy;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.ClientRegistry;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.*;
import dan200.computercraft.client.render.TileEntityCableRenderer;
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.network.container.*;
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.render.BlockEntityRendererRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
import net.minecraft.container.ArrayPropertyDelegate;
import net.minecraft.inventory.BasicInventory;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import java.util.function.BiFunction;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class ComputerCraftProxyClient
{
public static void setup()
@SubscribeEvent
public static void setupClient( FMLClientSetupEvent event )
{
registerContainers();
// Setup TESRs
BlockEntityRendererRegistry.INSTANCE.register( TileMonitor.class, new TileEntityMonitorRenderer() );
BlockEntityRendererRegistry.INSTANCE.register( TileCable.class, new TileEntityCableRenderer() );
BlockEntityRendererRegistry.INSTANCE.register( TileTurtle.class, new TileEntityTurtleRenderer() );
ClientRegistry.onItemColours();
ClientSpriteRegistryCallback.registerBlockAtlas( ClientRegistry::onTextureStitchEvent );
ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent );
ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) ->
TurtleModelLoader.INSTANCE.accepts( name ) ? TurtleModelLoader.INSTANCE.loadModel( name ) : null
);
ClientTickCallback.EVENT.register( client -> FrameInfo.onTick() );
ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() );
ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() );
ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() );
}
private static void registerContainers()
{
ContainerType.registerGui( TileEntityContainerType::computer, ( id, packet, player ) ->
GuiComputer.create( id, (TileComputer) packet.getTileEntity( player ), player.inventory ) );
ContainerType.registerGui( TileEntityContainerType::computer, ( packet, player ) ->
new GuiComputer( (TileComputer) packet.getTileEntity( player ) ) );
ContainerType.registerGui( TileEntityContainerType::diskDrive, GuiDiskDrive::new );
ContainerType.registerGui( TileEntityContainerType::printer, GuiPrinter::new );
ContainerType.registerGui( TileEntityContainerType::turtle, ( id, packet, player ) -> {
ContainerType.registerGui( TileEntityContainerType::turtle, ( packet, player ) -> {
TileTurtle turtle = (TileTurtle) packet.getTileEntity( player );
return new GuiTurtle( turtle,
new ContainerTurtle( id, player.inventory, new BasicInventory( TileTurtle.INVENTORY_SIZE ), new ArrayPropertyDelegate( 1 ) ),
player.inventory
);
return new GuiTurtle( turtle, new ContainerTurtle( player.inventory, turtle.getAccess(), turtle.getClientComputer() ) );
} );
ContainerType.registerGui( PocketComputerContainerType::new, GuiPocketComputer::new );
ContainerType.registerGui( PrintoutContainerType::new, GuiPrintout::new );
ContainerType.registerGui( ViewComputerContainerType::new, ( id, packet, player ) -> {
ContainerType.registerGui( ViewComputerContainerType::new, ( packet, player ) -> {
ClientComputer computer = ComputerCraft.clientComputerRegistry.get( packet.instanceId );
if( computer == null )
{
ComputerCraft.clientComputerRegistry.add( packet.instanceId, computer = new ClientComputer( packet.instanceId ) );
}
ContainerViewComputer container = new ContainerViewComputer( id, computer );
return new GuiComputer<>( container, player.inventory, packet.family, computer, packet.width, packet.height );
ContainerViewComputer container = new ContainerViewComputer( computer );
return new GuiComputer( container, packet.family, computer, packet.width, packet.height );
} );
ModLoadingContext.get().registerExtensionPoint( ExtensionPoint.GUIFACTORY, () -> packet -> {
ContainerType<?> type = ContainerType.factories.get( packet.getId() ).get();
if( packet.getAdditionalData() != null ) type.fromBytes( packet.getAdditionalData() );
@SuppressWarnings( "unchecked" )
BiFunction<ContainerType<?>, EntityPlayer, GuiContainer> factory = (BiFunction<ContainerType<?>, EntityPlayer, GuiContainer>) ContainerType.guiFactories.get( packet.getId() );
return factory.apply( type, Minecraft.getInstance().player );
} );
}
/*
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public static final class ForgeHandlers
{
@@ -91,5 +93,4 @@ public final class ComputerCraftProxyClient
}
}
}
*/
}

View File

@@ -6,23 +6,26 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.opengl.GL11;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class CableHighlightRenderer
{
private CableHighlightRenderer()
@@ -32,43 +35,54 @@ public final class CableHighlightRenderer
/**
* Draw an outline for a specific part of a cable "Multipart".
*
* @see WorldRenderer#drawHighlightedBlockOutline(Entity, HitResult, int, float)
* @param event The event to observe
* @see WorldRenderer#drawSelectionBox(EntityPlayer, RayTraceResult, int, float)
*/
public static boolean drawHighlight( Camera camera, BlockHitResult hit )
@SubscribeEvent
public static void drawHighlight( DrawBlockHighlightEvent event )
{
MinecraftClient mc = MinecraftClient.getInstance();
BlockPos pos = hit.getBlockPos();
World world = mc.world;
if( event.getTarget().type != RayTraceResult.Type.BLOCK ) return;
BlockState state = world.getBlockState( pos );
BlockPos pos = event.getTarget().getBlockPos();
World world = event.getPlayer().getEntityWorld();
IBlockState state = world.getBlockState( pos );
// We only care about instances with both cable and modem.
if( state.getBlock() != ComputerCraft.Blocks.cable || state.get( BlockCable.MODEM ).getFacing() == null || !state.get( BlockCable.CABLE ) )
{
return false;
return;
}
event.setCanceled( true );
EntityPlayer player = event.getPlayer();
Minecraft mc = Minecraft.getInstance();
float partialTicks = event.getPartialTicks();
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO );
GlStateManager.lineWidth( Math.max( 2.5F, mc.window.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.disableTexture();
GlStateManager.lineWidth( Math.max( 2.5F, mc.mainWindow.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.disableTexture2D();
GlStateManager.depthMask( false );
GlStateManager.matrixMode( GL11.GL_PROJECTION );
GlStateManager.pushMatrix();
GlStateManager.scalef( 1.0F, 1.0F, 0.999F );
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks;
double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks;
double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks;
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), event.getTarget().hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) )
? CableShapes.getModemShape( state )
: CableShapes.getCableShape( state );
WorldRenderer.drawShapeOutline( shape, pos.getX() - camera.getPos().getX(), pos.getY() - camera.getPos().getY(), pos.getZ() - camera.getPos().getZ(), 0.0F, 0.0F, 0.0F, 0.4F );
WorldRenderer.drawShape( shape, pos.getX() - x, pos.getY() - y, pos.getZ() - z, 0.0F, 0.0F, 0.0F, 0.4F );
GlStateManager.popMatrix();
GlStateManager.matrixMode( GL11.GL_MODELVIEW );
GlStateManager.depthMask( true );
GlStateManager.enableTexture();
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
return true;
}
}

View File

@@ -6,14 +6,13 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.shared.mixed.MixedFirstPersonRenderer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.FirstPersonRenderer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.FirstPersonRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AbsoluteHand;
import net.minecraft.util.Hand;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumHandSide;
import net.minecraft.util.math.MathHelper;
public abstract class ItemMapLikeRenderer
@@ -22,23 +21,23 @@ public abstract class ItemMapLikeRenderer
* The main rendering method for the item
*
* @param stack The stack to render
* @see FirstPersonRenderer#renderFirstPersonMap(ItemStack)
* @see FirstPersonRenderer#renderMapFirstPerson(ItemStack)
*/
protected abstract void renderItem( ItemStack stack );
public void renderItemFirstPerson( Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
protected void renderItemFirstPerson( EnumHand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
{
PlayerEntity player = MinecraftClient.getInstance().player;
EntityPlayer player = Minecraft.getInstance().player;
GlStateManager.pushMatrix();
if( hand == Hand.MAIN_HAND && player.getOffHandStack().isEmpty() )
if( hand == EnumHand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
{
renderItemFirstPersonCenter( pitch, equipProgress, swingProgress, stack );
}
else
{
renderItemFirstPersonSide(
hand == Hand.MAIN_HAND ? player.getMainHand() : player.getMainHand().getOpposite(),
hand == EnumHand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
equipProgress, swingProgress, stack
);
}
@@ -52,12 +51,12 @@ public abstract class ItemMapLikeRenderer
* @param equipProgress The equip progress of this item
* @param swingProgress The swing progress of this item
* @param stack The stack to render
* @see FirstPersonRenderer#method_3222(float, AbsoluteHand, float, ItemStack) // renderMapFirstPersonSide
* @see FirstPersonRenderer#renderMapFirstPersonSide(float, EnumHandSide, float, ItemStack)
*/
private void renderItemFirstPersonSide( AbsoluteHand side, float equipProgress, float swingProgress, ItemStack stack )
private void renderItemFirstPersonSide( EnumHandSide side, float equipProgress, float swingProgress, ItemStack stack )
{
MinecraftClient minecraft = MinecraftClient.getInstance();
float offset = side == AbsoluteHand.RIGHT ? 1f : -1f;
Minecraft minecraft = Minecraft.getInstance();
float offset = side == EnumHandSide.RIGHT ? 1f : -1f;
GlStateManager.translatef( offset * 0.125f, -0.125f, 0f );
// If the player is not invisible then render a single arm
@@ -65,7 +64,7 @@ public abstract class ItemMapLikeRenderer
{
GlStateManager.pushMatrix();
GlStateManager.rotatef( offset * 10f, 0f, 0f, 1f );
((MixedFirstPersonRenderer) minecraft.getFirstPersonRenderer()).renderArmFirstPerson_CC( equipProgress, swingProgress, side );
minecraft.getFirstPersonRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
GlStateManager.popMatrix();
}
@@ -94,11 +93,11 @@ public abstract class ItemMapLikeRenderer
* @param equipProgress The equip progress of this item
* @param swingProgress The swing progress of this item
* @param stack The stack to render
* @see FirstPersonRenderer#renderFirstPersonMap(float, float, float)
* @see FirstPersonRenderer#renderMapFirstPerson(float, float, float)
*/
private void renderItemFirstPersonCenter( float pitch, float equipProgress, float swingProgress, ItemStack stack )
{
MixedFirstPersonRenderer renderer = (MixedFirstPersonRenderer) MinecraftClient.getInstance().getFirstPersonRenderer();
FirstPersonRenderer renderer = Minecraft.getInstance().getFirstPersonRenderer();
// Setup the appropriate transformations. This is just copied from the
// corresponding method in ItemRenderer.
@@ -106,10 +105,10 @@ public abstract class ItemMapLikeRenderer
float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
GlStateManager.translatef( 0f, -tX / 2f, tZ );
float pitchAngle = renderer.getMapAngleFromPitch_CC( pitch );
float pitchAngle = renderer.getMapAngleFromPitch( pitch );
GlStateManager.translatef( 0f, 0.04f + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
GlStateManager.rotatef( pitchAngle * -85f, 1f, 0f, 0f );
renderer.renderArms_CC();
renderer.renderArms();
float rX = MathHelper.sin( swingRt * (float) Math.PI );
GlStateManager.rotatef( rX * 20f, 1f, 0f, 0f );
GlStateManager.scalef( 2f, 2f, 2f );

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
@@ -17,13 +16,16 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderSpecificHandEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
@@ -32,19 +34,29 @@ import static dan200.computercraft.client.gui.GuiComputer.*;
/**
* Emulates map rendering for pocket computers
*/
@Environment( EnvType.CLIENT )
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ItemPocketRenderer extends ItemMapLikeRenderer
{
private static final int MARGIN = 2;
private static final int FRAME = 12;
private static final int LIGHT_HEIGHT = 8;
public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
private ItemPocketRenderer()
{
}
@SubscribeEvent
public static void renderItem( RenderSpecificHandEvent event )
{
ItemStack stack = event.getItemStack();
if( !(stack.getItem() instanceof ItemPocketComputer) ) return;
event.setCanceled( true );
INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
}
@Override
protected void renderItem( ItemStack stack )
{
@@ -100,13 +112,13 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
else
{
// Otherwise render a plain background
MinecraftClient.getInstance().getTextureManager().bindTexture( BACKGROUND );
Minecraft.getInstance().getTextureManager().bindTexture( BACKGROUND );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
BufferBuilder buffer = tessellator.getBuffer();
Colour black = Colour.Black;
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION );
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION );
renderTexture( buffer, 0, 0, 0, 0, width, height, black.getR(), black.getG(), black.getB() );
tessellator.draw();
}
@@ -119,7 +131,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderFrame( ComputerFamily family, int colour, int width, int height )
{
MinecraftClient.getInstance().getTextureManager().bindTexture( colour != -1
Minecraft.getInstance().getTextureManager().bindTexture( colour != -1
? BACKGROUND_COLOUR
: family == ComputerFamily.Normal ? BACKGROUND_NORMAL : BACKGROUND_ADVANCED
);
@@ -129,8 +141,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
float b = (colour & 0xFF) / 255.0f;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_UV_COLOR );
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR );
// Top left, middle, right
renderTexture( buffer, -FRAME, -FRAME, 12, 28, FRAME, FRAME, r, g, b );
@@ -161,22 +173,22 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderLight( int colour, int width, int height )
{
GlStateManager.enableBlend();
GlStateManager.disableTexture();
GlStateManager.disableTexture2D();
float r = ((colour >>> 16) & 0xFF) / 255.0f;
float g = ((colour >>> 8) & 0xFF) / 255.0f;
float b = (colour & 0xFF) / 255.0f;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR );
buffer.vertex( width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
buffer.vertex( width, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
buffer.vertex( width, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
buffer.vertex( width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR );
buffer.pos( width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( width, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( width, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
tessellator.draw();
GlStateManager.enableTexture();
GlStateManager.enableTexture2D();
}
private static void renderTerminal( Terminal terminal, boolean greyscale, int width, int height )
@@ -234,9 +246,9 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderTexture( BufferBuilder builder, int x, int y, int textureX, int textureY, int width, int height, int textureWidth, int textureHeight, float r, float g, float b )
{
float scale = 1 / 255.0f;
builder.vertex( x, y + height, 0 ).texture( textureX * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).next();
builder.vertex( x + width, y + height, 0 ).texture( (textureX + textureWidth) * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).next();
builder.vertex( x + width, y, 0 ).texture( (textureX + textureWidth) * scale, textureY * scale ).color( r, g, b, 1.0f ).next();
builder.vertex( x, y, 0 ).texture( textureX * scale, textureY * scale ).color( r, g, b, 1.0f ).next();
builder.pos( x, y + height, 0 ).tex( textureX * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).endVertex();
builder.pos( x + width, y + height, 0 ).tex( (textureX + textureWidth) * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).endVertex();
builder.pos( x + width, y, 0 ).tex( (textureX + textureWidth) * scale, textureY * scale ).color( r, g, b, 1.0f ).endVertex();
builder.pos( x, y, 0 ).tex( textureX * scale, textureY * scale ).color( r, g, b, 1.0f ).endVertex();
}
}

View File

@@ -6,12 +6,15 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.media.items.ItemPrintout;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderItemInFrameEvent;
import net.minecraftforge.client.event.RenderSpecificHandEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
@@ -22,16 +25,15 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENG
/**
* Emulates map and item-frame rendering for printouts
*/
@Environment( EnvType.CLIENT )
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
{
public static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer();
private static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer();
private ItemPrintoutRenderer()
{
}
/*
@SubscribeEvent
public static void onRenderInHand( RenderSpecificHandEvent event )
{
@@ -41,7 +43,6 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
event.setCanceled( true );
INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
}
*/
@Override
protected void renderItem( ItemStack stack )
@@ -60,12 +61,15 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
GlStateManager.enableLighting();
}
public void renderInFrame( ItemFrameEntity entity, ItemStack stack )
@SubscribeEvent
public static void onRenderInFrame( RenderItemInFrameEvent event )
{
GlStateManager.disableLighting();
ItemStack stack = event.getItem();
if( !(stack.getItem() instanceof ItemPrintout) ) return;
int rotation = entity.getRotation();
GlStateManager.rotatef( (float) rotation * 360.0F / 8.0F, 0.0F, 0.0F, 1.0F );
event.setCanceled( true );
GlStateManager.disableLighting();
// Move a little bit forward to ensure we're not clipping with the frame
GlStateManager.translatef( 0.0f, 0.0f, -0.001f );

View File

@@ -6,13 +6,19 @@
package dan200.computercraft.client.render;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraftforge.client.model.pipeline.LightUtil;
import net.minecraftforge.client.model.pipeline.VertexTransformer;
import net.minecraftforge.common.model.TRSRTransformation;
import javax.annotation.Nonnull;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import java.util.List;
/**
@@ -34,11 +40,6 @@ public final class ModelTransformer
}
public static void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> input, Matrix4f transform )
{
transformQuadsTo( VertexFormats.POSITION_COLOR_UV_NORMAL, output, input, transform );
}
public static void transformQuadsTo( VertexFormat format, List<BakedQuad> output, List<BakedQuad> input, Matrix4f transform )
{
if( transform == null || transform.equals( identity ) )
{
@@ -46,55 +47,224 @@ public final class ModelTransformer
}
else
{
for( BakedQuad quad : input ) output.add( doTransformQuad( format, quad, transform ) );
Matrix4f normalMatrix = new Matrix4f( transform );
normalMatrix.invert();
normalMatrix.transpose();
for( BakedQuad quad : input ) output.add( doTransformQuad( quad, transform, normalMatrix ) );
}
}
public static BakedQuad transformQuad( VertexFormat format, BakedQuad input, Matrix4f transform )
public static BakedQuad transformQuad( BakedQuad input, Matrix4f transform )
{
if( transform == null || transform.equals( identity ) ) return input;
return doTransformQuad( format, input, transform );
Matrix4f normalMatrix = new Matrix4f( transform );
normalMatrix.invert();
normalMatrix.transpose();
return doTransformQuad( input, transform, normalMatrix );
}
private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform )
private static BakedQuad doTransformQuad( BakedQuad input, Matrix4f positionMatrix, Matrix4f normalMatrix )
{
int[] vertexData = quad.getVertexData().clone();
int offset = 0;
BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), quad.getSprite() );
for( int i = 0; i < format.getElementCount(); ++i ) // For each vertex element
BakedQuadBuilder builder = new BakedQuadBuilder( input.getFormat() );
NormalAwareTransformer transformer = new NormalAwareTransformer( builder, positionMatrix, normalMatrix );
input.pipe( transformer );
if( transformer.areNormalsInverted() )
{
VertexFormatElement element = format.getElement( i );
if( element.isPosition() &&
element.getFormat() == VertexFormatElement.Format.FLOAT &&
element.getCount() == 3 ) // When we find a position element
{
for( int j = 0; j < 4; ++j ) // For each corner of the quad
{
int start = offset + j * format.getVertexSize();
if( (start % 4) == 0 )
{
start = start / 4;
// Extract the position
Vector4f pos = new Vector4f(
Float.intBitsToFloat( vertexData[start] ),
Float.intBitsToFloat( vertexData[start + 1] ),
Float.intBitsToFloat( vertexData[start + 2] ),
1
);
// Transform the position
transform.transform( pos );
// Insert the position
vertexData[start] = Float.floatToRawIntBits( pos.x );
vertexData[start + 1] = Float.floatToRawIntBits( pos.y );
vertexData[start + 2] = Float.floatToRawIntBits( pos.z );
}
}
}
offset += element.getSize();
builder.swap( 1, 3 );
transformer.areNormalsInverted();
}
return builder.build();
}
/**
* A vertex transformer that tracks whether the normals have been inverted and so the vertices
* should be reordered so backface culling works as expected.
*/
private static class NormalAwareTransformer extends VertexTransformer
{
private final Matrix4f positionMatrix;
private final Matrix4f normalMatrix;
private int vertexIndex = 0, elementIndex = 0;
private final Point3f[] before = new Point3f[4];
private final Point3f[] after = new Point3f[4];
NormalAwareTransformer( IVertexConsumer parent, Matrix4f positionMatrix, Matrix4f normalMatrix )
{
super( parent );
this.positionMatrix = positionMatrix;
this.normalMatrix = normalMatrix;
}
@Override
public void setQuadOrientation( @Nonnull EnumFacing orientation )
{
super.setQuadOrientation( orientation == null ? orientation : TRSRTransformation.rotate( positionMatrix, orientation ) );
}
@Override
public void put( int element, @Nonnull float... data )
{
switch( getVertexFormat().getElement( element ).getUsage() )
{
case POSITION:
{
Point3f vec = new Point3f( data );
Point3f newVec = new Point3f();
positionMatrix.transform( vec, newVec );
float[] newData = new float[4];
newVec.get( newData );
super.put( element, newData );
before[vertexIndex] = vec;
after[vertexIndex] = newVec;
break;
}
case NORMAL:
{
Vector3f vec = new Vector3f( data );
normalMatrix.transform( vec );
float[] newData = new float[4];
vec.get( newData );
super.put( element, newData );
break;
}
default:
super.put( element, data );
break;
}
elementIndex++;
if( elementIndex == getVertexFormat().getElementCount() )
{
vertexIndex++;
elementIndex = 0;
}
}
public boolean areNormalsInverted()
{
Vector3f temp1 = new Vector3f(), temp2 = new Vector3f();
Vector3f crossBefore = new Vector3f(), crossAfter = new Vector3f();
// Determine what cross product we expect to have
temp1.sub( before[1], before[0] );
temp2.sub( before[1], before[2] );
crossBefore.cross( temp1, temp2 );
normalMatrix.transform( crossBefore );
// And determine what cross product we actually have
temp1.sub( after[1], after[0] );
temp2.sub( after[1], after[2] );
crossAfter.cross( temp1, temp2 );
// If the angle between expected and actual cross product is greater than
// pi/2 radians then we will need to reorder our quads.
return Math.abs( crossBefore.angle( crossAfter ) ) >= Math.PI / 2;
}
}
/**
* A vertex consumer which is capable of building {@link BakedQuad}s.
*
* Equivalent to {@link net.minecraftforge.client.model.pipeline.UnpackedBakedQuad.Builder} but more memory
* efficient.
*
* This also provides the ability to swap vertices through {@link #swap(int, int)} to allow reordering.
*/
private static final class BakedQuadBuilder implements IVertexConsumer
{
private final VertexFormat format;
private final int[] vertexData;
private int vertexIndex = 0, elementIndex = 0;
private EnumFacing orientation;
private int quadTint;
private boolean diffuse;
private TextureAtlasSprite texture;
private BakedQuadBuilder( VertexFormat format )
{
this.format = format;
vertexData = new int[format.getSize()];
}
@Nonnull
@Override
public VertexFormat getVertexFormat()
{
return format;
}
@Override
public void setQuadTint( int tint )
{
quadTint = tint;
}
@Override
public void setQuadOrientation( @Nonnull EnumFacing orientation )
{
this.orientation = orientation;
}
@Override
public void setApplyDiffuseLighting( boolean diffuse )
{
this.diffuse = diffuse;
}
@Override
public void setTexture( @Nonnull TextureAtlasSprite texture )
{
this.texture = texture;
}
@Override
public void put( int element, @Nonnull float... data )
{
LightUtil.pack( data, vertexData, format, vertexIndex, element );
elementIndex++;
if( elementIndex == getVertexFormat().getElementCount() )
{
vertexIndex++;
elementIndex = 0;
}
}
public void swap( int a, int b )
{
int length = vertexData.length / 4;
for( int i = 0; i < length; i++ )
{
int temp = vertexData[a * length + i];
vertexData[a * length + i] = vertexData[b * length + i];
vertexData[b * length + i] = temp;
}
}
public BakedQuad build()
{
if( elementIndex != 0 || vertexIndex != 4 )
{
throw new IllegalStateException( "Got an unexpected number of elements/vertices" );
}
if( texture == null )
{
throw new IllegalStateException( "Texture has not been set" );
}
return new BakedQuad( vertexData, quadTint, orientation, texture, diffuse, format );
}
return copy;
}
}

View File

@@ -6,24 +6,30 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.opengl.GL11;
import java.util.EnumSet;
import static net.minecraft.util.math.Direction.*;
import static net.minecraft.util.EnumFacing.*;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class MonitorHighlightRenderer
{
private static final float EXPAND = 0.002f;
@@ -32,22 +38,23 @@ public final class MonitorHighlightRenderer
{
}
public static boolean drawHighlight( Camera camera, BlockHitResult hit )
@SubscribeEvent
public static void drawHighlight( DrawBlockHighlightEvent event )
{
MinecraftClient mc = MinecraftClient.getInstance();
if( mc.player.isSneaking() ) return false;
if( event.getTarget().type != RayTraceResult.Type.BLOCK || event.getPlayer().isSneaking() ) return;
BlockPos pos = hit.getBlockPos();
World world = mc.world;
World world = event.getPlayer().getEntityWorld();
BlockPos pos = event.getTarget().getBlockPos();
BlockEntity tile = world.getBlockEntity( pos );
if( !(tile instanceof TileMonitor) ) return false;
TileEntity tile = world.getTileEntity( pos );
if( !(tile instanceof TileMonitor) ) return;
TileMonitor monitor = (TileMonitor) tile;
event.setCanceled( true );
// Determine which sides are part of the external faces of the monitor, and so which need to be rendered.
EnumSet<Direction> faces = EnumSet.allOf( Direction.class );
Direction front = monitor.getFront();
EnumSet<EnumFacing> faces = EnumSet.allOf( EnumFacing.class );
EnumFacing front = monitor.getFront();
faces.remove( front );
if( monitor.getXIndex() != 0 ) faces.remove( monitor.getRight().getOpposite() );
if( monitor.getXIndex() != monitor.getWidth() - 1 ) faces.remove( monitor.getRight() );
@@ -56,16 +63,21 @@ public final class MonitorHighlightRenderer
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO );
GlStateManager.lineWidth( Math.max( 2.5F, (float) mc.window.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.disableTexture();
GlStateManager.lineWidth( Math.max( 2.5F, (float) Minecraft.getInstance().mainWindow.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.disableTexture2D();
GlStateManager.depthMask( false );
GlStateManager.pushMatrix();
GlStateManager.translated( pos.getX() - camera.getPos().getX(), pos.getY() - camera.getPos().getY(), pos.getZ() - camera.getPos().getZ() );
EntityPlayer player = event.getPlayer();
double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * event.getPartialTicks();
double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * event.getPartialTicks();
double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * event.getPartialTicks();
GlStateManager.translated( -x + pos.getX(), -y + pos.getY(), -z + pos.getZ() );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_LINES, VertexFormats.POSITION_COLOR );
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR );
// I wish I could think of a better way to do this
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, 0, 0, 0, UP );
@@ -85,23 +97,21 @@ public final class MonitorHighlightRenderer
GlStateManager.popMatrix();
GlStateManager.depthMask( true );
GlStateManager.enableTexture();
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
return true;
}
private static void line( BufferBuilder buffer, int x, int y, int z, Direction direction )
private static void line( BufferBuilder buffer, int x, int y, int z, EnumFacing direction )
{
double minX = x == 0 ? -EXPAND : 1 + EXPAND;
double minY = y == 0 ? -EXPAND : 1 + EXPAND;
double minZ = z == 0 ? -EXPAND : 1 + EXPAND;
buffer.vertex( minX, minY, minZ ).color( 0, 0, 0, 0.4f ).next();
buffer.vertex(
minX + direction.getOffsetX() * (1 + EXPAND * 2),
minY + direction.getOffsetY() * (1 + EXPAND * 2),
minZ + direction.getOffsetZ() * (1 + EXPAND * 2)
).color( 0, 0, 0, 0.4f ).next();
buffer.pos( minX, minY, minZ ).color( 0, 0, 0, 0.4f ).endVertex();
buffer.pos(
minX + direction.getXOffset() * (1 + EXPAND * 2),
minY + direction.getYOffset() * (1 + EXPAND * 2),
minZ + direction.getZOffset() * (1 + EXPAND * 2)
).color( 0, 0, 0, 0.4f ).endVertex();
}
}

View File

@@ -6,17 +6,17 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.util.Identifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
@@ -24,7 +24,7 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
public final class PrintoutRenderer
{
private static final Identifier BG = new Identifier( "computercraft", "textures/gui/printout.png" );
private static final ResourceLocation BG = new ResourceLocation( "computercraft", "textures/gui/printout.png" );
private static final double BG_SIZE = 256.0;
/**
@@ -76,7 +76,7 @@ public final class PrintoutRenderer
{
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
GlStateManager.enableBlend();
GlStateManager.enableTexture();
GlStateManager.enableTexture2D();
GlStateManager.blendFuncSeparate( SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO );
FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance();
@@ -91,14 +91,14 @@ public final class PrintoutRenderer
{
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
GlStateManager.enableBlend();
GlStateManager.enableTexture();
GlStateManager.enableTexture2D();
GlStateManager.blendFuncSeparate( SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO );
MinecraftClient.getInstance().getTextureManager().bindTexture( BG );
Minecraft.getInstance().getTextureManager().bindTexture( BG );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_UV );
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX );
int leftPages = page;
int rightPages = pages - page - 1;
@@ -159,18 +159,18 @@ public final class PrintoutRenderer
private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double u, double v, double width, double height )
{
buffer.vertex( x, y + height, z ).texture( u / BG_SIZE, (v + height) / BG_SIZE ).next();
buffer.vertex( x + width, y + height, z ).texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).next();
buffer.vertex( x + width, y, z ).texture( (u + width) / BG_SIZE, v / BG_SIZE ).next();
buffer.vertex( x, y, z ).texture( u / BG_SIZE, v / BG_SIZE ).next();
buffer.pos( x, y + height, z ).tex( u / BG_SIZE, (v + height) / BG_SIZE ).endVertex();
buffer.pos( x + width, y + height, z ).tex( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).endVertex();
buffer.pos( x + width, y, z ).tex( (u + width) / BG_SIZE, v / BG_SIZE ).endVertex();
buffer.pos( x, y, z ).tex( u / BG_SIZE, v / BG_SIZE ).endVertex();
}
private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double width, double height, double u, double v, double tWidth, double tHeight )
{
buffer.vertex( x, y + height, z ).texture( u / BG_SIZE, (v + tHeight) / BG_SIZE ).next();
buffer.vertex( x + width, y + height, z ).texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).next();
buffer.vertex( x + width, y, z ).texture( (u + tWidth) / BG_SIZE, v / BG_SIZE ).next();
buffer.vertex( x, y, z ).texture( u / BG_SIZE, v / BG_SIZE ).next();
buffer.pos( x, y + height, z ).tex( u / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex();
buffer.pos( x + width, y + height, z ).tex( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex();
buffer.pos( x + width, y, z ).tex( (u + tWidth) / BG_SIZE, v / BG_SIZE ).endVertex();
buffer.pos( x, y, z ).tex( u / BG_SIZE, v / BG_SIZE ).endVertex();
}
public static double offsetAt( int page )

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wired.CableModemVariant;
@@ -14,19 +13,23 @@ import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;
@@ -35,7 +38,7 @@ import java.util.Random;
/**
* Render breaking animation only over part of a {@link TileCable}.
*/
public class TileEntityCableRenderer extends BlockEntityRenderer<TileCable>
public class TileEntityCableRenderer extends TileEntityRenderer<TileCable>
{
private static final Random random = new Random();
@@ -46,34 +49,44 @@ public class TileEntityCableRenderer extends BlockEntityRenderer<TileCable>
BlockPos pos = te.getPos();
MinecraftClient mc = MinecraftClient.getInstance();
Minecraft mc = Minecraft.getInstance();
HitResult hit = mc.hitResult;
if( !(hit instanceof BlockHitResult) || !((BlockHitResult) hit).getBlockPos().equals( pos ) ) return;
RayTraceResult hit = mc.objectMouseOver;
if( hit == null || !hit.getBlockPos().equals( pos ) ) return;
if( MinecraftForgeClient.getRenderPass() != 0 ) return;
World world = te.getWorld();
BlockState state = te.getCachedState();
IBlockState state = world.getBlockState( pos );
Block block = state.getBlock();
if( block != ComputerCraft.Blocks.cable ) return;
state = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
state = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) )
? block.getDefaultState().with( BlockCable.MODEM, state.get( BlockCable.MODEM ) )
: state.with( BlockCable.MODEM, CableModemVariant.None );
BakedModel model = mc.getBlockRenderManager().getModel( state );
IBakedModel model = mc.getBlockRendererDispatcher().getModelForState( state );
preRenderDamagedBlocks();
BufferBuilder buffer = Tessellator.getInstance().getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_UV_LMAP );
buffer.setOffset( x - pos.getX(), y - pos.getY(), z - pos.getZ() );
buffer.disableColor();
BufferBuilder buffer = Tessellator.getInstance().getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.BLOCK );
buffer.setTranslation( x - pos.getX(), y - pos.getY(), z - pos.getZ() );
buffer.noColor();
ForgeHooksClient.setRenderLayer( block.getRenderLayer() );
// See BlockRendererDispatcher#renderBlockDamage
Sprite breakingTexture = mc.getSpriteAtlas().getSprite( DESTROY_STAGE_TEXTURES[destroyStage] );
mc.getBlockRenderManager().tesselateDamage( state, pos, breakingTexture, world );
TextureAtlasSprite breakingTexture = mc.getTextureMap().getSprite( DESTROY_STAGES[destroyStage] );
mc.getBlockRendererDispatcher().getBlockModelRenderer().renderModel(
world,
ForgeHooksClient.getDamageModel( model, breakingTexture, state, world, pos ),
state, pos, buffer, true, random, state.getPositionRandom( pos ), EmptyModelData.INSTANCE
);
buffer.setOffset( 0, 0, 0 );
ForgeHooksClient.setRenderLayer( BlockRenderLayer.SOLID );
buffer.setTranslation( 0, 0, 0 );
Tessellator.getInstance().draw();
postRenderDamagedBlocks();

View File

@@ -6,8 +6,6 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GLX;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.Terminal;
@@ -17,16 +15,18 @@ import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import org.lwjgl.opengl.GL11;
public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
{
@Override
public void render( TileMonitor tileEntity, double posX, double posY, double posZ, float f, int i )
@@ -64,9 +64,9 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
posZ += originPos.getZ() - monitorPos.getZ();
// Determine orientation
Direction dir = origin.getDirection();
Direction front = origin.getFront();
float yaw = dir.asRotation();
EnumFacing dir = origin.getDirection();
EnumFacing front = origin.getFront();
float yaw = dir.getHorizontalAngle();
float pitch = DirectionUtil.toPitchAngle( front );
GlStateManager.pushMatrix();
@@ -85,16 +85,16 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
// Get renderers
MinecraftClient mc = MinecraftClient.getInstance();
Minecraft mc = Minecraft.getInstance();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBufferBuilder();
BufferBuilder renderer = tessellator.getBuffer();
// Get terminal
boolean redraw = originTerminal.pollTerminalChanged();
// Draw the contents
GlStateManager.depthMask( false );
GLX.glMultiTexCoord2f( GLX.GL_TEXTURE1, 0xFFFF, 0xFFFF );
OpenGlHelper.glMultiTexCoord2f( OpenGlHelper.GL_TEXTURE1, 0xFFFF, 0xFFFF );
GlStateManager.disableLighting();
mc.gameRenderer.disableLightmap();
try
@@ -171,7 +171,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
}
}
GlStateManager.callList( originTerminal.renderDisplayLists[0] );
GlStateManager.clearCurrentColor();
GlStateManager.resetColor();
// Draw text
fontRenderer.bindFont();
@@ -199,7 +199,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
}
}
GlStateManager.callList( originTerminal.renderDisplayLists[1] );
GlStateManager.clearCurrentColor();
GlStateManager.resetColor();
// Draw cursor
fontRenderer.bindFont();
@@ -233,7 +233,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
if( FrameInfo.getGlobalCursorBlink() )
{
GlStateManager.callList( originTerminal.renderDisplayLists[2] );
GlStateManager.clearCurrentColor();
GlStateManager.resetColor();
}
}
finally
@@ -251,11 +251,11 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
final float g = colour.getG();
final float b = colour.getB();
renderer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION_UV_COLOR );
renderer.vertex( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).texture( 0.0, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).texture( 0.0, 1.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).texture( 1.0, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).texture( 1.0, 1.0 ).color( r, g, b, 1.0f ).next();
renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR );
renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 0.0, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 1.0, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 1.0, 1.0 ).color( r, g, b, 1.0f ).endVertex();
tessellator.draw();
}
}
@@ -271,11 +271,11 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
try
{
mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND );
renderer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION );
renderer.vertex( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.vertex( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION );
renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
tessellator.draw();
}
finally

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.computer.core.ComputerFamily;
@@ -14,37 +13,39 @@ import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelManager;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.pipeline.LightUtil;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import javax.vecmath.Matrix4f;
import java.nio.FloatBuffer;
import java.util.List;
import java.util.Random;
public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
public class TileEntityTurtleRenderer extends TileEntityRenderer<TileTurtle>
{
private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" );
private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" );
private static final ModelIdentifier COLOUR_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_colour", "inventory" );
private static final ModelIdentifier ELF_OVERLAY_MODEL = new ModelIdentifier( "computercraft:turtle_elf_overlay", "inventory" );
private static final FloatBuffer matrixBuf = BufferUtils.createFloatBuffer( 16 );
private static final ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_normal", "inventory" );
private static final ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_advanced", "inventory" );
private static final ModelResourceLocation COLOUR_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_colour", "inventory" );
private static final ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" );
@Override
public void render( TileTurtle tileEntity, double posX, double posY, double posZ, float partialTicks, int breaking )
@@ -52,7 +53,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
if( tileEntity != null ) renderTurtleAt( tileEntity, posX, posY, posZ, partialTicks );
}
public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured )
public static ModelResourceLocation getTurtleModel( ComputerFamily family, boolean coloured )
{
switch( family )
{
@@ -64,11 +65,11 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
}
}
public static ModelIdentifier getTurtleOverlayModel( Identifier overlay, boolean christmas )
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
{
if( overlay != null )
{
return new ModelIdentifier( overlay, "inventory" );
return new ModelResourceLocation( overlay, "inventory" );
}
else if( christmas )
{
@@ -84,21 +85,21 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
{
// Render the label
String label = turtle.createProxy().getLabel();
if( label != null && renderManager.hitResult != null && renderManager.hitResult instanceof BlockHitResult && turtle.getPos().equals( ((BlockHitResult) renderManager.hitResult).getBlockPos() ) )
if( label != null && rendererDispatcher.cameraHitResult != null && turtle.getPos().equals( rendererDispatcher.cameraHitResult.getBlockPos() ) )
{
disableLightmap( true );
GameRenderer.renderFloatingText(
setLightmapDisabled( true );
GameRenderer.drawNameplate(
getFontRenderer(), label,
(float) posX + 0.5F, (float) posY + 1.2F, (float) posZ + 0.5F, 0,
renderManager.cameraEntity.getYaw(), renderManager.cameraEntity.getPitch(), false
rendererDispatcher.entityYaw, rendererDispatcher.entityPitch, false, false
);
disableLightmap( false );
setLightmapDisabled( false );
}
GlStateManager.pushMatrix();
try
{
BlockState state = turtle.getCachedState();
IBlockState state = turtle.getBlockState();
// Setup the transform
Vec3d offset = turtle.getRenderOffset( partialTicks );
float yaw = turtle.getRenderYaw( partialTicks );
@@ -110,18 +111,18 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
{
// Flip the model and swap the cull face as winding order will have changed.
GlStateManager.scalef( 1.0f, -1.0f, 1.0f );
GlStateManager.cullFace( GlStateManager.FaceSides.FRONT );
GlStateManager.cullFace( GlStateManager.CullFace.FRONT );
}
GlStateManager.translatef( -0.5f, -0.5f, -0.5f );
// Render the turtle
int colour = turtle.getColour();
ComputerFamily family = turtle.getFamily();
Identifier overlay = turtle.getOverlay();
ResourceLocation overlay = turtle.getOverlay();
renderModel( state, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
// Render the overlay
ModelIdentifier overlayModel = getTurtleOverlayModel(
ModelResourceLocation overlayModel = getTurtleOverlayModel(
overlay,
HolidayUtil.getCurrentHoliday() == Holiday.Christmas
);
@@ -148,11 +149,11 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
finally
{
GlStateManager.popMatrix();
GlStateManager.cullFace( GlStateManager.FaceSides.BACK );
GlStateManager.cullFace( GlStateManager.CullFace.BACK );
}
}
private void renderUpgrade( BlockState state, TileTurtle turtle, TurtleSide side, float f )
private void renderUpgrade( IBlockState state, TileTurtle turtle, TurtleSide side, float f )
{
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
if( upgrade != null )
@@ -165,21 +166,12 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
GlStateManager.rotatef( -toolAngle, 1.0f, 0.0f, 0.0f );
GlStateManager.translatef( 0.0f, -0.5f, -0.5f );
Pair<BakedModel, Matrix4f> pair = upgrade.getModel( turtle.getAccess(), side );
Pair<IBakedModel, Matrix4f> pair = upgrade.getModel( turtle.getAccess(), side );
if( pair != null )
{
if( pair.getRight() != null )
{
matrixBuf.clear();
float[] t = new float[4];
for( int i = 0; i < 4; i++ )
{
pair.getRight().getColumn( i, t );
matrixBuf.put( t );
}
matrixBuf.flip();
GlStateManager.multMatrix( matrixBuf );
ForgeHooksClient.multiplyCurrentGlMatrix( pair.getRight() );
}
if( pair.getLeft() != null )
{
@@ -194,43 +186,48 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
}
}
private void renderModel( BlockState state, ModelIdentifier modelLocation, int[] tints )
private void renderModel( IBlockState state, ModelResourceLocation modelLocation, int[] tints )
{
MinecraftClient mc = MinecraftClient.getInstance();
BakedModelManager modelManager = mc.getItemRenderer().getModels().getModelManager();
Minecraft mc = Minecraft.getInstance();
ModelManager modelManager = mc.getItemRenderer().getItemModelMesher().getModelManager();
renderModel( state, modelManager.getModel( modelLocation ), tints );
}
private void renderModel( BlockState state, BakedModel model, int[] tints )
private void renderModel( IBlockState state, IBakedModel model, int[] tints )
{
Random random = new Random( 0 );
Tessellator tessellator = Tessellator.getInstance();
renderManager.textureManager.bindTexture( SpriteAtlasTexture.BLOCK_ATLAS_TEX );
renderQuads( tessellator, model.getQuads( state, null, random ), tints );
for( Direction facing : DirectionUtil.FACINGS )
rendererDispatcher.textureManager.bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE );
renderQuads( tessellator, model.getQuads( state, null, random, EmptyModelData.INSTANCE ), tints );
for( EnumFacing facing : DirectionUtil.FACINGS )
{
renderQuads( tessellator, model.getQuads( state, facing, random ), tints );
renderQuads( tessellator, model.getQuads( state, facing, random, EmptyModelData.INSTANCE ), tints );
}
}
private static void renderQuads( Tessellator tessellator, List<BakedQuad> quads, int[] tints )
{
BufferBuilder buffer = tessellator.getBufferBuilder();
VertexFormat format = VertexFormats.POSITION_COLOR_UV_NORMAL;
BufferBuilder buffer = tessellator.getBuffer();
VertexFormat format = DefaultVertexFormats.ITEM;
buffer.begin( GL11.GL_QUADS, format );
for( BakedQuad quad : quads )
{
int colour = 0xFFFFFFFF;
if( quad.hasColor() && tints != null )
VertexFormat quadFormat = quad.getFormat();
if( quadFormat != format )
{
int index = quad.getColorIndex();
tessellator.draw();
format = quadFormat;
buffer.begin( GL11.GL_QUADS, format );
}
int colour = 0xFFFFFFFF;
if( quad.hasTintIndex() && tints != null )
{
int index = quad.getTintIndex();
if( index >= 0 && index < tints.length ) colour = tints[index] | 0xFF000000;
}
buffer.putVertexData( quad.getVertexData() );
buffer.setQuadColor( colour );
Vec3i normal = quad.getFace().getVector();
buffer.postNormal( normal.getX(), normal.getY(), normal.getZ() );
LightUtil.renderQuadColor( buffer, quad, colour );
}
tessellator.draw();
}

View File

@@ -7,12 +7,14 @@
package dan200.computercraft.client.render;
import dan200.computercraft.ComputerCraft;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.IUnbakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.common.model.IModelState;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -22,11 +24,11 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public final class TurtleModelLoader
public final class TurtleModelLoader implements ICustomModelLoader
{
private static final Identifier NORMAL_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_normal" );
private static final Identifier ADVANCED_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_advanced" );
private static final Identifier COLOUR_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_colour" );
private static final ResourceLocation NORMAL_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_normal" );
private static final ResourceLocation ADVANCED_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_advanced" );
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_colour" );
public static final TurtleModelLoader INSTANCE = new TurtleModelLoader();
@@ -34,14 +36,21 @@ public final class TurtleModelLoader
{
}
public boolean accepts( @Nonnull Identifier name )
@Override
public void onResourceManagerReload( @Nonnull IResourceManager manager )
{
}
@Override
public boolean accepts( @Nonnull ResourceLocation name )
{
return name.getNamespace().equals( ComputerCraft.MOD_ID )
&& (name.getPath().equals( "item/turtle_normal" ) || name.getPath().equals( "item/turtle_advanced" ));
}
@Nonnull
public UnbakedModel loadModel( @Nonnull Identifier name )
@Override
public IUnbakedModel loadModel( @Nonnull ResourceLocation name )
{
if( name.getNamespace().equals( ComputerCraft.MOD_ID ) )
{
@@ -57,35 +66,38 @@ public final class TurtleModelLoader
throw new IllegalStateException( "Loader does not accept " + name );
}
private static final class TurtleModel implements UnbakedModel
private static final class TurtleModel implements IUnbakedModel
{
private final Identifier family;
private final ResourceLocation family;
private TurtleModel( Identifier family ) {this.family = family;}
private TurtleModel( ResourceLocation family )
{
this.family = family;
}
@Nonnull
@Override
public Collection<Identifier> getModelDependencies()
public Collection<ResourceLocation> getDependencies()
{
return Arrays.asList( family, COLOUR_TURTLE_MODEL );
}
@Nonnull
@Override
public Collection<Identifier> getTextureDependencies( @Nonnull Function<Identifier, UnbakedModel> modelGetter, @Nonnull Set<String> missingTextureErrors )
public Collection<ResourceLocation> getTextures( @Nonnull Function<ResourceLocation, IUnbakedModel> modelGetter, @Nonnull Set<String> missingTextureErrors )
{
return getModelDependencies().stream()
.flatMap( x -> modelGetter.apply( x ).getTextureDependencies( modelGetter, missingTextureErrors ).stream() )
return getDependencies().stream()
.flatMap( x -> modelGetter.apply( x ).getTextures( modelGetter, missingTextureErrors ).stream() )
.collect( Collectors.toSet() );
}
@Nullable
@Override
public BakedModel bake( @Nonnull ModelLoader loader, @Nonnull Function<Identifier, Sprite> spriteGetter, @Nonnull ModelBakeSettings state )
public IBakedModel bake( @Nonnull Function<ResourceLocation, IUnbakedModel> modelGetter, @Nonnull Function<ResourceLocation, TextureAtlasSprite> spriteGetter, @Nonnull IModelState state, boolean uvlock, @Nonnull VertexFormat format )
{
return new TurtleSmartItemModel(
loader.getOrLoadModel( family ).bake( loader, spriteGetter, state ),
loader.getOrLoadModel( COLOUR_TURTLE_MODEL ).bake( loader, spriteGetter, state )
modelGetter.apply( family ).bake( modelGetter, spriteGetter, state, uvlock, format ),
modelGetter.apply( COLOUR_TURTLE_MODEL ).bake( modelGetter, spriteGetter, state, uvlock, format )
);
}
}

View File

@@ -6,31 +6,32 @@
package dan200.computercraft.client.render;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelItemPropertyOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraft.block.state.IBlockState;
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.TextureAtlasSprite;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import javax.annotation.Nonnull;
import javax.vecmath.Matrix4f;
import java.util.*;
public class TurtleMultiModel implements BakedModel
public class TurtleMultiModel implements IBakedModel
{
private final BakedModel m_baseModel;
private final BakedModel m_overlayModel;
private final IBakedModel m_baseModel;
private final IBakedModel m_overlayModel;
private final Matrix4f m_generalTransform;
private final BakedModel m_leftUpgradeModel;
private final IBakedModel m_leftUpgradeModel;
private final Matrix4f m_leftUpgradeTransform;
private final BakedModel m_rightUpgradeModel;
private final IBakedModel m_rightUpgradeModel;
private final Matrix4f m_rightUpgradeTransform;
private List<BakedQuad> m_generalQuads = null;
private Map<Direction, List<BakedQuad>> m_faceQuads = new EnumMap<>( Direction.class );
private Map<EnumFacing, List<BakedQuad>> m_faceQuads = new EnumMap<>( EnumFacing.class );
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Matrix4f generalTransform, BakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, BakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, Matrix4f generalTransform, IBakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, IBakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
{
// Get the models
m_baseModel = baseModel;
@@ -44,7 +45,15 @@ public class TurtleMultiModel implements BakedModel
@Nonnull
@Override
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand )
@Deprecated
public List<BakedQuad> getQuads( IBlockState state, EnumFacing side, @Nonnull Random rand )
{
return getQuads( state, side, rand, EmptyModelData.INSTANCE );
}
@Nonnull
@Override
public List<BakedQuad> getQuads( IBlockState state, EnumFacing side, @Nonnull Random rand, @Nonnull IModelData data )
{
if( side != null )
{
@@ -58,13 +67,13 @@ public class TurtleMultiModel implements BakedModel
}
}
private List<BakedQuad> buildQuads( BlockState state, Direction side, Random rand )
private List<BakedQuad> buildQuads( IBlockState state, EnumFacing side, Random rand )
{
ArrayList<BakedQuad> quads = new ArrayList<>();
ModelTransformer.transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand ), m_generalTransform );
ModelTransformer.transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform );
if( m_overlayModel != null )
{
ModelTransformer.transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand ), m_generalTransform );
ModelTransformer.transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform );
}
if( m_leftUpgradeModel != null )
{
@@ -74,7 +83,7 @@ public class TurtleMultiModel implements BakedModel
upgradeTransform = new Matrix4f( m_generalTransform );
upgradeTransform.mul( m_leftUpgradeTransform );
}
ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand ), upgradeTransform );
ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
}
if( m_rightUpgradeModel != null )
{
@@ -84,45 +93,49 @@ public class TurtleMultiModel implements BakedModel
upgradeTransform = new Matrix4f( m_generalTransform );
upgradeTransform.mul( m_rightUpgradeTransform );
}
ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand ), upgradeTransform );
ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
}
quads.trimToSize();
return quads;
}
@Override
public boolean useAmbientOcclusion()
public boolean isAmbientOcclusion()
{
return m_baseModel.useAmbientOcclusion();
return m_baseModel.isAmbientOcclusion();
}
@Override
public boolean hasDepthInGui()
public boolean isGui3d()
{
return m_baseModel.hasDepthInGui();
return m_baseModel.isGui3d();
}
@Override
public boolean isBuiltin()
public boolean isBuiltInRenderer()
{
return m_baseModel.isBuiltin();
return m_baseModel.isBuiltInRenderer();
}
@Nonnull
@Override
public Sprite getSprite()
public TextureAtlasSprite getParticleTexture()
{
return m_baseModel.getSprite();
return m_baseModel.getParticleTexture();
}
@Nonnull
@Override
public ModelTransformation getTransformation()
@Deprecated
public net.minecraft.client.renderer.model.ItemCameraTransforms getItemCameraTransforms()
{
return m_baseModel.getTransformation();
return m_baseModel.getItemCameraTransforms();
}
@Nonnull
@Override
public ModelItemPropertyOverrideList getItemPropertyOverrides()
public ItemOverrideList getOverrides()
{
return ModelItemPropertyOverrideList.EMPTY;
return ItemOverrideList.EMPTY;
}
}

View File

@@ -12,31 +12,26 @@ import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelItemPropertyOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.entity.LivingEntity;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.model.data.IModelData;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
public class TurtleSmartItemModel implements BakedModel
public class TurtleSmartItemModel implements IBakedModel
{
private static final Matrix4f s_identity, s_flip;
@@ -56,11 +51,11 @@ public class TurtleSmartItemModel implements BakedModel
final boolean m_colour;
final ITurtleUpgrade m_leftUpgrade;
final ITurtleUpgrade m_rightUpgrade;
final Identifier m_overlay;
final ResourceLocation m_overlay;
final boolean m_christmas;
final boolean m_flip;
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas, boolean flip )
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
{
m_colour = colour;
m_leftUpgrade = leftUpgrade;
@@ -100,35 +95,35 @@ public class TurtleSmartItemModel implements BakedModel
}
}
private final BakedModel familyModel;
private final BakedModel colourModel;
private final IBakedModel familyModel;
private final IBakedModel colourModel;
private HashMap<TurtleModelCombination, BakedModel> m_cachedModels;
private ModelItemPropertyOverrideList m_overrides;
private HashMap<TurtleModelCombination, IBakedModel> m_cachedModels;
private ItemOverrideList m_overrides;
public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel )
public TurtleSmartItemModel( IBakedModel familyModel, IBakedModel colourModel )
{
this.familyModel = familyModel;
this.colourModel = colourModel;
m_cachedModels = new HashMap<>();
m_overrides = new ModelItemPropertyOverrideList( null, null, null, Collections.emptyList() )
m_overrides = new ItemOverrideList()
{
@Nonnull
@Override
public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable LivingEntity entity )
public IBakedModel getModelWithOverrides( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.Left );
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
Identifier overlay = turtle.getOverlay( stack );
ResourceLocation overlay = turtle.getOverlay( stack );
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas;
String label = turtle.getLabel( stack );
boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
BakedModel model = m_cachedModels.get( combo );
IBakedModel model = m_cachedModels.get( combo );
if( model == null ) m_cachedModels.put( combo, model = buildModel( combo ) );
return model;
}
@@ -137,22 +132,22 @@ public class TurtleSmartItemModel implements BakedModel
@Nonnull
@Override
public ModelItemPropertyOverrideList getItemPropertyOverrides()
public ItemOverrideList getOverrides()
{
return m_overrides;
}
private BakedModel buildModel( TurtleModelCombination combo )
private IBakedModel buildModel( TurtleModelCombination combo )
{
MinecraftClient mc = MinecraftClient.getInstance();
BakedModelManager modelManager = mc.getItemRenderer().getModels().getModelManager();
ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas );
Minecraft mc = Minecraft.getInstance();
ModelManager modelManager = mc.getItemRenderer().getItemModelMesher().getModelManager();
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas );
BakedModel baseModel = combo.m_colour ? colourModel : familyModel;
BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
IBakedModel baseModel = combo.m_colour ? colourModel : familyModel;
IBakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
Matrix4f transform = combo.m_flip ? s_flip : s_identity;
Pair<BakedModel, Matrix4f> leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
Pair<BakedModel, Matrix4f> rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null;
Pair<IBakedModel, Matrix4f> leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
Pair<IBakedModel, Matrix4f> rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null;
if( leftModel != null && rightModel != null )
{
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel.getLeft(), leftModel.getRight(), rightModel.getLeft(), rightModel.getRight() );
@@ -174,38 +169,50 @@ public class TurtleSmartItemModel implements BakedModel
@Nonnull
@Override
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction facing, Random rand )
public List<BakedQuad> getQuads( IBlockState state, EnumFacing facing, @Nonnull Random rand )
{
return familyModel.getQuads( state, facing, rand );
}
@Nonnull
@Override
public boolean useAmbientOcclusion()
@Deprecated
public List<BakedQuad> getQuads( IBlockState state, EnumFacing facing, @Nonnull Random rand, @Nonnull IModelData data )
{
return familyModel.useAmbientOcclusion();
return familyModel.getQuads( state, facing, rand, data );
}
@Override
public boolean hasDepthInGui()
public boolean isAmbientOcclusion()
{
return familyModel.hasDepthInGui();
return familyModel.isAmbientOcclusion();
}
@Override
public boolean isBuiltin()
public boolean isGui3d()
{
return familyModel.isBuiltin();
return familyModel.isGui3d();
}
@Override
public Sprite getSprite()
public boolean isBuiltInRenderer()
{
return null;
return familyModel.isBuiltInRenderer();
}
@Nonnull
@Override
public ModelTransformation getTransformation()
public TextureAtlasSprite getParticleTexture()
{
return familyModel.getTransformation();
return familyModel.getParticleTexture();
}
@Nonnull
@Override
@Deprecated
public ItemCameraTransforms getItemCameraTransforms()
{
return familyModel.getItemCameraTransforms();
}
}

View File

@@ -43,9 +43,7 @@ public class FSAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"fs"
};
return new String[] { "fs" };
}
@Override

View File

@@ -42,9 +42,7 @@ public class HTTPAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"http"
};
return new String[] { "http" };
}
@Override
@@ -83,6 +81,7 @@ public class HTTPAPI implements ILuaAPI
}
@Override
@SuppressWarnings( "resource" )
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
{
switch( method )
@@ -95,7 +94,7 @@ public class HTTPAPI implements ILuaAPI
if( args.length >= 1 && args[0] instanceof Map )
{
Map<?, ?> options = (Map) args[0];
Map<?, ?> options = (Map<?, ?>) args[0];
address = getStringField( options, "url" );
postString = optStringField( options, "body", null );
headerTable = optTableField( options, "headers", Collections.emptyMap() );
@@ -135,7 +134,6 @@ public class HTTPAPI implements ILuaAPI
try
{
URI uri = HttpRequest.checkUri( address );
HttpRequest request = new HttpRequest( requests, m_apiEnvironment, address, postString, headers, binary, redirect );
long requestBody = request.body().readableBytes() + HttpRequest.getHeaderSize( headers );

View File

@@ -10,6 +10,7 @@ package dan200.computercraft.core.apis;
* This exists purely to ensure binary compatibility.
*
* @see dan200.computercraft.api.lua.ILuaAPI
* @deprecated Use the version in the public API. Only exists for compatibility with CCEmuX.
*/
@Deprecated
public interface ILuaAPI extends dan200.computercraft.api.lua.ILuaAPI

View File

@@ -36,9 +36,9 @@ public class OSAPI implements ILuaAPI
private static class Timer
{
public int m_ticksLeft;
int m_ticksLeft;
public Timer( int ticksLeft )
Timer( int ticksLeft )
{
m_ticksLeft = ticksLeft;
}
@@ -46,10 +46,10 @@ public class OSAPI implements ILuaAPI
private static class Alarm implements Comparable<Alarm>
{
public final double m_time;
public final int m_day;
final double m_time;
final int m_day;
public Alarm( double time, int day )
Alarm( double time, int day )
{
m_time = time;
m_day = day;
@@ -78,9 +78,7 @@ public class OSAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"os"
};
return new String[] { "os" };
}
@Override
@@ -385,9 +383,7 @@ public class OSAPI implements ILuaAPI
// Get in-game epoch
synchronized( m_alarms )
{
return new Object[] {
m_day * 86400000 + (int) (m_time * 3600000.0f)
};
return new Object[] { m_day * 86400000 + (int) (m_time * 3600000.0f) };
}
default:
throw new LuaException( "Unsupported operation" );
@@ -401,7 +397,6 @@ public class OSAPI implements ILuaAPI
Instant instant = Instant.ofEpochSecond( time );
ZonedDateTime date;
ZoneOffset offset;
boolean isDst;
if( format.startsWith( "!" ) )
{
offset = ZoneOffset.UTC;

View File

@@ -36,7 +36,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
private Map<String, Integer> m_methodMap;
private boolean m_attached;
public PeripheralWrapper( IPeripheral peripheral, String side )
PeripheralWrapper( IPeripheral peripheral, String side )
{
super( m_environment );
m_side = side;
@@ -282,9 +282,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
@Override
public String[] getNames()
{
return new String[] {
"peripheral"
};
return new String[] { "peripheral" };
}
@Override
@@ -326,7 +324,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
"isPresent",
"getType",
"getMethods",
"call"
"call",
};
}
@@ -356,7 +354,6 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
ComputerSide side = ComputerSide.valueOfInsensitive( getString( args, 0 ) );
if( side != null )
{
String type = null;
synchronized( m_peripherals )
{
PeripheralWrapper p = m_peripherals[side.ordinal()];

View File

@@ -29,9 +29,7 @@ public class RedstoneAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"rs", "redstone"
};
return new String[] { "rs", "redstone" };
}
@Nonnull

View File

@@ -33,9 +33,7 @@ public class TermAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"term"
};
return new String[] { "term" };
}
@Nonnull
@@ -89,9 +87,7 @@ public class TermAPI implements ILuaAPI
public static Object[] encodeColour( int colour ) throws LuaException
{
return new Object[] {
1 << colour
};
return new Object[] { 1 << colour };
}
public static void setColour( Terminal terminal, int colour, double r, double g, double b )

View File

@@ -212,6 +212,7 @@ public class BinaryReadableHandle extends HandleGeneric
}
}
case 3: // close
checkOpen();
close();
return null;
case 4: // seek

View File

@@ -95,6 +95,7 @@ public class BinaryWritableHandle extends HandleGeneric
return null;
}
case 2: // close
checkOpen();
close();
return null;
case 3: // seek

View File

@@ -152,6 +152,7 @@ public class EncodedReadableHandle extends HandleGeneric
return null;
}
case 3: // close
checkOpen();
close();
return null;
default:

View File

@@ -93,6 +93,7 @@ public class EncodedWritableHandle extends HandleGeneric
return null;
}
case 3: // close
checkOpen();
close();
return null;
default:

View File

@@ -37,8 +37,13 @@ public abstract class HandleGeneric implements ILuaObject
protected final void close()
{
m_open = false;
IoUtil.closeQuietly( m_closable );
m_closable = null;
Closeable closeable = m_closable;
if( closeable != null )
{
IoUtil.closeQuietly( closeable );
m_closable = null;
}
}
/**

View File

@@ -72,7 +72,8 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
*/
protected void dispose()
{
@SuppressWarnings( "unchecked" ) T thisT = (T) this;
@SuppressWarnings( "unchecked" )
T thisT = (T) this;
limiter.release( thisT );
}
@@ -95,7 +96,8 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
public boolean queue( Consumer<T> task )
{
@SuppressWarnings( "unchecked" ) T thisT = (T) this;
@SuppressWarnings( "unchecked" )
T thisT = (T) this;
return limiter.queue( thisT, () -> task.accept( thisT ) );
}

View File

@@ -30,7 +30,10 @@ public enum ComputerSide
private final String name;
ComputerSide( String name ) {this.name = name;}
ComputerSide( String name )
{
this.name = name;
}
@Nonnull
public static ComputerSide valueOf( int side )

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IWorkMonitor;
import dan200.computercraft.core.tracking.Tracking;
import dan200.computercraft.shared.turtle.core.TurtleBrain;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.tileentity.TileEntity;
import javax.annotation.Nonnull;
import java.util.ArrayDeque;
@@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit;
* this tick. At the beginning of the tick, we execute as many {@link MainThread} tasks as possible, until our
* time-frame or the global time frame has expired.
*
* Then, when other objects (such as {@link BlockEntity}) are ticked, we update how much time we've used using
* Then, when other objects (such as {@link TileEntity}) are ticked, we update how much time we've used using
* {@link IWorkMonitor#trackWork(long, TimeUnit)}.
*
* Now, if anywhere during this period, we use more than our allocated time slice, the executor is marked as

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.core.filesystem;
import dan200.computercraft.api.filesystem.FileOperationException;
import dan200.computercraft.api.filesystem.IMount;
import javax.annotation.Nonnull;
@@ -95,7 +96,7 @@ public class ComboMount implements IMount
}
else
{
throw new IOException( "/" + path + ": Not a directory" );
throw new FileOperationException( path, "Not a directory" );
}
}
@@ -110,7 +111,7 @@ public class ComboMount implements IMount
return part.getSize( path );
}
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
@Nonnull
@@ -126,7 +127,7 @@ public class ComboMount implements IMount
return part.openForRead( path );
}
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
@Nonnull
@@ -141,6 +142,6 @@ public class ComboMount implements IMount
return part.openChannelForRead( path );
}
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
}

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.core.filesystem;
import dan200.computercraft.api.filesystem.FileOperationException;
import dan200.computercraft.api.filesystem.IMount;
import javax.annotation.Nonnull;
@@ -44,7 +45,7 @@ public class EmptyMount implements IMount
@Deprecated
public InputStream openForRead( @Nonnull String path ) throws IOException
{
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
@Nonnull
@@ -52,6 +53,6 @@ public class EmptyMount implements IMount
@Deprecated
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
{
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
}

View File

@@ -7,6 +7,7 @@
package dan200.computercraft.core.filesystem;
import com.google.common.collect.Sets;
import dan200.computercraft.api.filesystem.FileOperationException;
import dan200.computercraft.api.filesystem.IWritableMount;
import javax.annotation.Nonnull;
@@ -167,12 +168,12 @@ public class FileMount implements IWritableMount
{
if( !created() )
{
if( !path.isEmpty() ) throw new IOException( "/" + path + ": Not a directory" );
if( !path.isEmpty() ) throw new FileOperationException( path, "Not a directory" );
return;
}
File file = getRealPath( path );
if( !file.exists() || !file.isDirectory() ) throw new IOException( "/" + path + ": Not a directory" );
if( !file.exists() || !file.isDirectory() ) throw new FileOperationException( path, "Not a directory" );
String[] paths = file.list();
for( String subPath : paths )
@@ -194,7 +195,7 @@ public class FileMount implements IWritableMount
if( file.exists() ) return file.isDirectory() ? 0 : file.length();
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
@Nonnull
@@ -208,7 +209,7 @@ public class FileMount implements IWritableMount
if( file.exists() && !file.isDirectory() ) return new FileInputStream( file );
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
@Nonnull
@@ -221,7 +222,7 @@ public class FileMount implements IWritableMount
if( file.exists() && !file.isDirectory() ) return FileChannel.open( file.toPath(), READ_OPTIONS );
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
// IWritableMount implementation
@@ -233,7 +234,7 @@ public class FileMount implements IWritableMount
File file = getRealPath( path );
if( file.exists() )
{
if( !file.isDirectory() ) throw new IOException( "/" + path + ": File exists" );
if( !file.isDirectory() ) throw new FileOperationException( path, "File exists" );
return;
}
@@ -247,7 +248,7 @@ public class FileMount implements IWritableMount
if( getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE )
{
throw new IOException( "/" + path + ": Out of space" );
throw new FileOperationException( path, "Out of space" );
}
if( file.mkdirs() )
@@ -256,14 +257,14 @@ public class FileMount implements IWritableMount
}
else
{
throw new IOException( "/" + path + ": Access denied" );
throw new FileOperationException( path, "Access denied" );
}
}
@Override
public void delete( @Nonnull String path ) throws IOException
{
if( path.isEmpty() ) throw new IOException( "/" + path + ": Access denied" );
if( path.isEmpty() ) throw new FileOperationException( path, "Access denied" );
if( created() )
{
@@ -319,7 +320,7 @@ public class FileMount implements IWritableMount
{
create();
File file = getRealPath( path );
if( file.exists() && file.isDirectory() ) throw new IOException( "/" + path + ": Cannot write to directory" );
if( file.exists() && file.isDirectory() ) throw new FileOperationException( path, "Cannot write to directory" );
if( file.exists() )
{
@@ -327,7 +328,7 @@ public class FileMount implements IWritableMount
}
else if( getRemainingSpace() < MINIMUM_FILE_SIZE )
{
throw new IOException( "/" + path + ": Out of space" );
throw new FileOperationException( path, "Out of space" );
}
m_usedSpace += MINIMUM_FILE_SIZE;
@@ -340,12 +341,12 @@ public class FileMount implements IWritableMount
{
if( !created() )
{
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
File file = getRealPath( path );
if( !file.exists() ) throw new IOException( "/" + path + ": No such file" );
if( file.isDirectory() ) throw new IOException( "/" + path + ": Cannot write to directory" );
if( !file.exists() ) throw new FileOperationException( path, "No such file" );
if( file.isDirectory() ) throw new FileOperationException( path, "Cannot write to directory" );
// Allowing seeking when appending is not recommended, so we use a separate channel.
return new WritableCountingChannel(

View File

@@ -8,6 +8,7 @@ package dan200.computercraft.core.filesystem;
import com.google.common.io.ByteStreams;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.FileOperationException;
import dan200.computercraft.api.filesystem.IFileSystem;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
@@ -45,7 +46,7 @@ public class FileSystem
m_writableMount = null;
}
public MountWrapper( String label, String location, IWritableMount mount )
MountWrapper( String label, String location, IWritableMount mount )
{
this( label, location, (IMount) mount );
m_writableMount = mount;
@@ -107,7 +108,7 @@ public class FileSystem
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
@@ -122,12 +123,12 @@ public class FileSystem
}
else
{
throw new FileSystemException( "/" + path + ": Not a directory" );
throw localExceptionOf( path, "Not a directory" );
}
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
@@ -149,12 +150,12 @@ public class FileSystem
}
else
{
throw new FileSystemException( "/" + path + ": No such file" );
throw localExceptionOf( path, "No such file" );
}
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
@@ -169,12 +170,12 @@ public class FileSystem
}
else
{
throw new FileSystemException( "/" + path + ": No such file" );
throw localExceptionOf( path, "No such file" );
}
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
@@ -182,19 +183,14 @@ public class FileSystem
public void makeDirectory( String path ) throws FileSystemException
{
if( m_writableMount == null )
{
throw new FileSystemException( "/" + path + ": Access denied" );
}
if( m_writableMount == null ) throw exceptionOf( path, "Access denied" );
path = toLocal( path );
try
{
path = toLocal( path );
if( m_mount.exists( path ) )
{
if( !m_mount.isDirectory( path ) )
{
throw new FileSystemException( "/" + path + ": File exists" );
}
if( !m_mount.isDirectory( path ) ) throw localExceptionOf( path, "File exists" );
}
else
{
@@ -203,16 +199,14 @@ public class FileSystem
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
public void delete( String path ) throws FileSystemException
{
if( m_writableMount == null )
{
throw new FileSystemException( "/" + path + ": Access denied" );
}
if( m_writableMount == null ) throw exceptionOf( path, "Access denied" );
try
{
path = toLocal( path );
@@ -227,22 +221,20 @@ public class FileSystem
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
public WritableByteChannel openForWrite( String path ) throws FileSystemException
{
if( m_writableMount == null )
{
throw new FileSystemException( "/" + path + ": Access denied" );
}
if( m_writableMount == null ) throw exceptionOf( path, "Access denied" );
path = toLocal( path );
try
{
path = toLocal( path );
if( m_mount.exists( path ) && m_mount.isDirectory( path ) )
{
throw new FileSystemException( "/" + path + ": Cannot write to directory" );
throw localExceptionOf( path, "Cannot write to directory" );
}
else
{
@@ -263,19 +255,17 @@ public class FileSystem
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
public WritableByteChannel openForAppend( String path ) throws FileSystemException
{
if( m_writableMount == null )
{
throw new FileSystemException( "/" + path + ": Access denied" );
}
if( m_writableMount == null ) throw exceptionOf( path, "Access denied" );
path = toLocal( path );
try
{
path = toLocal( path );
if( !m_mount.exists( path ) )
{
if( !path.isEmpty() )
@@ -290,7 +280,7 @@ public class FileSystem
}
else if( m_mount.isDirectory( path ) )
{
throw new FileSystemException( "/" + path + ": Cannot write to directory" );
throw localExceptionOf( path, "Cannot write to directory" );
}
else
{
@@ -303,16 +293,36 @@ public class FileSystem
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( e );
}
}
// private members
private String toLocal( String path )
{
return FileSystem.toLocal( path, m_location );
}
private FileSystemException localExceptionOf( IOException e )
{
if( !m_location.isEmpty() && e instanceof FileOperationException )
{
FileOperationException ex = (FileOperationException) e;
if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() );
}
return new FileSystemException( e.getMessage() );
}
private FileSystemException localExceptionOf( String path, String message )
{
if( !m_location.isEmpty() ) path = path.isEmpty() ? m_location : m_location + "/" + path;
return exceptionOf( path, message );
}
private static FileSystemException exceptionOf( String path, String message )
{
return new FileSystemException( "/" + path + ": " + message );
}
}
private final FileSystemWrapperMount m_wrapper = new FileSystemWrapperMount( this );
@@ -769,7 +779,7 @@ public class FileSystem
// Clean the path or illegal characters.
final char[] specialChars = new char[] {
'"', ':', '<', '>', '?', '|' // Sorted by ascii value (important)
'"', ':', '<', '>', '?', '|', // Sorted by ascii value (important)
};
StringBuilder cleanName = new StringBuilder();

View File

@@ -9,6 +9,7 @@ package dan200.computercraft.core.filesystem;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.io.ByteStreams;
import dan200.computercraft.api.filesystem.FileOperationException;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
import dan200.computercraft.shared.util.IoUtil;
@@ -92,7 +93,7 @@ public class JarMount implements IMount
new MountReference( this );
// Read in all the entries
root = new FileEntry( "" );
root = new FileEntry();
Enumeration<? extends ZipEntry> zipEntries = zip.entries();
while( zipEntries.hasMoreElements() )
{
@@ -139,7 +140,7 @@ public class JarMount implements IMount
FileEntry nextEntry = lastEntry.children.get( part );
if( nextEntry == null || !nextEntry.isDirectory() )
{
lastEntry.children.put( part, nextEntry = new FileEntry( part ) );
lastEntry.children.put( part, nextEntry = new FileEntry() );
}
lastEntry = nextEntry;
@@ -166,7 +167,7 @@ public class JarMount implements IMount
public void list( @Nonnull String path, @Nonnull List<String> contents ) throws IOException
{
FileEntry file = get( path );
if( file == null || !file.isDirectory() ) throw new IOException( "/" + path + ": Not a directory" );
if( file == null || !file.isDirectory() ) throw new FileOperationException( path, "Not a directory" );
file.list( contents );
}
@@ -176,7 +177,7 @@ public class JarMount implements IMount
{
FileEntry file = get( path );
if( file != null ) return file.size;
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
@Nonnull
@@ -218,22 +219,15 @@ public class JarMount implements IMount
}
}
throw new IOException( "/" + path + ": No such file" );
throw new FileOperationException( path, "No such file" );
}
private static class FileEntry
{
final String name;
String path;
long size;
Map<String, FileEntry> children;
FileEntry( String name )
{
this.name = name;
}
void setup( ZipEntry entry )
{
path = entry.getName();

View File

@@ -11,12 +11,12 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.io.ByteStreams;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
import net.minecraft.resource.ReloadableResourceManager;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceReloadListener;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profiler;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResource;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.resource.IResourceType;
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -26,9 +26,8 @@ import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
public class ResourceMount implements IMount
{
@@ -58,12 +57,12 @@ public class ResourceMount implements IMount
private final String namespace;
private final String subPath;
private final ReloadableResourceManager manager;
private final IReloadableResourceManager manager;
@Nullable
private FileEntry root;
public ResourceMount( String namespace, String subPath, ReloadableResourceManager manager )
public ResourceMount( String namespace, String subPath, IReloadableResourceManager manager )
{
this.namespace = namespace;
this.subPath = subPath;
@@ -76,8 +75,8 @@ public class ResourceMount implements IMount
private void load()
{
boolean hasAny = false;
FileEntry newRoot = new FileEntry( new Identifier( namespace, subPath ) );
for( Identifier file : manager.findResources( subPath, s -> true ) )
FileEntry newRoot = new FileEntry( new ResourceLocation( namespace, subPath ) );
for( ResourceLocation file : manager.getAllResourceLocations( subPath, s -> true ) )
{
if( !file.getNamespace().equals( namespace ) ) continue;
@@ -120,7 +119,7 @@ public class ResourceMount implements IMount
FileEntry nextEntry = lastEntry.children.get( part );
if( nextEntry == null )
{
lastEntry.children.put( part, nextEntry = new FileEntry( new Identifier( namespace, subPath + "/" + path ) ) );
lastEntry.children.put( part, nextEntry = new FileEntry( new ResourceLocation( namespace, subPath + "/" + path ) ) );
}
lastEntry = nextEntry;
@@ -164,14 +163,14 @@ public class ResourceMount implements IMount
try
{
Resource resource = manager.getResource( file.identifier );
IResource resource = manager.getResource( file.identifier );
InputStream s = resource.getInputStream();
int total = 0, read = 0;
do
{
total += read;
read = s.read( TEMP_BUFFER );
} while( read > 0 );
} while ( read > 0 );
return file.size = total;
}
@@ -220,11 +219,11 @@ public class ResourceMount implements IMount
private static class FileEntry
{
final Identifier identifier;
final ResourceLocation identifier;
Map<String, FileEntry> children;
long size = -1;
FileEntry( Identifier identifier )
FileEntry( ResourceLocation identifier )
{
this.identifier = identifier;
}
@@ -241,37 +240,34 @@ public class ResourceMount implements IMount
}
/**
* A {@link ResourceReloadListener} which reloads any associated mounts.
* A {@link ISelectiveResourceReloadListener} which reloads any associated mounts.
*
* While people should really be keeping a permanent reference to this, some people construct it every
* method call, so let's make this as small as possible.
*/
static class Listener implements ResourceReloadListener
static class Listener implements ISelectiveResourceReloadListener
{
private static final Listener INSTANCE = new Listener();
private final Set<ResourceMount> mounts = Collections.newSetFromMap( new WeakHashMap<>() );
private final Set<ReloadableResourceManager> managers = Collections.newSetFromMap( new WeakHashMap<>() );
private final Set<IReloadableResourceManager> managers = Collections.newSetFromMap( new WeakHashMap<>() );
@Override
public CompletableFuture<Void> reload( Synchronizer synchronizer, ResourceManager resourceManager, Profiler profiler, Profiler profiler1, Executor executor, Executor executor1 )
public void onResourceManagerReload( @Nonnull IResourceManager manager )
{
return CompletableFuture.runAsync( () -> {
profiler.push( "Mount reloading" );
try
{
for( ResourceMount mount : mounts ) mount.load();
}
finally
{
profiler.pop();
}
}, executor );
// FIXME: Remove this. We need this patch in order to prevent trying to load ReloadRequirements.
onResourceManagerReload( manager, x -> true );
}
synchronized void add( ReloadableResourceManager manager, ResourceMount mount )
@Override
public synchronized void onResourceManagerReload( @Nonnull IResourceManager manager, @Nonnull Predicate<IResourceType> predicate )
{
if( managers.add( manager ) ) manager.registerListener( this );
for( ResourceMount mount : mounts ) mount.load();
}
synchronized void add( IReloadableResourceManager manager, ResourceMount mount )
{
if( managers.add( manager ) ) manager.addReloadListener( this );
mounts.add( mount );
}
}

View File

@@ -550,7 +550,7 @@ public class CobaltLuaMachine implements ILuaMachine
{
if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Error running task", t );
m_computer.queueEvent( "task_complete", new Object[] {
taskID, false, "Java Exception Thrown: " + t
taskID, false, "Java Exception Thrown: " + t,
} );
}
};

View File

@@ -7,7 +7,7 @@
package dan200.computercraft.core.terminal;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NBTTagCompound;
public class Terminal
{
@@ -334,7 +334,7 @@ public class Terminal
m_changed = false;
}
public synchronized CompoundTag writeToNBT( CompoundTag nbt )
public synchronized NBTTagCompound writeToNBT( NBTTagCompound nbt )
{
nbt.putInt( "term_cursorX", m_cursorX );
nbt.putInt( "term_cursorY", m_cursorY );
@@ -354,7 +354,7 @@ public class Terminal
return nbt;
}
public synchronized void readFromNBT( CompoundTag nbt )
public synchronized void readFromNBT( NBTTagCompound nbt )
{
m_cursorX = nbt.getInt( "term_cursorX" );
m_cursorY = nbt.getInt( "term_cursorY" );
@@ -365,17 +365,17 @@ public class Terminal
for( int n = 0; n < m_height; n++ )
{
m_text[n].fill( ' ' );
if( nbt.containsKey( "term_text_" + n ) )
if( nbt.contains( "term_text_" + n ) )
{
m_text[n].write( nbt.getString( "term_text_" + n ) );
}
m_textColour[n].fill( base16.charAt( m_cursorColour ) );
if( nbt.containsKey( "term_textColour_" + n ) )
if( nbt.contains( "term_textColour_" + n ) )
{
m_textColour[n].write( nbt.getString( "term_textColour_" + n ) );
}
m_backgroundColour[n].fill( base16.charAt( m_cursorBackgroundColour ) );
if( nbt.containsKey( "term_textBgColour_" + n ) )
if( nbt.contains( "term_textBgColour_" + n ) )
{
m_backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) );
}

View File

@@ -8,7 +8,7 @@ package dan200.computercraft.core.terminal;
public class TextBuffer
{
public char[] m_text;
private final char[] m_text;
public TextBuffer( char c, int length )
{

View File

@@ -9,8 +9,8 @@ package dan200.computercraft.shared;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -24,18 +24,18 @@ public final class BundledRedstone
private BundledRedstone() {}
public static void register( @Nonnull IBundledRedstoneProvider provider )
public static synchronized void register( @Nonnull IBundledRedstoneProvider provider )
{
Objects.requireNonNull( provider, "provider cannot be null" );
providers.add( provider );
}
public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
return World.isValid( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
}
private static int getUnmaskedOutput( World world, BlockPos pos, Direction side )
private static int getUnmaskedOutput( World world, BlockPos pos, EnumFacing side )
{
if( !World.isValid( pos ) ) return -1;
@@ -60,7 +60,7 @@ public final class BundledRedstone
return combinedSignal;
}
public static int getOutput( World world, BlockPos pos, Direction side )
public static int getOutput( World world, BlockPos pos, EnumFacing side )
{
int signal = getUnmaskedOutput( world, pos, side );
return signal >= 0 ? signal : 0;

View File

@@ -0,0 +1,344 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.core.apis.AddressPredicate;
import dan200.computercraft.core.apis.http.websocket.Websocket;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static dan200.computercraft.ComputerCraft.DEFAULT_HTTP_BLACKLIST;
import static dan200.computercraft.ComputerCraft.DEFAULT_HTTP_WHITELIST;
import static net.minecraftforge.common.ForgeConfigSpec.Builder;
import static net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class Config
{
private static final int MODEM_MAX_RANGE = 100000;
private static final String TRANSLATION_PREFIX = "gui.computercraft.config.";
private static ConfigValue<Integer> computerSpaceLimit;
private static ConfigValue<Integer> floppySpaceLimit;
private static ConfigValue<Integer> maximumFilesOpen;
private static ConfigValue<Boolean> disableLua51Features;
private static ConfigValue<String> defaultComputerSettings;
private static ConfigValue<Boolean> debugEnabled;
private static ConfigValue<Boolean> logComputerErrors;
private static ConfigValue<Integer> computerThreads;
private static ConfigValue<Integer> maxMainGlobalTime;
private static ConfigValue<Integer> maxMainComputerTime;
private static ConfigValue<Boolean> httpEnabled;
private static ConfigValue<Boolean> httpWebsocketEnabled;
private static ConfigValue<List<? extends String>> httpWhitelist;
private static ConfigValue<List<? extends String>> httpBlacklist;
private static ConfigValue<Integer> httpTimeout;
private static ConfigValue<Integer> httpMaxRequests;
private static ConfigValue<Integer> httpMaxDownload;
private static ConfigValue<Integer> httpMaxUpload;
private static ConfigValue<Integer> httpMaxWebsockets;
private static ConfigValue<Integer> httpMaxWebsocketMessage;
private static ConfigValue<Boolean> commandBlockEnabled;
private static ConfigValue<Integer> modemRange;
private static ConfigValue<Integer> modemHighAltitudeRange;
private static ConfigValue<Integer> modemRangeDuringStorm;
private static ConfigValue<Integer> modemHighAltitudeRangeDuringStorm;
private static ConfigValue<Integer> maxNotesPerTick;
private static ConfigValue<Boolean> turtlesNeedFuel;
private static ConfigValue<Integer> turtleFuelLimit;
private static ConfigValue<Integer> advancedTurtleFuelLimit;
private static ConfigValue<Boolean> turtlesObeyBlockProtection;
private static ConfigValue<Boolean> turtlesCanPush;
private static ConfigValue<List<? extends String>> turtleDisabledActions;
private static final ForgeConfigSpec spec;
private Config() {}
static
{
Builder builder = new Builder();
{ // General computers
computerSpaceLimit = builder
.comment( "The disk space limit for computers and turtles, in bytes" )
.translation( TRANSLATION_PREFIX + "computer_space_limit" )
.define( "computer_space_limit", ComputerCraft.computerSpaceLimit );
floppySpaceLimit = builder
.comment( "The disk space limit for floppy disks, in bytes" )
.translation( TRANSLATION_PREFIX + "floppy_space_limit" )
.define( "floppy_space_limit", ComputerCraft.floppySpaceLimit );
maximumFilesOpen = builder
.comment( "Set how many files a computer can have open at the same time. Set to 0 for unlimited." )
.translation( TRANSLATION_PREFIX + "maximum_open_files" )
.defineInRange( "maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE );
disableLua51Features = builder
.comment( "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " +
"Useful for ensuring forward compatibility of your programs now." )
.define( "disable_lua51_features", ComputerCraft.disable_lua51_features );
defaultComputerSettings = builder
.comment( "A comma separated list of default system settings to set on new computers. Example: " +
"\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " +
"autocompletion" )
.define( "default_computer_settings", ComputerCraft.default_computer_settings );
debugEnabled = builder
.comment( "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players." )
.define( "debug_enabled", ComputerCraft.debug_enable );
logComputerErrors = builder
.comment( "Log exceptions thrown by peripherals and other Lua objects.\n" +
"This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." )
.define( "log_computer_errors", ComputerCraft.logPeripheralErrors );
}
{
builder.comment( "Controls execution behaviour of computers. This is largely intended for fine-tuning " +
"servers, and generally shouldn't need to be touched" );
builder.push( "execution" );
computerThreads = builder
.comment( "Set the number of threads computers can run on. A higher number means more computers can run " +
"at once, but may induce lag.\n" +
"Please note that some mods may not work with a thread count higher than 1. Use with caution." )
.worldRestart()
.defineInRange( "computer_threads", ComputerCraft.computer_threads, 1, Integer.MAX_VALUE );
maxMainGlobalTime = builder
.comment( "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" +
"Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " +
"- this aims to be the upper bound of the average time." )
.defineInRange( "max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE );
maxMainComputerTime = builder
.comment( "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" +
"Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " +
"- this aims to be the upper bound of the average time." )
.defineInRange( "max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE );
builder.pop();
}
{ // HTTP
builder.comment( "Controls the HTTP API" );
builder.push( "http" );
httpEnabled = builder
.comment( "Enable the \"http\" API on Computers (see \"http_whitelist\" and \"http_blacklist\" for more " +
"fine grained control than this)" )
.define( "enabled", ComputerCraft.http_enable );
httpWebsocketEnabled = builder
.comment( "Enable use of http websockets. This requires the \"http_enable\" option to also be true." )
.define( "websocket_enabled", ComputerCraft.http_websocket_enable );
httpWhitelist = builder
.comment( "A list of wildcards for domains or IP ranges that can be accessed through the \"http\" API on Computers.\n" +
"Set this to \"*\" to access to the entire internet. Example: \"*.pastebin.com\" will restrict access to just subdomains of pastebin.com.\n" +
"You can use domain names (\"pastebin.com\"), wilcards (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\")." )
.defineList( "whitelist", Arrays.asList( DEFAULT_HTTP_WHITELIST ), x -> true );
httpBlacklist = builder
.comment( "A list of wildcards for domains or IP ranges that cannot be accessed through the \"http\" API on Computers.\n" +
"If this is empty then all whitelisted domains will be accessible. Example: \"*.github.com\" will block access to all subdomains of github.com.\n" +
"You can use domain names (\"pastebin.com\"), wilcards (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\")." )
.defineList( "blacklist", Arrays.asList( DEFAULT_HTTP_BLACKLIST ), x -> true );
httpTimeout = builder
.comment( "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." )
.defineInRange( "timeout", ComputerCraft.httpTimeout, 0, Integer.MAX_VALUE );
httpMaxRequests = builder
.comment( "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited." )
.defineInRange( "max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE );
httpMaxDownload = builder
.comment( "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." )
.defineInRange( "max_download", (int) ComputerCraft.httpMaxDownload, 0, Integer.MAX_VALUE );
httpMaxUpload = builder
.comment( "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." )
.defineInRange( "max_upload", (int) ComputerCraft.httpMaxUpload, 0, Integer.MAX_VALUE );
httpMaxWebsockets = builder
.comment( "The number of websockets a computer can have open at one time. Set to 0 for unlimited." )
.defineInRange( "max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE );
httpMaxWebsocketMessage = builder
.comment( "The maximum size (in bytes) that a computer can send or receive in one websocket packet." )
.defineInRange( "max_websocket_message", ComputerCraft.httpMaxWebsocketMessage, 0, Websocket.MAX_MESSAGE_SIZE );
builder.pop();
}
{ // Peripherals
builder.comment( "Various options relating to peripherals." );
builder.push( "peripheral" );
commandBlockEnabled = builder
.comment( "Enable Command Block peripheral support" )
.define( "command_block_enabled", ComputerCraft.enableCommandBlock );
modemRange = builder
.comment( "The range of Wireless Modems at low altitude in clear weather, in meters" )
.defineInRange( "modem_range", ComputerCraft.modem_range, 0, MODEM_MAX_RANGE );
modemHighAltitudeRange = builder
.comment( "The range of Wireless Modems at maximum altitude in clear weather, in meters" )
.defineInRange( "modem_high_altitude_range", ComputerCraft.modem_highAltitudeRange, 0, MODEM_MAX_RANGE );
modemRangeDuringStorm = builder
.comment( "The range of Wireless Modems at low altitude in stormy weather, in meters" )
.defineInRange( "modem_range_during_storm", ComputerCraft.modem_rangeDuringStorm, 0, MODEM_MAX_RANGE );
modemHighAltitudeRangeDuringStorm = builder
.comment( "The range of Wireless Modems at maximum altitude in stormy weather, in meters" )
.defineInRange( "modem_high_altitude_range_during_storm", ComputerCraft.modem_highAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE );
maxNotesPerTick = builder
.comment( "Maximum amount of notes a speaker can play at once" )
.defineInRange( "max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE );
builder.pop();
}
{ // Turtles
builder.comment( "Various options relating to turtles." );
builder.push( "turtle" );
turtlesNeedFuel = builder
.comment( "Set whether Turtles require fuel to move" )
.define( "need_fuel", ComputerCraft.turtlesNeedFuel );
turtleFuelLimit = builder
.comment( "The fuel limit for Turtles" )
.defineInRange( "normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE );
advancedTurtleFuelLimit = builder
.comment( "The fuel limit for Advanced Turtles" )
.defineInRange( "advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE );
turtlesObeyBlockProtection = builder
.comment( "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)" )
.define( "obey_block_protection", ComputerCraft.turtlesObeyBlockProtection );
turtlesCanPush = builder
.comment( "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" )
.define( "can_push", ComputerCraft.turtlesCanPush );
turtleDisabledActions = builder
.comment( "A list of turtle actions which are disabled." )
.defineList( "disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction( (String) x ) != null );
builder.pop();
}
spec = builder.build();
}
public static void load()
{
ModLoadingContext.get().registerConfig( ModConfig.Type.COMMON, spec );
}
public static void sync()
{
// General
ComputerCraft.computerSpaceLimit = computerSpaceLimit.get();
ComputerCraft.floppySpaceLimit = floppySpaceLimit.get();
ComputerCraft.maximumFilesOpen = maximumFilesOpen.get();
ComputerCraft.disable_lua51_features = disableLua51Features.get();
ComputerCraft.default_computer_settings = defaultComputerSettings.get();
ComputerCraft.debug_enable = debugEnabled.get();
ComputerCraft.computer_threads = computerThreads.get();
ComputerCraft.logPeripheralErrors = logComputerErrors.get();
// Execution
ComputerCraft.computer_threads = computerThreads.get();
ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( maxMainGlobalTime.get() );
ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( maxMainComputerTime.get() );
// HTTP
ComputerCraft.http_enable = httpEnabled.get();
ComputerCraft.http_websocket_enable = httpWebsocketEnabled.get();
ComputerCraft.http_whitelist = new AddressPredicate( httpWhitelist.get() );
ComputerCraft.http_blacklist = new AddressPredicate( httpBlacklist.get() );
ComputerCraft.httpTimeout = httpTimeout.get();
ComputerCraft.httpMaxRequests = httpMaxRequests.get();
ComputerCraft.httpMaxDownload = httpMaxDownload.get();
ComputerCraft.httpMaxUpload = httpMaxUpload.get();
ComputerCraft.httpMaxWebsockets = httpMaxWebsockets.get();
ComputerCraft.httpMaxWebsocketMessage = httpMaxWebsocketMessage.get();
// Peripheral
ComputerCraft.enableCommandBlock = commandBlockEnabled.get();
ComputerCraft.maxNotesPerTick = maxNotesPerTick.get();
ComputerCraft.modem_range = modemRange.get();
ComputerCraft.modem_highAltitudeRange = modemHighAltitudeRange.get();
ComputerCraft.modem_rangeDuringStorm = modemRangeDuringStorm.get();
ComputerCraft.modem_highAltitudeRangeDuringStorm = modemHighAltitudeRangeDuringStorm.get();
// Turtles
ComputerCraft.turtlesNeedFuel = turtlesNeedFuel.get();
ComputerCraft.turtleFuelLimit = turtleFuelLimit.get();
ComputerCraft.advancedTurtleFuelLimit = advancedTurtleFuelLimit.get();
ComputerCraft.turtlesObeyBlockProtection = turtlesObeyBlockProtection.get();
ComputerCraft.turtlesCanPush = turtlesCanPush.get();
ComputerCraft.turtleDisabledActions.clear();
for( String value : turtleDisabledActions.get() ) ComputerCraft.turtleDisabledActions.add( getAction( value ) );
}
@SubscribeEvent
public static void sync( ModConfig.Loading event )
{
sync();
}
@SubscribeEvent
public static void sync( ModConfig.ConfigReloading event )
{
sync();
}
private static final Converter<String, String> converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE );
private static TurtleAction getAction( String value )
{
try
{
return TurtleAction.valueOf( converter.convert( value ) );
}
catch( IllegalArgumentException e )
{
return null;
}
}
}

View File

@@ -9,8 +9,8 @@ package dan200.computercraft.shared;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -30,12 +30,12 @@ public final class Peripherals
providers.add( provider );
}
public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side )
public static IPeripheral getPeripheral( World world, BlockPos pos, EnumFacing side )
{
return World.isValid( pos ) && !world.isClient ? getPeripheralAt( world, pos, side ) : null;
return World.isValid( pos ) && !world.isRemote ? getPeripheralAt( world, pos, side ) : null;
}
private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side )
private static IPeripheral getPeripheralAt( World world, BlockPos pos, EnumFacing side )
{
// Try the handlers in order:
for( IPeripheralProvider peripheralProvider : providers )

View File

@@ -10,13 +10,17 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.shared.util.InventoryUtil;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModLoadingContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public final class PocketUpgrades
{
private static final Map<String, IPocketUpgrade> upgrades = new HashMap<>();
private static final IdentityHashMap<IPocketUpgrade, String> upgradeOwners = new IdentityHashMap<>();
private PocketUpgrades() {}
@@ -32,6 +36,9 @@ public final class PocketUpgrades
}
upgrades.put( id, upgrade );
ModContainer mc = ModLoadingContext.get().getActiveContainer();
if( mc != null && mc.getModId() != null ) upgradeOwners.put( upgrade, mc.getModId() );
}
public static IPocketUpgrade get( String id )
@@ -58,6 +65,12 @@ public final class PocketUpgrades
return null;
}
@Nullable
public static String getOwner( IPocketUpgrade upgrade )
{
return upgradeOwners.get( upgrade );
}
public static Iterable<IPocketUpgrade> getVanillaUpgrades()
{
List<IPocketUpgrade> vanilla = new ArrayList<>();

View File

@@ -8,18 +8,14 @@ package dan200.computercraft.shared;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.shared.common.ColourableRecipe;
import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.items.ItemComputer;
import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.media.recipes.DiskRecipe;
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
import dan200.computercraft.shared.peripheral.modem.wired.*;
@@ -34,215 +30,239 @@ import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe;
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.turtle.recipes.TurtleRecipe;
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.ImpostorRecipe;
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
import net.fabricmc.fabric.api.block.FabricBlockSettings;
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
import dan200.computercraft.shared.util.CreativeTabMain;
import net.minecraft.block.Block;
import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.*;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.MutableRegistry;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityType;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemGroup;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.IForgeRegistry;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class Registry
{
private static final ItemGroup mainItemGroup = FabricItemGroupBuilder
.create( new Identifier( ComputerCraft.MOD_ID, "main" ) )
.icon( () -> new ItemStack( ComputerCraft.Items.computerNormal ) )
.build();
private static final ItemGroup mainItemGroup = new CreativeTabMain();
private Registry()
{
}
public static void registerBlocks( MutableRegistry<Block> registry )
@SubscribeEvent
public static void registerBlocks( RegistryEvent.Register<Block> event )
{
IForgeRegistry<Block> registry = event.getRegistry();
// Computers
ComputerCraft.Blocks.computerNormal = new BlockComputer(
FabricBlockSettings.of( Material.STONE ).hardness( 2.0f ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.0f ),
ComputerFamily.Normal, TileComputer.FACTORY_NORMAL
);
ComputerCraft.Blocks.computerAdvanced = new BlockComputer(
FabricBlockSettings.of( Material.STONE ).hardness( 2.0f ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.0f ),
ComputerFamily.Advanced, TileComputer.FACTORY_ADVANCED
);
ComputerCraft.Blocks.computerCommand = new BlockComputer(
FabricBlockSettings.of( Material.STONE ).strength( -1, 6000000.0F ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( -1, 6000000.0F ),
ComputerFamily.Command, TileCommandComputer.FACTORY
);
registry.add( new Identifier( ComputerCraft.MOD_ID, "computer_normal" ), ComputerCraft.Blocks.computerNormal );
registry.add( new Identifier( ComputerCraft.MOD_ID, "computer_advanced" ), ComputerCraft.Blocks.computerAdvanced );
registry.add( new Identifier( ComputerCraft.MOD_ID, "computer_command" ), ComputerCraft.Blocks.computerCommand );
registry.registerAll(
ComputerCraft.Blocks.computerNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_normal" ) ),
ComputerCraft.Blocks.computerAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_advanced" ) ),
ComputerCraft.Blocks.computerCommand.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_command" ) )
);
// Turtles
ComputerCraft.Blocks.turtleNormal = new BlockTurtle(
FabricBlockSettings.of( Material.STONE ).hardness( 2.5f ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f ),
ComputerFamily.Normal, TileTurtle.FACTORY_NORMAL
);
ComputerCraft.Blocks.turtleAdvanced = new BlockTurtle(
FabricBlockSettings.of( Material.STONE ).hardness( 2.5f ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f ),
ComputerFamily.Advanced, TileTurtle.FACTORY_ADVANCED
);
registry.add( new Identifier( ComputerCraft.MOD_ID, "turtle_normal" ), ComputerCraft.Blocks.turtleNormal );
registry.add( new Identifier( ComputerCraft.MOD_ID, "turtle_advanced" ), ComputerCraft.Blocks.turtleAdvanced );
registry.registerAll(
ComputerCraft.Blocks.turtleNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_normal" ) ),
ComputerCraft.Blocks.turtleAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ) )
);
// Peripherals
ComputerCraft.Blocks.speaker = new BlockSpeaker(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build()
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 )
);
ComputerCraft.Blocks.diskDrive = new BlockDiskDrive(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build()
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 )
);
ComputerCraft.Blocks.monitorNormal = new BlockMonitor(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileMonitor.FACTORY_NORMAL
);
ComputerCraft.Blocks.monitorAdvanced = new BlockMonitor(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileMonitor.FACTORY_ADVANCED
);
ComputerCraft.Blocks.printer = new BlockPrinter(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build()
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 )
);
ComputerCraft.Blocks.wirelessModemNormal = new BlockWirelessModem(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileWirelessModem.FACTORY_NORMAL
);
ComputerCraft.Blocks.wirelessModemAdvanced = new BlockWirelessModem(
FabricBlockSettings.of( Material.STONE ).hardness( 2 ).build(),
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileWirelessModem.FACTORY_ADVANCED
);
ComputerCraft.Blocks.wiredModemFull = new BlockWiredModemFull(
FabricBlockSettings.of( Material.STONE ).hardness( 1.5f ).build()
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 1.5f )
);
ComputerCraft.Blocks.cable = new BlockCable(
FabricBlockSettings.of( Material.STONE ).hardness( 1.5f ).build()
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 1.5f )
);
registry.add( new Identifier( ComputerCraft.MOD_ID, "speaker" ), ComputerCraft.Blocks.speaker );
registry.add( new Identifier( ComputerCraft.MOD_ID, "disk_drive" ), ComputerCraft.Blocks.diskDrive );
registry.add( new Identifier( ComputerCraft.MOD_ID, "monitor_normal" ), ComputerCraft.Blocks.monitorNormal );
registry.add( new Identifier( ComputerCraft.MOD_ID, "monitor_advanced" ), ComputerCraft.Blocks.monitorAdvanced );
registry.add( new Identifier( ComputerCraft.MOD_ID, "printer" ), ComputerCraft.Blocks.printer );
registry.add( new Identifier( ComputerCraft.MOD_ID, "wireless_modem_normal" ), ComputerCraft.Blocks.wirelessModemNormal );
registry.add( new Identifier( ComputerCraft.MOD_ID, "wireless_modem_advanced" ), ComputerCraft.Blocks.wirelessModemAdvanced );
registry.add( new Identifier( ComputerCraft.MOD_ID, "wired_modem_full" ), ComputerCraft.Blocks.wiredModemFull );
registry.add( new Identifier( ComputerCraft.MOD_ID, "cable" ), ComputerCraft.Blocks.cable );
registry.registerAll(
ComputerCraft.Blocks.speaker.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ) ),
ComputerCraft.Blocks.diskDrive.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "disk_drive" ) ),
ComputerCraft.Blocks.monitorNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "monitor_normal" ) ),
ComputerCraft.Blocks.monitorAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "monitor_advanced" ) ),
ComputerCraft.Blocks.printer.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printer" ) ),
ComputerCraft.Blocks.wirelessModemNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) ),
ComputerCraft.Blocks.wirelessModemAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) ),
ComputerCraft.Blocks.wiredModemFull.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem_full" ) ),
ComputerCraft.Blocks.cable.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "cable" ) )
);
}
public static void registerTileEntities( MutableRegistry<BlockEntityType<?>> registry )
@SubscribeEvent
public static void registerTileEntities( RegistryEvent.Register<TileEntityType<?>> event )
{
IForgeRegistry<TileEntityType<?>> registry = event.getRegistry();
// Computers
registry.add( TileComputer.FACTORY_NORMAL.getId(), TileComputer.FACTORY_NORMAL );
registry.add( TileComputer.FACTORY_ADVANCED.getId(), TileComputer.FACTORY_ADVANCED );
registry.add( TileCommandComputer.FACTORY.getId(), TileCommandComputer.FACTORY );
registry.registerAll( TileComputer.FACTORY_NORMAL, TileComputer.FACTORY_ADVANCED, TileCommandComputer.FACTORY );
// Turtles
registry.add( TileTurtle.FACTORY_NORMAL.getId(), TileTurtle.FACTORY_NORMAL );
registry.add( TileTurtle.FACTORY_ADVANCED.getId(), TileTurtle.FACTORY_ADVANCED );
registry.registerAll( TileTurtle.FACTORY_NORMAL, TileTurtle.FACTORY_ADVANCED );
// Peripherals
registry.add( TileSpeaker.FACTORY.getId(), TileSpeaker.FACTORY );
registry.add( TileDiskDrive.FACTORY.getId(), TileDiskDrive.FACTORY );
registry.add( TilePrinter.FACTORY.getId(), TilePrinter.FACTORY );
registry.add( TileMonitor.FACTORY_NORMAL.getId(), TileMonitor.FACTORY_NORMAL );
registry.add( TileMonitor.FACTORY_ADVANCED.getId(), TileMonitor.FACTORY_ADVANCED );
registry.add( TileWirelessModem.FACTORY_NORMAL.getId(), TileWirelessModem.FACTORY_NORMAL );
registry.add( TileWirelessModem.FACTORY_ADVANCED.getId(), TileWirelessModem.FACTORY_ADVANCED );
registry.add( TileCable.FACTORY.getId(), TileCable.FACTORY );
registry.add( TileWiredModemFull.FACTORY.getId(), TileWiredModemFull.FACTORY );
registry.registerAll(
TileSpeaker.FACTORY,
TileDiskDrive.FACTORY,
TileMonitor.FACTORY_NORMAL,
TileMonitor.FACTORY_ADVANCED,
TilePrinter.FACTORY,
TileWirelessModem.FACTORY_NORMAL,
TileWirelessModem.FACTORY_ADVANCED,
TileWiredModemFull.FACTORY,
TileCable.FACTORY
);
}
private static void registerItemBlock( MutableRegistry<Item> registry, BlockItem item )
private static <T extends ItemBlock> T setupItemBlock( T item )
{
registry.add( net.minecraft.util.registry.Registry.BLOCK.getId( item.getBlock() ), item );
item.setRegistryName( item.getBlock().getRegistryName() );
return item;
}
private static Item.Settings defaultItem()
private static Item.Properties defaultItem()
{
return new Item.Settings().itemGroup( mainItemGroup );
return new Item.Properties().group( mainItemGroup );
}
public static void registerItems( MutableRegistry<Item> registry )
@SubscribeEvent
public static void registerItems( RegistryEvent.Register<Item> event )
{
IForgeRegistry<Item> registry = event.getRegistry();
// Computer
ComputerCraft.Items.computerNormal = new ItemComputer( ComputerCraft.Blocks.computerNormal, defaultItem() );
ComputerCraft.Items.computerAdvanced = new ItemComputer( ComputerCraft.Blocks.computerAdvanced, defaultItem() );
ComputerCraft.Items.computerCommand = new ItemComputer( ComputerCraft.Blocks.computerCommand, defaultItem() );
registerItemBlock( registry, ComputerCraft.Items.computerNormal );
registerItemBlock( registry, ComputerCraft.Items.computerAdvanced );
registerItemBlock( registry, ComputerCraft.Items.computerCommand );
registry.registerAll(
setupItemBlock( ComputerCraft.Items.computerNormal ),
setupItemBlock( ComputerCraft.Items.computerAdvanced ),
setupItemBlock( ComputerCraft.Items.computerCommand )
);
// Turtle
ComputerCraft.Items.turtleNormal = new ItemTurtle( ComputerCraft.Blocks.turtleNormal, defaultItem() );
ComputerCraft.Items.turtleAdvanced = new ItemTurtle( ComputerCraft.Blocks.turtleAdvanced, defaultItem() );
registerItemBlock( registry, ComputerCraft.Items.turtleNormal );
registerItemBlock( registry, ComputerCraft.Items.turtleAdvanced );
registry.registerAll(
setupItemBlock( ComputerCraft.Items.turtleNormal ),
setupItemBlock( ComputerCraft.Items.turtleAdvanced )
);
// Pocket computer
ComputerCraft.Items.pocketComputerNormal = new ItemPocketComputer( defaultItem().stackSize( 1 ), ComputerFamily.Normal );
ComputerCraft.Items.pocketComputerAdvanced = new ItemPocketComputer( defaultItem().stackSize( 1 ), ComputerFamily.Advanced );
ComputerCraft.Items.pocketComputerNormal = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.Normal );
ComputerCraft.Items.pocketComputerAdvanced = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.Advanced );
registry.add( new Identifier( ComputerCraft.MOD_ID, "pocket_computer_normal" ), ComputerCraft.Items.pocketComputerNormal );
registry.add( new Identifier( ComputerCraft.MOD_ID, "pocket_computer_advanced" ), ComputerCraft.Items.pocketComputerAdvanced );
registry.registerAll(
ComputerCraft.Items.pocketComputerNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_normal" ) ),
ComputerCraft.Items.pocketComputerAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_advanced" ) )
);
// Floppy disk
ComputerCraft.Items.disk = new ItemDisk( defaultItem().stackSize( 1 ) );
ComputerCraft.Items.treasureDisk = new ItemTreasureDisk( defaultItem().stackSize( 1 ) );
ComputerCraft.Items.disk = new ItemDisk( defaultItem().maxStackSize( 1 ) );
ComputerCraft.Items.treasureDisk = new ItemTreasureDisk( defaultItem().maxStackSize( 1 ) );
registry.add( new Identifier( ComputerCraft.MOD_ID, "disk" ), ComputerCraft.Items.disk );
registry.add( new Identifier( ComputerCraft.MOD_ID, "treasure_disk" ), ComputerCraft.Items.treasureDisk );
registry.registerAll(
ComputerCraft.Items.disk.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "disk" ) ),
ComputerCraft.Items.treasureDisk.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "treasure_disk" ) )
);
// Printouts
ComputerCraft.Items.printedPage = new ItemPrintout( defaultItem().stackSize( 1 ), ItemPrintout.Type.PAGE );
ComputerCraft.Items.printedPages = new ItemPrintout( defaultItem().stackSize( 1 ), ItemPrintout.Type.PAGES );
ComputerCraft.Items.printedBook = new ItemPrintout( defaultItem().stackSize( 1 ), ItemPrintout.Type.BOOK );
ComputerCraft.Items.printedPage = new ItemPrintout( defaultItem().maxStackSize( 1 ), ItemPrintout.Type.PAGE );
ComputerCraft.Items.printedPages = new ItemPrintout( defaultItem().maxStackSize( 1 ), ItemPrintout.Type.PAGES );
ComputerCraft.Items.printedBook = new ItemPrintout( defaultItem().maxStackSize( 1 ), ItemPrintout.Type.BOOK );
registry.add( new Identifier( ComputerCraft.MOD_ID, "printed_page" ), ComputerCraft.Items.printedPage );
registry.add( new Identifier( ComputerCraft.MOD_ID, "printed_pages" ), ComputerCraft.Items.printedPages );
registry.add( new Identifier( ComputerCraft.MOD_ID, "printed_book" ), ComputerCraft.Items.printedBook );
registry.registerAll(
ComputerCraft.Items.printedPage.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printed_page" ) ),
ComputerCraft.Items.printedPages.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printed_pages" ) ),
ComputerCraft.Items.printedBook.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printed_book" ) )
);
// Peripherals
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.speaker, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.diskDrive, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.printer, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.monitorNormal, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.monitorAdvanced, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.wirelessModemNormal, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.wirelessModemAdvanced, defaultItem() ) );
registerItemBlock( registry, new BlockItem( ComputerCraft.Blocks.wiredModemFull, defaultItem() ) );
registry.registerAll(
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.speaker, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.diskDrive, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.printer, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.monitorNormal, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.monitorAdvanced, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.wirelessModemNormal, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.wirelessModemAdvanced, defaultItem() ) ),
setupItemBlock( new ItemBlock( ComputerCraft.Blocks.wiredModemFull, defaultItem() ) )
);
ComputerCraft.Items.cable = new ItemBlockCable.Cable( ComputerCraft.Blocks.cable, defaultItem() );
ComputerCraft.Items.wiredModem = new ItemBlockCable.WiredModem( ComputerCraft.Blocks.cable, defaultItem() );
registry.add( new Identifier( ComputerCraft.MOD_ID, "cable" ), ComputerCraft.Items.cable );
registry.add( new Identifier( ComputerCraft.MOD_ID, "wired_modem" ), ComputerCraft.Items.wiredModem );
registry.registerAll(
ComputerCraft.Items.cable.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "cable" ) ),
ComputerCraft.Items.wiredModem.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem" ) )
);
registerTurtleUpgrades();
registerPocketUpgrades();
@@ -251,31 +271,31 @@ public final class Registry
private static void registerTurtleUpgrades()
{
// Upgrades
ComputerCraft.TurtleUpgrades.wirelessModemNormal = new TurtleModem( false, new Identifier( ComputerCraft.MOD_ID, "wireless_modem_normal" ) );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.wirelessModemNormal );
ComputerCraft.TurtleUpgrades.wirelessModemNormal = new TurtleModem( false, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) );
TurtleUpgrades.register( ComputerCraft.TurtleUpgrades.wirelessModemNormal );
ComputerCraft.TurtleUpgrades.wirelessModemAdvanced = new TurtleModem( true, new Identifier( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) );
ComputerCraft.TurtleUpgrades.wirelessModemAdvanced = new TurtleModem( true, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.wirelessModemAdvanced );
ComputerCraft.TurtleUpgrades.speaker = new TurtleSpeaker( new Identifier( ComputerCraft.MOD_ID, "speaker" ) );
ComputerCraft.TurtleUpgrades.speaker = new TurtleSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ) );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.speaker );
ComputerCraft.TurtleUpgrades.craftingTable = new TurtleCraftingTable( new Identifier( "minecraft", "crafting_table" ) );
ComputerCraft.TurtleUpgrades.craftingTable = new TurtleCraftingTable( new ResourceLocation( "minecraft", "crafting_table" ) );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.craftingTable );
ComputerCraft.TurtleUpgrades.diamondSword = new TurtleSword( new Identifier( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD );
ComputerCraft.TurtleUpgrades.diamondSword = new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondSword );
ComputerCraft.TurtleUpgrades.diamondShovel = new TurtleShovel( new Identifier( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL );
ComputerCraft.TurtleUpgrades.diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondShovel );
ComputerCraft.TurtleUpgrades.diamondPickaxe = new TurtleTool( new Identifier( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE );
ComputerCraft.TurtleUpgrades.diamondPickaxe = new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondPickaxe );
ComputerCraft.TurtleUpgrades.diamondAxe = new TurtleAxe( new Identifier( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE );
ComputerCraft.TurtleUpgrades.diamondAxe = new TurtleAxe( new ResourceLocation( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondAxe );
ComputerCraft.TurtleUpgrades.diamondHoe = new TurtleHoe( new Identifier( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE );
ComputerCraft.TurtleUpgrades.diamondHoe = new TurtleHoe( new ResourceLocation( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondHoe );
}
@@ -286,16 +306,9 @@ public final class Registry
ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.speaker = new PocketSpeaker() );
}
public static void registerRecipes( MutableRegistry<RecipeSerializer<?>> registry )
@SubscribeEvent
public static void registerEntities( RegistryEvent.Register<EntityType<?>> registry )
{
registry.add( new Identifier( ComputerCraft.MOD_ID, "colour" ), ColourableRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "computer_upgrade" ), ComputerUpgradeRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "pocket_computer_upgrade" ), PocketComputerUpgradeRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "disk" ), DiskRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "printout" ), PrintoutRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "turtle" ), TurtleRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "turtle_upgrade" ), TurtleUpgradeRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "impostor_shaped" ), ImpostorRecipe.SERIALIZER );
registry.add( new Identifier( ComputerCraft.MOD_ID, "impostor_shapeless" ), ImpostorShapelessRecipe.SERIALIZER );
registry.getRegistry().register( TurtlePlayer.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_player" ) ) );
}
}

View File

@@ -6,30 +6,32 @@
package dan200.computercraft.shared;
import com.google.common.eventbus.Subscribe;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID )
public final class TurtlePermissions
{
public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player )
public static boolean isBlockEnterable( World world, BlockPos pos, EntityPlayer player )
{
MinecraftServer server = world.getServer();
return server == null || world.isClient || !server.isSpawnProtected( world, pos, player );
return server == null || world.isRemote || !server.isBlockProtected( world, pos, player );
}
public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player )
public static boolean isBlockEditable( World world, BlockPos pos, EntityPlayer player )
{
MinecraftServer server = world.getServer();
return server == null || world.isClient || !server.isSpawnProtected( world, pos, player );
return server == null || world.isRemote || !server.isBlockProtected( world, pos, player );
}
@Subscribe
public void onTurtleAction( TurtleActionEvent event )
@SubscribeEvent
public static void onTurtleAction( TurtleActionEvent event )
{
if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) )
{

View File

@@ -11,13 +11,17 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.util.InventoryUtil;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModLoadingContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public final class TurtleUpgrades
{
private static final Map<String, ITurtleUpgrade> upgrades = new HashMap<>();
private static final IdentityHashMap<ITurtleUpgrade, String> upgradeOwners = new IdentityHashMap<>();
private TurtleUpgrades() {}
@@ -33,6 +37,9 @@ public final class TurtleUpgrades
}
upgrades.put( id, upgrade );
ModContainer mc = ModLoadingContext.get().getActiveContainer();
if( mc != null && mc.getModId() != null ) upgradeOwners.put( upgrade, mc.getModId() );
}
@@ -77,6 +84,12 @@ public final class TurtleUpgrades
return vanilla;
}
@Nullable
public static String getOwner( @Nonnull ITurtleUpgrade upgrade )
{
return upgradeOwners.get( upgrade );
}
public static Iterable<ITurtleUpgrade> getUpgrades()
{
return Collections.unmodifiableCollection( upgrades.values() );

View File

@@ -21,15 +21,16 @@ import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.Containers;
import net.minecraft.command.CommandSource;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.server.SPacketPlayerPosLook;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import javax.annotation.Nonnull;
import java.util.*;
@@ -44,7 +45,7 @@ import static dan200.computercraft.shared.command.builder.CommandBuilder.args;
import static dan200.computercraft.shared.command.builder.CommandBuilder.command;
import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.choice;
import static dan200.computercraft.shared.command.text.ChatHelpers.*;
import static net.minecraft.server.command.CommandManager.literal;
import static net.minecraft.command.Commands.literal;
public final class CommandComputerCraft
{
@@ -58,7 +59,7 @@ public final class CommandComputerCraft
{
}
public static void register( CommandDispatcher<ServerCommandSource> dispatcher )
public static void register( CommandDispatcher<CommandSource> dispatcher )
{
dispatcher.register( choice( "computercraft" )
.then( literal( "dump" )
@@ -66,17 +67,17 @@ public final class CommandComputerCraft
.executes( context -> {
TableBuilder table = new TableBuilder( DUMP_LIST_ID, "Computer", "On", "Position" );
ServerCommandSource source = context.getSource();
CommandSource source = context.getSource();
List<ServerComputer> computers = new ArrayList<>( ComputerCraft.serverComputerRegistry.getComputers() );
// Unless we're on a server, limit the number of rows we can send.
World world = source.getWorld();
BlockPos pos = new BlockPos( source.getPosition() );
BlockPos pos = new BlockPos( source.getPos() );
computers.sort( ( a, b ) -> {
if( a.getWorld() == b.getWorld() && a.getWorld() == world )
{
return Double.compare( a.getPosition().getSquaredDistance( pos ), b.getPosition().getSquaredDistance( pos ) );
return Double.compare( a.getPosition().distanceSq( pos ), b.getPosition().distanceSq( pos ) );
}
else if( a.getWorld() == world )
{
@@ -168,17 +169,17 @@ public final class CommandComputerCraft
if( world == null || pos == null ) throw TP_NOT_THERE.create();
Entity entity = context.getSource().getEntityOrThrow();
if( !(entity instanceof ServerPlayerEntity) ) throw TP_NOT_PLAYER.create();
Entity entity = context.getSource().assertIsEntity();
if( !(entity instanceof EntityPlayerMP) ) throw TP_NOT_PLAYER.create();
ServerPlayerEntity player = (ServerPlayerEntity) entity;
EntityPlayerMP player = (EntityPlayerMP) entity;
if( player.getEntityWorld() == world )
{
player.networkHandler.teleportRequest( pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0, Collections.emptySet() );
player.connection.setPlayerLocation( pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0, EnumSet.noneOf( SPacketPlayerPosLook.EnumFlags.class ) );
}
else
{
player.teleport( (ServerWorld) world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0 );
player.teleport( (WorldServer) world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0 );
}
return 1;
@@ -209,7 +210,7 @@ public final class CommandComputerCraft
.requires( UserLevel.OP )
.arg( "computer", oneComputer() )
.executes( context -> {
ServerPlayerEntity player = context.getSource().getPlayer();
EntityPlayerMP player = context.getSource().asPlayer();
ServerComputer computer = getComputerArgument( context, "computer" );
Containers.openComputerGUI( player, computer );
return 1;
@@ -256,18 +257,18 @@ public final class CommandComputerCraft
);
}
private static Component linkComputer( ServerCommandSource source, ServerComputer serverComputer, int computerId )
private static ITextComponent linkComputer( CommandSource source, ServerComputer serverComputer, int computerId )
{
TextComponent out = new TextComponent( "" );
ITextComponent out = new TextComponentString( "" );
// Append the computer instance
if( serverComputer == null )
{
out.append( text( "?" ) );
out.appendSibling( text( "?" ) );
}
else
{
out.append( link(
out.appendSibling( link(
text( Integer.toString( serverComputer.getInstanceID() ) ),
"/computercraft dump " + serverComputer.getInstanceID(),
translate( "commands.computercraft.dump.action" )
@@ -275,20 +276,20 @@ public final class CommandComputerCraft
}
// And ID
out.append( " (id " + computerId + ")" );
out.appendText( " (id " + computerId + ")" );
// And, if we're a player, some useful links
if( serverComputer != null && UserLevel.OP.test( source ) && isPlayer( source ) )
{
out
.append( " " )
.append( link(
.appendText( " " )
.appendSibling( link(
text( "\u261b" ),
"/computercraft tp " + serverComputer.getInstanceID(),
translate( "commands.computercraft.tp.action" )
) )
.append( " " )
.append( link(
.appendText( " " )
.appendSibling( link(
text( "\u20e2" ),
"/computercraft view " + serverComputer.getInstanceID(),
translate( "commands.computercraft.view.action" )
@@ -298,7 +299,7 @@ public final class CommandComputerCraft
return out;
}
private static Component linkPosition( ServerCommandSource context, ServerComputer computer )
private static ITextComponent linkPosition( CommandSource context, ServerComputer computer )
{
if( UserLevel.OP.test( context ) )
{
@@ -315,20 +316,20 @@ public final class CommandComputerCraft
}
@Nonnull
private static TrackingContext getTimingContext( ServerCommandSource source )
private static TrackingContext getTimingContext( CommandSource source )
{
Entity entity = source.getEntity();
return entity instanceof PlayerEntity ? Tracking.getContext( entity.getUuid() ) : Tracking.getContext( SYSTEM_UUID );
return entity instanceof EntityPlayer ? Tracking.getContext( entity.getUniqueID() ) : Tracking.getContext( SYSTEM_UUID );
}
private static final List<TrackingField> DEFAULT_FIELDS = Arrays.asList( TrackingField.TASKS, TrackingField.TOTAL_TIME, TrackingField.AVERAGE_TIME, TrackingField.MAX_TIME );
private static int displayTimings( ServerCommandSource source, TrackingField sortField, List<TrackingField> fields ) throws CommandSyntaxException
private static int displayTimings( CommandSource source, TrackingField sortField, List<TrackingField> fields ) throws CommandSyntaxException
{
return displayTimings( source, getTimingContext( source ).getTimings(), sortField, fields );
}
private static int displayTimings( ServerCommandSource source, @Nonnull List<ComputerTracker> timings, @Nonnull TrackingField sortField, @Nonnull List<TrackingField> fields ) throws CommandSyntaxException
private static int displayTimings( CommandSource source, @Nonnull List<ComputerTracker> timings, @Nonnull TrackingField sortField, @Nonnull List<TrackingField> fields ) throws CommandSyntaxException
{
if( timings.isEmpty() ) throw NO_TIMINGS_EXCEPTION.create();
@@ -344,7 +345,7 @@ public final class CommandComputerCraft
timings.sort( Comparator.<ComputerTracker, Long>comparing( x -> x.get( sortField ) ).reversed() );
Component[] headers = new Component[1 + fields.size()];
ITextComponent[] headers = new ITextComponent[1 + fields.size()];
headers[0] = translate( "commands.computercraft.track.dump.computer" );
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() );
TableBuilder table = new TableBuilder( TRACK_ID, headers );
@@ -354,9 +355,9 @@ public final class CommandComputerCraft
Computer computer = entry.getComputer();
ServerComputer serverComputer = computer == null ? null : lookup.get( computer );
Component computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
ITextComponent computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
Component[] row = new Component[1 + fields.size()];
ITextComponent[] row = new ITextComponent[1 + fields.size()];
row[0] = computerComponent;
for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) );
table.row( row );

View File

@@ -8,16 +8,23 @@ package dan200.computercraft.shared.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import net.minecraft.client.MinecraftClient;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.command.ServerCommandSource;
import dan200.computercraft.ComputerCraft;
import net.minecraft.client.Minecraft;
import net.minecraft.command.CommandSource;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import static net.minecraft.command.Commands.argument;
import static net.minecraft.command.Commands.literal;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class CommandCopy
{
private static final String PREFIX = "/computercraft copy ";
@@ -26,36 +33,35 @@ public final class CommandCopy
{
}
public static void register( CommandDispatcher<ServerCommandSource> registry )
public static void register( CommandDispatcher<CommandSource> registry )
{
registry.register( literal( "computercraft" )
.then( literal( "copy" ) )
.then( argument( "message", StringArgumentType.greedyString() ) )
.executes( context -> {
MinecraftClient.getInstance().keyboard.setClipboard( context.getArgument( "message", String.class ) );
Minecraft.getInstance().keyboardListener.setClipboardString( context.getArgument( "message", String.class ) );
return 1;
} )
);
}
public static boolean onClientSendMessage( String message )
@SubscribeEvent
public static void onClientSendMessage( ClientChatEvent event )
{
// Emulate the command on the client side
if( message.startsWith( PREFIX ) )
if( event.getMessage().startsWith( PREFIX ) )
{
MinecraftClient.getInstance().keyboard.setClipboard( message.substring( PREFIX.length() ) );
return true;
Minecraft.getInstance().keyboardListener.setClipboardString( event.getMessage().substring( PREFIX.length() ) );
event.setCanceled( true );
}
return false;
}
public static TextComponent createCopyText( String text )
public static ITextComponent createCopyText( String text )
{
TextComponent name = new TextComponent( text );
TextComponentString name = new TextComponentString( text );
name.getStyle()
.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, PREFIX + text ) )
.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) );
.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TextComponentTranslation( "gui.computercraft.tooltip.copy" ) ) );
return name;
}
}

View File

@@ -9,11 +9,11 @@ package dan200.computercraft.shared.command;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import dan200.computercraft.api.turtle.event.FakePlayer;
import net.minecraft.command.CommandSource;
import net.minecraft.command.ISuggestionProvider;
import net.minecraft.entity.Entity;
import net.minecraft.server.command.CommandSource;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.common.util.FakePlayer;
import java.util.Arrays;
import java.util.Locale;
@@ -24,29 +24,29 @@ public final class CommandUtils
{
private CommandUtils() {}
public static boolean isPlayer( ServerCommandSource output )
public static boolean isPlayer( CommandSource output )
{
Entity sender = output.getEntity();
return sender instanceof ServerPlayerEntity
return sender instanceof EntityPlayerMP
&& !(sender instanceof FakePlayer)
&& ((ServerPlayerEntity) sender).networkHandler != null;
&& ((EntityPlayerMP) sender).connection != null;
}
@SuppressWarnings( "unchecked" )
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder, Function<CommandContext<ServerCommandSource>, CompletableFuture<Suggestions>> supplier )
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder, Function<CommandContext<CommandSource>, CompletableFuture<Suggestions>> supplier )
{
Object source = context.getSource();
if( !(source instanceof CommandSource) )
if( !(source instanceof ISuggestionProvider) )
{
return Suggestions.empty();
}
else if( source instanceof ServerCommandSource )
else if( source instanceof CommandSource )
{
return supplier.apply( (CommandContext<ServerCommandSource>) context );
return supplier.apply( (CommandContext<CommandSource>) context );
}
else
{
return ((CommandSource) source).getCompletions( (CommandContext<CommandSource>) context, builder );
return ((ISuggestionProvider) source).getSuggestionsFromServer( (CommandContext<ISuggestionProvider>) context, builder );
}
}

View File

@@ -9,7 +9,7 @@ package dan200.computercraft.shared.command;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.util.text.TextComponentTranslation;
public final class Exceptions
{
@@ -28,16 +28,16 @@ public final class Exceptions
private static SimpleCommandExceptionType translated( String key )
{
return new SimpleCommandExceptionType( new TranslatableComponent( key ) );
return new SimpleCommandExceptionType( new TextComponentTranslation( key ) );
}
private static DynamicCommandExceptionType translated1( String key )
{
return new DynamicCommandExceptionType( x -> new TranslatableComponent( key, x ) );
return new DynamicCommandExceptionType( x -> new TextComponentTranslation( key, x ) );
}
private static Dynamic2CommandExceptionType translated2( String key )
{
return new Dynamic2CommandExceptionType( ( x, y ) -> new TranslatableComponent( key, x, y ) );
return new Dynamic2CommandExceptionType( ( x, y ) -> new TextComponentTranslation( key, x, y ) );
}
}

Some files were not shown because too many files have changed in this diff Show More