mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-01 06:03:00 +00:00
Compare commits
13 Commits
mc-1.14.x
...
v1.15.2-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d7a81696d | ||
|
|
33260a7747 | ||
|
|
af40f5ae5c | ||
|
|
759d02a249 | ||
|
|
d7729337ac | ||
|
|
f106733d71 | ||
|
|
2360a6e951 | ||
|
|
f4f71185ae | ||
|
|
649acbae1c | ||
|
|
05eada427b | ||
|
|
f3a330e330 | ||
|
|
044d2b2b06 | ||
|
|
fb440b0d2e |
14
build.gradle
14
build.gradle
@@ -9,7 +9,7 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.code.gson:gson:2.8.1'
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.154'
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.169'
|
||||
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
|
||||
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
|
||||
}
|
||||
@@ -47,7 +47,7 @@ minecraft {
|
||||
}
|
||||
|
||||
server {
|
||||
workingDirectory project.file('run')
|
||||
workingDirectory project.file("run/server-${mc_version}")
|
||||
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
@@ -99,10 +99,10 @@ dependencies {
|
||||
|
||||
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
||||
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.27:api")
|
||||
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.14.4:5.0.1.162")
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3:api")
|
||||
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.15.2:6.0.0.9")
|
||||
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.27")
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3")
|
||||
|
||||
shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'
|
||||
|
||||
@@ -373,7 +373,7 @@ curseforge {
|
||||
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
|
||||
project {
|
||||
id = '282001'
|
||||
releaseType = 'release'
|
||||
releaseType = 'alpha'
|
||||
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 {
|
||||
@@ -451,7 +451,7 @@ githubRelease {
|
||||
.takeWhile { it != 'Type "help changelog" to see the full version history.' }
|
||||
.join("\n").trim()
|
||||
}
|
||||
prerelease false
|
||||
prerelease true
|
||||
}
|
||||
|
||||
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
<property name="file" value="config/checkstyle/suppressions.xml" />
|
||||
</module>
|
||||
|
||||
<module name="BeforeExecutionExclusionFileFilter">
|
||||
<property name="fileNamePattern" value="render_old"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<!-- Annotations -->
|
||||
<module name="AnnotationLocation" />
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
mod_version=1.87.0
|
||||
|
||||
# Minecraft properties (update mods.toml when changing)
|
||||
mc_version=1.14.4
|
||||
forge_version=28.1.71
|
||||
mappings_version=20191123-1.14.3
|
||||
mc_version=1.15.2
|
||||
forge_version=31.1.41
|
||||
mappings_version=20200410-1.15.1
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package dan200.computercraft;
|
||||
|
||||
import dan200.computercraft.api.turtle.event.TurtleAction;
|
||||
import dan200.computercraft.core.apis.AddressPredicate;
|
||||
import dan200.computercraft.core.apis.http.AddressRule;
|
||||
import dan200.computercraft.shared.Config;
|
||||
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||
@@ -39,8 +39,13 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mod( ComputerCraft.MOD_ID )
|
||||
public final class ComputerCraft
|
||||
@@ -50,8 +55,8 @@ public final class ComputerCraft
|
||||
public static final int DATAFIXER_VERSION = 0;
|
||||
|
||||
// Configuration options
|
||||
public static final String[] DEFAULT_HTTP_WHITELIST = new String[] { "*" };
|
||||
public static final String[] DEFAULT_HTTP_BLACKLIST = new String[] {
|
||||
public static final String[] DEFAULT_HTTP_ALLOW = new String[] { "*" };
|
||||
public static final String[] DEFAULT_HTTP_DENY = new String[] {
|
||||
"127.0.0.0/8",
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
@@ -71,10 +76,12 @@ public final class ComputerCraft
|
||||
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 );
|
||||
public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( 5 );
|
||||
|
||||
public static boolean http_enable = true;
|
||||
public static boolean http_websocket_enable = true;
|
||||
public static AddressPredicate http_whitelist = new AddressPredicate( DEFAULT_HTTP_WHITELIST );
|
||||
public static AddressPredicate http_blacklist = new AddressPredicate( DEFAULT_HTTP_BLACKLIST );
|
||||
public static boolean httpEnabled = true;
|
||||
public static boolean httpWebsocketEnabled = true;
|
||||
public static List<AddressRule> httpRules = Collections.unmodifiableList( Stream.concat(
|
||||
Stream.of( DEFAULT_HTTP_DENY ).map( x -> AddressRule.parse( x, AddressRule.Action.DENY ) ).filter( Objects::nonNull ),
|
||||
Stream.of( DEFAULT_HTTP_ALLOW ).map( x -> AddressRule.parse( x, AddressRule.Action.ALLOW ) ).filter( Objects::nonNull )
|
||||
).collect( Collectors.toList() ) );
|
||||
|
||||
public static int httpTimeout = 30000;
|
||||
public static int httpMaxRequests = 16;
|
||||
|
||||
@@ -112,31 +112,6 @@ public final class ComputerCraftAPI
|
||||
return getInstance().createResourceMount( domain, subPath );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file system mount to a resource folder, and returns it.
|
||||
*
|
||||
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a
|
||||
* resource folder onto a computer's file system.
|
||||
*
|
||||
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
|
||||
* resources with the same domain and path.
|
||||
*
|
||||
* @param klass The mod class to which the files belong.
|
||||
* @param domain The domain under which to look for resources. eg: "mymod".
|
||||
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
|
||||
* @return The mount, or {@code null} if it could be created for some reason.
|
||||
* @see IComputerAccess#mount(String, IMount)
|
||||
* @see IComputerAccess#mountWritable(String, IWritableMount)
|
||||
* @see IMount
|
||||
* @deprecated Use {@link #createResourceMount(String, String)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public static IMount createResourceMount( Class<?> klass, @Nonnull String domain, @Nonnull String subPath )
|
||||
{
|
||||
return getInstance().createResourceMount( domain, subPath );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. 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.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ModelManager;
|
||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A model to render, combined with a transformation matrix to apply.
|
||||
*/
|
||||
public final class TransformedModel
|
||||
{
|
||||
private final IBakedModel model;
|
||||
private final TransformationMatrix matrix;
|
||||
|
||||
public TransformedModel( @Nonnull IBakedModel model, @Nonnull TransformationMatrix matrix )
|
||||
{
|
||||
this.model = Objects.requireNonNull( model );
|
||||
this.matrix = Objects.requireNonNull( matrix );
|
||||
}
|
||||
|
||||
public TransformedModel( @Nonnull IBakedModel model )
|
||||
{
|
||||
this.model = Objects.requireNonNull( model );
|
||||
this.matrix = TransformationMatrix.identity();
|
||||
}
|
||||
|
||||
public static TransformedModel of( @Nonnull ModelResourceLocation location )
|
||||
{
|
||||
ModelManager modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel( modelManager.getModel( location ) );
|
||||
}
|
||||
|
||||
public static TransformedModel of( @Nonnull ItemStack item, @Nonnull TransformationMatrix transform )
|
||||
{
|
||||
IBakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelMesher().getItemModel( item );
|
||||
return new TransformedModel( model, transform );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public IBakedModel getModel()
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public TransformationMatrix getMatrix()
|
||||
{
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@ import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.List;
|
||||
@@ -23,10 +21,10 @@ import java.util.List;
|
||||
*
|
||||
* Ready made implementations of this interface can be created using
|
||||
* {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or
|
||||
* {@link ComputerCraftAPI#createResourceMount(Class, String, String)}, or you're free to implement it yourselves!
|
||||
* {@link ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
|
||||
*
|
||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
||||
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
|
||||
* @see ComputerCraftAPI#createResourceMount(String, String)
|
||||
* @see IComputerAccess#mount(String, IMount)
|
||||
* @see IWritableMount
|
||||
*/
|
||||
@@ -68,18 +66,6 @@ public interface IMount
|
||||
*/
|
||||
long getSize( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a file with a given path, and returns an {@link InputStream} representing its contents.
|
||||
*
|
||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||
* @return A stream representing the contents of the file.
|
||||
* @throws IOException If the file does not exist, or could not be opened.
|
||||
* @deprecated Use {@link #openChannelForRead(String)} instead
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
InputStream openForRead( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
|
||||
*
|
||||
@@ -90,10 +76,7 @@ public interface IMount
|
||||
* @throws IOException If the file does not exist, or could not be opened.
|
||||
*/
|
||||
@Nonnull
|
||||
default ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newChannel( openForRead( path ) );
|
||||
}
|
||||
ReadableByteChannel openForRead( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Get attributes about the given file.
|
||||
|
||||
@@ -12,7 +12,6 @@ import net.minecraft.world.World;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.OptionalLong;
|
||||
|
||||
@@ -46,18 +45,6 @@ public interface IWritableMount extends IMount
|
||||
*/
|
||||
void delete( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
|
||||
*
|
||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||
* @return A stream for writing to
|
||||
* @throws IOException If the file could not be opened for writing.
|
||||
* @deprecated Use {@link #openChannelForWrite(String)} instead.
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
OutputStream openForWrite( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
|
||||
*
|
||||
@@ -67,22 +54,7 @@ public interface IWritableMount extends IMount
|
||||
* @throws IOException If the file could not be opened for writing.
|
||||
*/
|
||||
@Nonnull
|
||||
default WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newChannel( openForWrite( path ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
|
||||
*
|
||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||
* @return A stream for writing to.
|
||||
* @throws IOException If the file could not be opened for writing.
|
||||
* @deprecated Use {@link #openChannelForAppend(String)} instead.
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
OutputStream openForAppend( @Nonnull String path ) throws IOException;
|
||||
WritableByteChannel openForWrite( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
|
||||
@@ -93,10 +65,7 @@ public interface IWritableMount extends IMount
|
||||
* @throws IOException If the file could not be opened for writing.
|
||||
*/
|
||||
@Nonnull
|
||||
default WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newChannel( openForAppend( path ) );
|
||||
}
|
||||
WritableByteChannel openForAppend( @Nonnull String path ) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the
|
||||
|
||||
@@ -79,7 +79,7 @@ public interface IMedia
|
||||
* @see IMount
|
||||
* @see dan200.computercraft.api.filesystem.IWritableMount
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String, long)
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String)
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(String, String)
|
||||
*/
|
||||
@Nullable
|
||||
default IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world )
|
||||
|
||||
@@ -14,7 +14,6 @@ import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -31,9 +30,9 @@ public interface IComputerAccess
|
||||
* @param mount The mount object to mount on the computer.
|
||||
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
|
||||
* file in the desired location. Store this value if you wish to unmount the mount later.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
||||
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
|
||||
* @see ComputerCraftAPI#createResourceMount(String, String)
|
||||
* @see #mount(String, IMount, String)
|
||||
* @see #mountWritable(String, IWritableMount)
|
||||
* @see #unmount(String)
|
||||
@@ -53,9 +52,9 @@ public interface IComputerAccess
|
||||
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
|
||||
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
|
||||
* file in the desired location. Store this value if you wish to unmount the mount later.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
||||
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
|
||||
* @see ComputerCraftAPI#createResourceMount(String, String)
|
||||
* @see #mount(String, IMount)
|
||||
* @see #mountWritable(String, IWritableMount)
|
||||
* @see #unmount(String)
|
||||
@@ -71,9 +70,9 @@ public interface IComputerAccess
|
||||
* @param mount The mount object to mount on the computer.
|
||||
* @return The location on the computer's file system where you the mount mounted, or null if there was already a
|
||||
* file in the desired location. Store this value if you wish to unmount the mount later.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
||||
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
|
||||
* @see ComputerCraftAPI#createResourceMount(String, String)
|
||||
* @see #mount(String, IMount)
|
||||
* @see #unmount(String)
|
||||
* @see IMount
|
||||
@@ -92,9 +91,9 @@ public interface IComputerAccess
|
||||
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
|
||||
* @return The location on the computer's file system where you the mount mounted, or null if there was already a
|
||||
* file in the desired location. Store this value if you wish to unmount the mount later.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
||||
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
|
||||
* @see ComputerCraftAPI#createResourceMount(String, String)
|
||||
* @see #mount(String, IMount)
|
||||
* @see #unmount(String)
|
||||
* @see IMount
|
||||
@@ -114,8 +113,8 @@ public interface IComputerAccess
|
||||
* @param location The desired location in the computers file system of the directory to unmount.
|
||||
* This must be the location of a directory previously mounted by {@link #mount(String, IMount)} or
|
||||
* {@link #mountWritable(String, IWritableMount)}, as indicated by their return value.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws RuntimeException If the mount does not exist, or was mounted by another peripheral.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @throws IllegalStateException If the mount does not exist, or was mounted by another peripheral.
|
||||
* @see #mount(String, IMount)
|
||||
* @see #mountWritable(String, IWritableMount)
|
||||
*/
|
||||
@@ -146,7 +145,7 @@ public interface IComputerAccess
|
||||
* to lua data types in the same fashion as the return values of IPeripheral.callMethod().
|
||||
*
|
||||
* You may supply {@code null} to indicate that no arguments are to be supplied.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see IPeripheral#callMethod
|
||||
*/
|
||||
void queueEvent( @Nonnull String event, @Nullable Object[] arguments );
|
||||
@@ -159,7 +158,7 @@ public interface IComputerAccess
|
||||
* which peripheral the event came.
|
||||
*
|
||||
* @return A string unique to the computer, but not globally.
|
||||
* @throws RuntimeException If the peripheral has been detached.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
*/
|
||||
@Nonnull
|
||||
String getAttachmentName();
|
||||
@@ -170,14 +169,12 @@ public interface IComputerAccess
|
||||
* This may include other peripherals on the wired network or peripherals on other sides of the computer.
|
||||
*
|
||||
* @return All reachable peripherals
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see #getAttachmentName()
|
||||
* @see #getAvailablePeripheral(String)
|
||||
*/
|
||||
@Nonnull
|
||||
default Map<String, IPeripheral> getAvailablePeripherals()
|
||||
{
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, IPeripheral> getAvailablePeripherals();
|
||||
|
||||
/**
|
||||
* Get a reachable peripheral with the given attachment name. This is a equivalent to
|
||||
@@ -188,10 +185,7 @@ public interface IComputerAccess
|
||||
* @see #getAvailablePeripherals()
|
||||
*/
|
||||
@Nullable
|
||||
default IPeripheral getAvailablePeripheral( @Nonnull String name )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
IPeripheral getAvailablePeripheral( @Nonnull String name );
|
||||
|
||||
/**
|
||||
* Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread.
|
||||
@@ -205,10 +199,8 @@ public interface IComputerAccess
|
||||
* thread.
|
||||
*
|
||||
* @return The work monitor for the main thread, or {@code null} if this computer does not have one.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
*/
|
||||
@Nullable
|
||||
default IWorkMonitor getMainThreadMonitor()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@Nonnull
|
||||
IWorkMonitor getMainThreadMonitor();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. 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;
|
||||
|
||||
/**
|
||||
* Thrown when performing operations on {@link IComputerAccess} when the current peripheral is no longer attached to
|
||||
* the computer.
|
||||
*/
|
||||
public class NotAttachedException extends IllegalStateException
|
||||
{
|
||||
private static final long serialVersionUID = 1221244785535553536L;
|
||||
|
||||
public NotAttachedException()
|
||||
{
|
||||
super( "You are not attached to this Computer" );
|
||||
}
|
||||
|
||||
public NotAttachedException( String s )
|
||||
{
|
||||
super( s );
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,8 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. 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;
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IItemProvider;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@@ -6,10 +6,10 @@
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
|
||||
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
@@ -18,11 +18,9 @@ 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;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
|
||||
/**
|
||||
* The primary interface for defining an update for Turtles. A turtle update
|
||||
@@ -126,12 +124,11 @@ public interface ITurtleUpgrade
|
||||
*
|
||||
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models!
|
||||
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
||||
* @return The model that you wish to be used to render your upgrade, and a transformation to apply to it. Returning
|
||||
* a transformation of {@code null} has the same effect as the identify matrix.
|
||||
* @return The model that you wish to be used to render your upgrade.
|
||||
*/
|
||||
@Nonnull
|
||||
@OnlyIn( Dist.CLIENT )
|
||||
Pair<IBakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
|
||||
TransformedModel getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
|
||||
|
||||
/**
|
||||
* Called once per tick for each turtle which has the upgrade equipped.
|
||||
|
||||
@@ -17,70 +17,70 @@ public enum TurtleAnimation
|
||||
/**
|
||||
* An animation which does nothing. This takes no time to complete.
|
||||
*
|
||||
* @see #Wait
|
||||
* @see #ShortWait
|
||||
* @see #WAIT
|
||||
* @see #SHORT_WAIT
|
||||
*/
|
||||
None,
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Make the turtle move forward. Note that the animation starts from the block <em>behind</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MoveForward,
|
||||
MOVE_FORWARD,
|
||||
|
||||
/**
|
||||
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MoveBack,
|
||||
MOVE_BACK,
|
||||
|
||||
/**
|
||||
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MoveUp,
|
||||
MOVE_UP,
|
||||
|
||||
/**
|
||||
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MoveDown,
|
||||
MOVE_DOWN,
|
||||
|
||||
/**
|
||||
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and
|
||||
* the turtle turns to face in the current direction.
|
||||
*/
|
||||
TurnLeft,
|
||||
TURN_LEFT,
|
||||
|
||||
/**
|
||||
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and
|
||||
* the turtle turns to face in the current direction.
|
||||
*/
|
||||
TurnRight,
|
||||
TURN_RIGHT,
|
||||
|
||||
/**
|
||||
* Swing the tool on the left.
|
||||
*/
|
||||
SwingLeftTool,
|
||||
SWING_LEFT_TOOL,
|
||||
|
||||
/**
|
||||
* Swing the tool on the right.
|
||||
*/
|
||||
SwingRightTool,
|
||||
SWING_RIGHT_TOOL,
|
||||
|
||||
/**
|
||||
* Wait until the animation has finished, performing no movement.
|
||||
*
|
||||
* @see #ShortWait
|
||||
* @see #None
|
||||
* @see #SHORT_WAIT
|
||||
* @see #NONE
|
||||
*/
|
||||
Wait,
|
||||
WAIT,
|
||||
|
||||
/**
|
||||
* Wait until the animation has finished, performing no movement. This takes 4 ticks to complete.
|
||||
*
|
||||
* @see #Wait
|
||||
* @see #None
|
||||
* @see #WAIT
|
||||
* @see #NONE
|
||||
*/
|
||||
ShortWait,
|
||||
SHORT_WAIT,
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ public enum TurtleSide
|
||||
/**
|
||||
* The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle).
|
||||
*/
|
||||
Left,
|
||||
LEFT,
|
||||
|
||||
/**
|
||||
* The turtle's right side (where the modem usually is on a Wireless Mining Turtle).
|
||||
*/
|
||||
Right,
|
||||
RIGHT,
|
||||
}
|
||||
|
||||
@@ -16,28 +16,28 @@ public enum TurtleUpgradeType
|
||||
* A tool is rendered as an item on the side of the turtle, and responds to the {@code turtle.dig()}
|
||||
* and {@code turtle.attack()} methods (Such as pickaxe or sword on Mining and Melee turtles).
|
||||
*/
|
||||
Tool,
|
||||
TOOL,
|
||||
|
||||
/**
|
||||
* A peripheral adds a special peripheral which is attached to the side of the turtle,
|
||||
* and can be interacted with the {@code peripheral} API (Such as the modem on Wireless Turtles).
|
||||
*/
|
||||
Peripheral,
|
||||
PERIPHERAL,
|
||||
|
||||
/**
|
||||
* An upgrade which provides both a tool and a peripheral. This can be used when you wish
|
||||
* your upgrade to also provide methods. For example, a pickaxe could provide methods
|
||||
* determining whether it can break the given block or not.
|
||||
*/
|
||||
Both;
|
||||
BOTH;
|
||||
|
||||
public boolean isTool()
|
||||
{
|
||||
return this == Tool || this == Both;
|
||||
return this == TOOL || this == BOTH;
|
||||
}
|
||||
|
||||
public boolean isPeripheral()
|
||||
{
|
||||
return this == Peripheral || this == Both;
|
||||
return this == PERIPHERAL || this == BOTH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ public enum TurtleVerb
|
||||
/**
|
||||
* The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}.
|
||||
*/
|
||||
Dig,
|
||||
DIG,
|
||||
|
||||
/**
|
||||
* The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}.
|
||||
*/
|
||||
Attack,
|
||||
ATTACK,
|
||||
}
|
||||
|
||||
@@ -11,20 +11,19 @@ import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.IUnbakedModel;
|
||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
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.BasicState;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
import net.minecraftforge.client.model.SimpleModelTransform;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@@ -71,13 +70,13 @@ public final class ClientRegistry
|
||||
@SubscribeEvent
|
||||
public static void registerModels( ModelRegistryEvent event )
|
||||
{
|
||||
ModelLoaderRegistry.registerLoader( TurtleModelLoader.INSTANCE );
|
||||
ModelLoaderRegistry.registerLoader( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ), TurtleModelLoader.INSTANCE );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
|
||||
{
|
||||
if( event.getMap() != Minecraft.getInstance().getTextureMap() ) return;
|
||||
if( !event.getMap().getTextureLocation().equals( PlayerContainer.LOCATION_BLOCKS_TEXTURE ) ) return;
|
||||
|
||||
for( String extra : EXTRA_TEXTURES )
|
||||
{
|
||||
@@ -92,29 +91,18 @@ public final class ClientRegistry
|
||||
ModelLoader loader = event.getModelLoader();
|
||||
Map<ResourceLocation, IBakedModel> registry = event.getModelRegistry();
|
||||
|
||||
for( String model : EXTRA_MODELS )
|
||||
for( String modelName : EXTRA_MODELS )
|
||||
{
|
||||
IBakedModel bakedModel = bake( loader, loader.getUnbakedModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/" + model ) ) );
|
||||
ResourceLocation location = new ResourceLocation( ComputerCraft.MOD_ID, "item/" + modelName );
|
||||
IUnbakedModel model = loader.getUnbakedModel( location );
|
||||
model.getTextures( loader::getUnbakedModel, new HashSet<>() );
|
||||
|
||||
if( bakedModel != null )
|
||||
IBakedModel baked = model.bakeModel( loader, ModelLoader.defaultTextureGetter(), SimpleModelTransform.IDENTITY, location );
|
||||
if( baked != null )
|
||||
{
|
||||
registry.put(
|
||||
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ),
|
||||
bakedModel
|
||||
);
|
||||
registry.put( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, modelName ), "inventory" ), baked );
|
||||
}
|
||||
}
|
||||
|
||||
// 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" ) ) )
|
||||
);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -142,7 +130,7 @@ public final class ClientRegistry
|
||||
case 2: // Light colour
|
||||
{
|
||||
int light = ItemPocketComputer.getLightState( stack );
|
||||
return light == -1 ? Colour.Black.getHex() : light;
|
||||
return light == -1 ? Colour.BLACK.getHex() : light;
|
||||
}
|
||||
}
|
||||
}, ComputerCraft.Items.pocketComputerNormal, ComputerCraft.Items.pocketComputerAdvanced );
|
||||
@@ -153,15 +141,4 @@ public final class ClientRegistry
|
||||
ComputerCraft.Blocks.turtleNormal, ComputerCraft.Blocks.turtleAdvanced
|
||||
);
|
||||
}
|
||||
|
||||
private static IBakedModel bake( ModelLoader loader, IUnbakedModel model )
|
||||
{
|
||||
model.getTextures( loader::getUnbakedModel, new HashSet<>() );
|
||||
|
||||
return model.bake(
|
||||
loader,
|
||||
ModelLoader.defaultTextureGetter(),
|
||||
new BasicState( model.getDefaultState(), false ), DefaultVertexFormats.BLOCK
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@@ -24,21 +24,10 @@ import javax.annotation.Nullable;
|
||||
|
||||
public final class FixedWidthFontRenderer
|
||||
{
|
||||
private static final Matrix4f IDENTITY = TransformationMatrix.identity().getMatrix();
|
||||
|
||||
private static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
|
||||
|
||||
/**
|
||||
* Like {@link DefaultVertexFormats#POSITION_TEX_COLOR}, but flipped. This is backported from 1.15, hence the
|
||||
* custom format.
|
||||
*/
|
||||
public static final VertexFormat POSITION_COLOR_TEX = new VertexFormat();
|
||||
|
||||
static
|
||||
{
|
||||
POSITION_COLOR_TEX.addElement( DefaultVertexFormats.POSITION_3F );
|
||||
POSITION_COLOR_TEX.addElement( DefaultVertexFormats.COLOR_4UB );
|
||||
POSITION_COLOR_TEX.addElement( DefaultVertexFormats.TEX_2F );
|
||||
}
|
||||
|
||||
public static final int FONT_HEIGHT = 9;
|
||||
public static final int FONT_WIDTH = 6;
|
||||
public static final float WIDTH = 256.0f;
|
||||
@@ -46,6 +35,8 @@ public final class FixedWidthFontRenderer
|
||||
public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH;
|
||||
public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
|
||||
|
||||
public static final RenderType TYPE = Type.MAIN;
|
||||
|
||||
private FixedWidthFontRenderer()
|
||||
{
|
||||
}
|
||||
@@ -61,7 +52,7 @@ public final class FixedWidthFontRenderer
|
||||
return i < 0 ? 0 : 15 - i;
|
||||
}
|
||||
|
||||
private static void drawChar( BufferBuilder buffer, float x, float y, int index, float r, float g, float b )
|
||||
private static void drawChar( Matrix4f transform, IVertexBuilder buffer, float x, float y, int index, float r, float g, float b )
|
||||
{
|
||||
// Short circuit to avoid the common case - the texture should be blank here after all.
|
||||
if( index == '\0' || index == ' ' ) return;
|
||||
@@ -72,25 +63,25 @@ public final class FixedWidthFontRenderer
|
||||
int xStart = 1 + column * (FONT_WIDTH + 2);
|
||||
int yStart = 1 + row * (FONT_HEIGHT + 2);
|
||||
|
||||
buffer.pos( x, y, 0f ).color( r, g, b, 1.0f ).tex( xStart / WIDTH, yStart / WIDTH ).endVertex();
|
||||
buffer.pos( x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).tex( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex();
|
||||
buffer.pos( x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).tex( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).endVertex();
|
||||
buffer.pos( x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).tex( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).endVertex();
|
||||
buffer.pos( x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).tex( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex();
|
||||
buffer.pos( x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).tex( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex();
|
||||
buffer.pos( transform, x, y, 0f ).color( r, g, b, 1.0f ).tex( xStart / WIDTH, yStart / WIDTH ).endVertex();
|
||||
buffer.pos( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).tex( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex();
|
||||
buffer.pos( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).tex( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).endVertex();
|
||||
buffer.pos( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).tex( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).endVertex();
|
||||
buffer.pos( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).tex( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex();
|
||||
buffer.pos( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).tex( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).endVertex();
|
||||
}
|
||||
|
||||
private static void drawQuad( BufferBuilder buffer, float x, float y, float width, float height, float r, float g, float b )
|
||||
private static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float width, float height, float r, float g, float b )
|
||||
{
|
||||
buffer.pos( x, y, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_START, BACKGROUND_START ).endVertex();
|
||||
buffer.pos( x, y + height, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||
buffer.pos( x + width, y, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||
buffer.pos( x + width, y, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||
buffer.pos( x, y + height, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||
buffer.pos( x + width, y + height, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_END, BACKGROUND_END ).endVertex();
|
||||
buffer.pos( transform, x, y, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_START, BACKGROUND_START ).endVertex();
|
||||
buffer.pos( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||
buffer.pos( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||
buffer.pos( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||
buffer.pos( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||
buffer.pos( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).tex( BACKGROUND_END, BACKGROUND_END ).endVertex();
|
||||
}
|
||||
|
||||
private static void drawQuad( BufferBuilder buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
||||
private static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
||||
{
|
||||
double[] colour = palette.getColour( getColour( colourIndex ) );
|
||||
float r, g, b;
|
||||
@@ -105,23 +96,23 @@ public final class FixedWidthFontRenderer
|
||||
b = (float) colour[2];
|
||||
}
|
||||
|
||||
drawQuad( buffer, x, y, width, height, r, g, b );
|
||||
drawQuad( transform, buffer, x, y, width, height, r, g, b );
|
||||
}
|
||||
|
||||
private static void drawBackground(
|
||||
@Nonnull BufferBuilder renderer, float x, float y,
|
||||
@Nonnull Matrix4f transform, @Nonnull IVertexBuilder renderer, float x, float y,
|
||||
@Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||
float leftMarginSize, float rightMarginSize, float height
|
||||
)
|
||||
{
|
||||
if( leftMarginSize > 0 )
|
||||
{
|
||||
drawQuad( renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
||||
drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
||||
}
|
||||
|
||||
if( rightMarginSize > 0 )
|
||||
{
|
||||
drawQuad( renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||
drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||
}
|
||||
|
||||
// Batch together runs of identical background cells.
|
||||
@@ -134,7 +125,7 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
||||
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
||||
}
|
||||
|
||||
blockColour = colourIndex;
|
||||
@@ -143,24 +134,24 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour );
|
||||
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawString(
|
||||
@Nonnull BufferBuilder renderer, float x, float y,
|
||||
@Nonnull Matrix4f transform, @Nonnull IVertexBuilder renderer, float x, float y,
|
||||
@Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour,
|
||||
@Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
if( backgroundColour != null )
|
||||
{
|
||||
drawBackground( renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT );
|
||||
drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT );
|
||||
}
|
||||
|
||||
for( int i = 0; i < text.length(); i++ )
|
||||
{
|
||||
double[] colour = palette.getColour( getColour( textColour.charAt( i ) ) );
|
||||
double[] colour = palette.getColour( 15 - "0123456789abcdef".indexOf( textColour.charAt( i ) ) );
|
||||
float r, g, b;
|
||||
if( greyscale )
|
||||
{
|
||||
@@ -176,7 +167,7 @@ public final class FixedWidthFontRenderer
|
||||
// Draw char
|
||||
int index = text.charAt( i );
|
||||
if( index > 255 ) index = '?';
|
||||
drawChar( renderer, x + i * FONT_WIDTH, y, index, r, g, b );
|
||||
drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -188,15 +179,13 @@ public final class FixedWidthFontRenderer
|
||||
{
|
||||
bindFont();
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
begin( buffer );
|
||||
drawString( buffer, x, y, text, textColour, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize );
|
||||
tessellator.draw();
|
||||
IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
|
||||
drawString( IDENTITY, ((IRenderTypeBuffer) renderer).getBuffer( TYPE ), x, y, text, textColour, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize );
|
||||
renderer.finish();
|
||||
}
|
||||
|
||||
public static void drawTerminalWithoutCursor(
|
||||
@Nonnull BufferBuilder buffer, float x, float y,
|
||||
@Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
@@ -206,13 +195,13 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
// Top and bottom margins
|
||||
drawBackground(
|
||||
buffer, x, y - topMarginSize,
|
||||
transform, buffer, x, y - topMarginSize,
|
||||
terminal.getBackgroundColourLine( 0 ), palette, greyscale,
|
||||
leftMarginSize, rightMarginSize, topMarginSize
|
||||
);
|
||||
|
||||
drawBackground(
|
||||
buffer, x, y + height * FONT_HEIGHT,
|
||||
transform, buffer, x, y + height * FONT_HEIGHT,
|
||||
terminal.getBackgroundColourLine( height - 1 ), palette, greyscale,
|
||||
leftMarginSize, rightMarginSize, bottomMarginSize
|
||||
);
|
||||
@@ -221,7 +210,7 @@ public final class FixedWidthFontRenderer
|
||||
for( int i = 0; i < height; i++ )
|
||||
{
|
||||
drawString(
|
||||
buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||
transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||
terminal.getLine( i ), terminal.getTextColourLine( i ), terminal.getBackgroundColourLine( i ),
|
||||
palette, greyscale, leftMarginSize, rightMarginSize
|
||||
);
|
||||
@@ -229,7 +218,7 @@ public final class FixedWidthFontRenderer
|
||||
}
|
||||
|
||||
public static void drawCursor(
|
||||
@Nonnull BufferBuilder buffer, float x, float y,
|
||||
@Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale
|
||||
)
|
||||
{
|
||||
@@ -254,75 +243,104 @@ public final class FixedWidthFontRenderer
|
||||
b = (float) colour[2];
|
||||
}
|
||||
|
||||
drawChar( buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b );
|
||||
drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawTerminal(
|
||||
@Nonnull BufferBuilder buffer, float x, float y,
|
||||
@Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
drawTerminalWithoutCursor( buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
drawCursor( buffer, x, y, terminal, greyscale );
|
||||
drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
drawCursor( transform, buffer, x, y, terminal, greyscale );
|
||||
}
|
||||
|
||||
public static void drawTerminal(
|
||||
@Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
bindFont();
|
||||
|
||||
IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
|
||||
IVertexBuilder buffer = renderer.getBuffer( TYPE );
|
||||
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
renderer.finish( TYPE );
|
||||
}
|
||||
|
||||
public static void drawTerminal(
|
||||
float x, float y, @Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
drawTerminal( IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull IRenderTypeBuffer renderer, float x, float y, float width, float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
drawQuad( transform, renderer.getBuffer( TYPE ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height )
|
||||
{
|
||||
bindFont();
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
begin( buffer );
|
||||
drawTerminal( buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
tessellator.draw();
|
||||
IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
|
||||
drawEmptyTerminal( transform, renderer, x, y, width, height );
|
||||
renderer.finish();
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( float x, float y, float width, float height )
|
||||
{
|
||||
bindFont();
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
begin( buffer );
|
||||
|
||||
Colour colour = Colour.Black;
|
||||
drawQuad( buffer, x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
|
||||
tessellator.draw();
|
||||
drawEmptyTerminal( IDENTITY, x, y, width, height );
|
||||
}
|
||||
|
||||
public static void drawBlocker( @Nonnull BufferBuilder buffer, float x, float y, float width, float height )
|
||||
public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull IRenderTypeBuffer renderer, float x, float y, float width, float height )
|
||||
{
|
||||
Colour colour = Colour.Black;
|
||||
drawQuad( buffer, x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
Colour colour = Colour.BLACK;
|
||||
drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
|
||||
public static void drawBlocker( float x, float y, float width, float height )
|
||||
{
|
||||
bindFont();
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
begin( buffer );
|
||||
drawBlocker( buffer, x, y, width, height );
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
public static void bindFont()
|
||||
private static void bindFont()
|
||||
{
|
||||
Minecraft.getInstance().getTextureManager().bindTexture( FONT );
|
||||
GlStateManager.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
|
||||
|
||||
GlStateManager.enableTexture();
|
||||
RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
|
||||
}
|
||||
|
||||
public static void begin( BufferBuilder buffer )
|
||||
private static final class Type extends RenderState
|
||||
{
|
||||
buffer.begin( GL11.GL_TRIANGLES, POSITION_COLOR_TEX );
|
||||
private static final int GL_MODE = GL11.GL_TRIANGLES;
|
||||
|
||||
private static final VertexFormat FORMAT = DefaultVertexFormats.POSITION_COLOR_TEX;
|
||||
|
||||
static final RenderType MAIN = RenderType.makeType(
|
||||
"terminal_font", FORMAT, GL_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.State.getBuilder()
|
||||
.texture( new RenderState.TextureState( FONT, false, false ) ) // blur, minimap
|
||||
.alpha( DEFAULT_ALPHA )
|
||||
.lightmap( LIGHTMAP_DISABLED )
|
||||
.writeMask( COLOR_WRITE )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
static final RenderType BLOCKER = RenderType.makeType(
|
||||
"terminal_blocker", FORMAT, GL_MODE, 256,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.State.getBuilder()
|
||||
.texture( new RenderState.TextureState( FONT, false, false ) ) // blur, minimap
|
||||
.alpha( DEFAULT_ALPHA )
|
||||
.writeMask( DEPTH_WRITE )
|
||||
.lightmap( LIGHTMAP_DISABLED )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
private Type( String name, Runnable setup, Runnable destroy )
|
||||
{
|
||||
super( name, setup, destroy );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
|
||||
@@ -134,17 +134,17 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
|
||||
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
|
||||
|
||||
// Draw a border around the terminal
|
||||
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
switch( m_family )
|
||||
{
|
||||
case Normal:
|
||||
case NORMAL:
|
||||
default:
|
||||
minecraft.getTextureManager().bindTexture( BACKGROUND_NORMAL );
|
||||
break;
|
||||
case Advanced:
|
||||
case ADVANCED:
|
||||
minecraft.getTextureManager().bindTexture( BACKGROUND_ADVANCED );
|
||||
break;
|
||||
case Command:
|
||||
case COMMAND:
|
||||
minecraft.getTextureManager().bindTexture( BACKGROUND_COMMAND );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
@@ -32,7 +32,7 @@ public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
|
||||
@Override
|
||||
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
minecraft.getTextureManager().bindTexture( BACKGROUND );
|
||||
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -33,7 +33,7 @@ public class GuiPrinter extends ContainerScreen<ContainerPrinter>
|
||||
@Override
|
||||
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
minecraft.getTextureManager().bindTexture( BACKGROUND );
|
||||
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
|
||||
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -18,6 +22,8 @@ import static dan200.computercraft.client.render.PrintoutRenderer.*;
|
||||
|
||||
public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
|
||||
{
|
||||
private static final Matrix4f IDENTITY = TransformationMatrix.identity().getMatrix();
|
||||
|
||||
private final boolean m_book;
|
||||
private final int m_pages;
|
||||
private final TextBuffer[] m_text;
|
||||
@@ -88,20 +94,22 @@ public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
|
||||
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw the printout
|
||||
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
GlStateManager.enableDepthTest();
|
||||
RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
drawBorder( guiLeft, guiTop, blitOffset, 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 );
|
||||
IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
|
||||
drawBorder( IDENTITY, renderer, guiLeft, guiTop, getBlitOffset(), m_page, m_pages, m_book );
|
||||
drawText( IDENTITY, renderer, guiLeft + X_TEXT_MARGIN, guiTop + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
|
||||
renderer.finish();
|
||||
}
|
||||
|
||||
@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--;
|
||||
setBlitOffset( getBlitOffset() - 1 );
|
||||
renderBackground();
|
||||
blitOffset++;
|
||||
setBlitOffset( getBlitOffset() + 1 );
|
||||
|
||||
super.render( mouseX, mouseY, partialTicks );
|
||||
renderHoveredToolTip( mouseX, mouseY );
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
|
||||
@@ -98,7 +98,7 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
|
||||
int slot = m_container.getSelectedSlot();
|
||||
if( slot >= 0 )
|
||||
{
|
||||
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.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 );
|
||||
@@ -110,11 +110,11 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
|
||||
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw term
|
||||
boolean advanced = m_family == ComputerFamily.Advanced;
|
||||
boolean advanced = m_family == ComputerFamily.ADVANCED;
|
||||
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
|
||||
|
||||
// Draw border/inventory
|
||||
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ import org.lwjgl.glfw.GLFW;
|
||||
import java.util.BitSet;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
||||
|
||||
public class WidgetTerminal implements IGuiEventListener
|
||||
{
|
||||
private static final float TERMINATE_TIME = 0.5f;
|
||||
@@ -173,8 +176,8 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FixedWidthFontRenderer.FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FixedWidthFontRenderer.FONT_HEIGHT);
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -197,8 +200,8 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FixedWidthFontRenderer.FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FixedWidthFontRenderer.FONT_HEIGHT);
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -224,8 +227,8 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FixedWidthFontRenderer.FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FixedWidthFontRenderer.FONT_HEIGHT);
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -249,8 +252,8 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FixedWidthFontRenderer.FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FixedWidthFontRenderer.FONT_HEIGHT);
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -318,19 +321,15 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
Terminal terminal = computer != null ? computer.getTerminal() : null;
|
||||
if( terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
originX, originY,
|
||||
terminal, !computer.isColour(), topMargin, bottomMargin, leftMargin, rightMargin
|
||||
);
|
||||
FixedWidthFontRenderer.drawTerminal( originX, originY, terminal, !computer.isColour(), topMargin, bottomMargin, leftMargin, rightMargin );
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = originX - leftMargin;
|
||||
int y = originY - rightMargin;
|
||||
int width = termWidth * FixedWidthFontRenderer.FONT_WIDTH + leftMargin + rightMargin;
|
||||
int height = termHeight * FixedWidthFontRenderer.FONT_HEIGHT + topMargin + bottomMargin;
|
||||
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( x, y, width, height );
|
||||
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||
originX - leftMargin, originY - rightMargin,
|
||||
termWidth * FONT_WIDTH + leftMargin + rightMargin,
|
||||
termHeight * FONT_HEIGHT + topMargin + bottomMargin
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ package dan200.computercraft.client.proxy;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
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.TurtlePlayerRenderer;
|
||||
@@ -15,7 +14,6 @@ import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
@@ -24,6 +22,8 @@ import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import net.minecraft.client.gui.ScreenManager;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -40,12 +40,22 @@ public final class ComputerCraftProxyClient
|
||||
{
|
||||
registerContainers();
|
||||
|
||||
// Setup TESRs
|
||||
ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() );
|
||||
ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() );
|
||||
ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() );
|
||||
// While turtles themselves are not transparent, their upgrades may be.
|
||||
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.turtleNormal, RenderType.getTranslucent() );
|
||||
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.turtleAdvanced, RenderType.getTranslucent() );
|
||||
|
||||
RenderingRegistry.registerEntityRenderingHandler( TurtlePlayer.class, TurtlePlayerRenderer::new );
|
||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.monitorNormal, RenderType.getCutout() );
|
||||
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.monitorAdvanced, RenderType.getCutout() );
|
||||
|
||||
// Setup TESRs
|
||||
ClientRegistry.bindTileEntityRenderer( TileMonitor.FACTORY_NORMAL, TileEntityMonitorRenderer::new );
|
||||
ClientRegistry.bindTileEntityRenderer( TileMonitor.FACTORY_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
ClientRegistry.bindTileEntityRenderer( TileTurtle.FACTORY_NORMAL, TileEntityTurtleRenderer::new );
|
||||
ClientRegistry.bindTileEntityRenderer( TileTurtle.FACTORY_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
// TODO: ClientRegistry.bindTileEntityRenderer( TileCable.FACTORY, x -> new TileEntityCableRenderer() );
|
||||
|
||||
RenderingRegistry.registerEntityRenderingHandler( TurtlePlayer.TYPE, TurtlePlayerRenderer::new );
|
||||
}
|
||||
|
||||
private static void registerContainers()
|
||||
|
||||
@@ -5,26 +5,27 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
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.Minecraft;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
|
||||
import net.minecraftforge.client.event.DrawHighlightEvent;
|
||||
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
|
||||
@@ -37,14 +38,12 @@ public final class CableHighlightRenderer
|
||||
* Draw an outline for a specific part of a cable "Multipart".
|
||||
*
|
||||
* @param event The event to observe
|
||||
* @see WorldRenderer#drawSelectionBox(ActiveRenderInfo, RayTraceResult, int)
|
||||
* @see WorldRenderer#drawSelectionBox(MatrixStack, IVertexBuilder, Entity, double, double, double, BlockPos, BlockState)
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public static void drawHighlight( DrawBlockHighlightEvent event )
|
||||
public static void drawHighlight( DrawHighlightEvent.HighlightBlock event )
|
||||
{
|
||||
if( event.getTarget().getType() != RayTraceResult.Type.BLOCK ) return;
|
||||
|
||||
BlockRayTraceResult hit = (BlockRayTraceResult) event.getTarget();
|
||||
BlockRayTraceResult hit = event.getTarget();
|
||||
BlockPos pos = hit.getPos();
|
||||
World world = event.getInfo().getRenderViewEntity().getEntityWorld();
|
||||
ActiveRenderInfo info = event.getInfo();
|
||||
@@ -59,31 +58,22 @@ public final class CableHighlightRenderer
|
||||
|
||||
event.setCanceled( true );
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
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.mainWindow.getFramebufferWidth() / 1920.0F * 2.5F ) );
|
||||
GlStateManager.disableTexture();
|
||||
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.getHitVec().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
|
||||
? CableShapes.getModemShape( state )
|
||||
: CableShapes.getCableShape( state );
|
||||
|
||||
Vec3d cameraPos = info.getProjectedView();
|
||||
WorldRenderer.drawShape(
|
||||
shape, pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ(),
|
||||
0.0F, 0.0F, 0.0F, 0.4F
|
||||
);
|
||||
double xOffset = pos.getX() - cameraPos.getX();
|
||||
double yOffset = pos.getY() - cameraPos.getY();
|
||||
double zOffset = pos.getZ() - cameraPos.getZ();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.matrixMode( GL11.GL_MODELVIEW );
|
||||
GlStateManager.depthMask( true );
|
||||
GlStateManager.enableTexture();
|
||||
GlStateManager.disableBlend();
|
||||
IVertexBuilder buffer = event.getBuffers().getBuffer( RenderType.getLines() );
|
||||
Matrix4f matrix4f = event.getMatrix().getLast().getMatrix();
|
||||
shape.forEachEdge( ( x1, y1, z1, x2, y2, z2 ) -> {
|
||||
buffer.pos( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
|
||||
.color( 0, 0, 0, 0.4f ).endVertex();
|
||||
buffer.pos( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
|
||||
.color( 0, 0, 0, 0.4f ).endVertex();
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.FirstPersonRenderer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Hand;
|
||||
@@ -19,99 +22,118 @@ public abstract class ItemMapLikeRenderer
|
||||
/**
|
||||
* The main rendering method for the item.
|
||||
*
|
||||
* @param stack The stack to render
|
||||
* @see FirstPersonRenderer#renderMapFirstPerson(ItemStack)
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param stack The stack to render
|
||||
* @see FirstPersonRenderer#renderItemInFirstPerson(AbstractClientPlayerEntity, float, float, Hand, float, ItemStack, float, MatrixStack, IRenderTypeBuffer, int)
|
||||
*/
|
||||
protected abstract void renderItem( ItemStack stack );
|
||||
protected abstract void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack );
|
||||
|
||||
protected void renderItemFirstPerson( Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
protected void renderItemFirstPerson( MatrixStack transform, IRenderTypeBuffer render, int lightTexture, Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
PlayerEntity player = Minecraft.getInstance().player;
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
transform.push();
|
||||
if( hand == Hand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
|
||||
{
|
||||
renderItemFirstPersonCenter( pitch, equipProgress, swingProgress, stack );
|
||||
renderItemFirstPersonCenter( transform, render, lightTexture, pitch, equipProgress, swingProgress, stack );
|
||||
}
|
||||
else
|
||||
{
|
||||
renderItemFirstPersonSide(
|
||||
transform, render, lightTexture,
|
||||
hand == Hand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
|
||||
equipProgress, swingProgress, stack
|
||||
);
|
||||
}
|
||||
GlStateManager.popMatrix();
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the item to one side of the player.
|
||||
*
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param combinedLight The current light level
|
||||
* @param side The side to render on
|
||||
* @param equipProgress The equip progress of this item
|
||||
* @param swingProgress The swing progress of this item
|
||||
* @param stack The stack to render
|
||||
* @see FirstPersonRenderer#renderMapFirstPersonSide(float, HandSide, float, ItemStack)
|
||||
* @see FirstPersonRenderer#renderMapFirstPersonSide(MatrixStack, IRenderTypeBuffer, int, float, HandSide, float, ItemStack)
|
||||
*/
|
||||
private void renderItemFirstPersonSide( HandSide side, float equipProgress, float swingProgress, ItemStack stack )
|
||||
private void renderItemFirstPersonSide( MatrixStack transform, IRenderTypeBuffer render, int combinedLight, HandSide side, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
float offset = side == HandSide.RIGHT ? 1f : -1f;
|
||||
GlStateManager.translatef( offset * 0.125f, -0.125f, 0f );
|
||||
transform.translate( offset * 0.125f, -0.125f, 0f );
|
||||
|
||||
// If the player is not invisible then render a single arm
|
||||
if( !minecraft.player.isInvisible() )
|
||||
{
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.rotatef( offset * 10f, 0f, 0f, 1f );
|
||||
minecraft.getFirstPersonRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
|
||||
GlStateManager.popMatrix();
|
||||
transform.push();
|
||||
transform.rotate( Vector3f.ZP.rotationDegrees( offset * 10f ) );
|
||||
minecraft.getFirstPersonRenderer().renderArmFirstPerson( transform, render, combinedLight, equipProgress, swingProgress, side );
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
// Setup the appropriate transformations. This is just copied from the
|
||||
// corresponding method in ItemRenderer.
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
|
||||
transform.push();
|
||||
transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
|
||||
float f1 = MathHelper.sqrt( swingProgress );
|
||||
float f2 = MathHelper.sin( f1 * (float) Math.PI );
|
||||
float f3 = -0.5f * f2;
|
||||
float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) );
|
||||
float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI );
|
||||
GlStateManager.translatef( offset * f3, f4 - 0.3f * f2, f5 );
|
||||
GlStateManager.rotatef( f2 * -45f, 1f, 0f, 0f );
|
||||
GlStateManager.rotatef( offset * f2 * -30f, 0f, 1f, 0f );
|
||||
transform.translate( offset * f3, f4 - 0.3f * f2, f5 );
|
||||
transform.rotate( Vector3f.XP.rotationDegrees( f2 * -45f ) );
|
||||
transform.rotate( Vector3f.YP.rotationDegrees( offset * f2 * -30f ) );
|
||||
|
||||
renderItem( stack );
|
||||
renderItem( transform, render, stack );
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an item in the middle of the screen.
|
||||
*
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param combinedLight The current light level
|
||||
* @param pitch The pitch of the player
|
||||
* @param equipProgress The equip progress of this item
|
||||
* @param swingProgress The swing progress of this item
|
||||
* @param stack The stack to render
|
||||
* @see FirstPersonRenderer#renderMapFirstPerson(float, float, float)
|
||||
* @see FirstPersonRenderer#renderMapFirstPerson(MatrixStack, IRenderTypeBuffer, int, float, float, float)
|
||||
*/
|
||||
private void renderItemFirstPersonCenter( float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
private void renderItemFirstPersonCenter( MatrixStack transform, IRenderTypeBuffer render, int combinedLight, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
FirstPersonRenderer renderer = Minecraft.getInstance().getFirstPersonRenderer();
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
FirstPersonRenderer renderer = minecraft.getFirstPersonRenderer();
|
||||
|
||||
// Setup the appropriate transformations. This is just copied from the
|
||||
// corresponding method in ItemRenderer.
|
||||
float swingRt = MathHelper.sqrt( swingProgress );
|
||||
float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
|
||||
float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
|
||||
GlStateManager.translatef( 0f, -tX / 2f, tZ );
|
||||
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();
|
||||
float rX = MathHelper.sin( swingRt * (float) Math.PI );
|
||||
GlStateManager.rotatef( rX * 20f, 1f, 0f, 0f );
|
||||
GlStateManager.scalef( 2f, 2f, 2f );
|
||||
transform.translate( 0, -tX / 2, tZ );
|
||||
|
||||
renderItem( stack );
|
||||
float pitchAngle = renderer.getMapAngleFromPitch( pitch );
|
||||
transform.translate( 0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
|
||||
transform.rotate( Vector3f.XP.rotationDegrees( pitchAngle * -85.0f ) );
|
||||
if( !minecraft.player.isInvisible() )
|
||||
{
|
||||
transform.push();
|
||||
transform.rotate( Vector3f.YP.rotationDegrees( 90.0F ) );
|
||||
renderer.renderArm( transform, render, combinedLight, HandSide.RIGHT );
|
||||
renderer.renderArm( transform, render, combinedLight, HandSide.LEFT );
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
float rX = MathHelper.sin( swingRt * (float) Math.PI );
|
||||
transform.rotate( Vector3f.XP.rotationDegrees( rX * 20.0F ) );
|
||||
transform.scale( 2.0F, 2.0F, 2.0F );
|
||||
|
||||
renderItem( transform, render, stack );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
@@ -14,12 +16,11 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.*;
|
||||
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.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -45,17 +46,20 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void renderItem( RenderSpecificHandEvent event )
|
||||
public static void onRenderInHand( RenderHandEvent 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() );
|
||||
INSTANCE.renderItemFirstPerson(
|
||||
event.getMatrixStack(), event.getBuffers(), event.getLight(),
|
||||
event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderItem( ItemStack stack )
|
||||
protected void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack )
|
||||
{
|
||||
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
|
||||
Terminal terminal = computer == null ? null : computer.getTerminal();
|
||||
@@ -77,50 +81,45 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
|
||||
// Setup various transformations. Note that these are partially adapted from the corresponding method
|
||||
// in ItemRenderer
|
||||
GlStateManager.pushMatrix();
|
||||
transform.push();
|
||||
transform.rotate( Vector3f.YP.rotationDegrees( 180f ) );
|
||||
transform.rotate( Vector3f.ZP.rotationDegrees( 180f ) );
|
||||
transform.scale( 0.5f, 0.5f, 0.5f );
|
||||
|
||||
GlStateManager.disableLighting();
|
||||
GlStateManager.disableDepthTest();
|
||||
|
||||
GlStateManager.rotatef( 180f, 0f, 1f, 0f );
|
||||
GlStateManager.rotatef( 180f, 0f, 0f, 1f );
|
||||
GlStateManager.scalef( 0.5f, 0.5f, 0.5f );
|
||||
|
||||
double scale = 0.75 / Math.max( width + FRAME * 2, height + FRAME * 2 + LIGHT_HEIGHT );
|
||||
GlStateManager.scaled( scale, scale, 0 );
|
||||
GlStateManager.translated( -0.5 * width, -0.5 * height, 0 );
|
||||
float scale = 0.75f / Math.max( width + FRAME * 2, height + FRAME * 2 + LIGHT_HEIGHT );
|
||||
transform.scale( scale, scale, 0 );
|
||||
transform.translate( -0.5 * width, -0.5 * height, 0 );
|
||||
|
||||
// Render the main frame
|
||||
ItemPocketComputer item = (ItemPocketComputer) stack.getItem();
|
||||
ComputerFamily family = item.getFamily();
|
||||
int frameColour = item.getColour( stack );
|
||||
renderFrame( family, frameColour, width, height );
|
||||
|
||||
Matrix4f matrix = transform.getLast().getMatrix();
|
||||
renderFrame( matrix, family, frameColour, width, height );
|
||||
|
||||
// Render the light
|
||||
int lightColour = ItemPocketComputer.getLightState( stack );
|
||||
if( lightColour == -1 ) lightColour = Colour.Black.getHex();
|
||||
renderLight( lightColour, width, height );
|
||||
if( lightColour == -1 ) lightColour = Colour.BLACK.getHex();
|
||||
renderLight( matrix, lightColour, width, height );
|
||||
|
||||
if( computer != null && terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal( MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
FixedWidthFontRenderer.drawTerminal( matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( 0, 0, width, height );
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( matrix, 0, 0, width, height );
|
||||
}
|
||||
|
||||
GlStateManager.enableDepthTest();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.popMatrix();
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private static void renderFrame( ComputerFamily family, int colour, int width, int height )
|
||||
private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height )
|
||||
{
|
||||
|
||||
Minecraft.getInstance().getTextureManager().bindTexture( colour != -1
|
||||
? BACKGROUND_COLOUR
|
||||
: family == ComputerFamily.Normal ? BACKGROUND_NORMAL : BACKGROUND_ADVANCED
|
||||
: family == ComputerFamily.NORMAL ? BACKGROUND_NORMAL : BACKGROUND_ADVANCED
|
||||
);
|
||||
|
||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||
@@ -129,38 +128,38 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR );
|
||||
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX );
|
||||
|
||||
// Top left, middle, right
|
||||
renderTexture( buffer, -FRAME, -FRAME, 12, 28, FRAME, FRAME, r, g, b );
|
||||
renderTexture( buffer, 0, -FRAME, 0, 0, width, FRAME, r, g, b );
|
||||
renderTexture( buffer, width, -FRAME, 24, 28, FRAME, FRAME, r, g, b );
|
||||
renderTexture( transform, buffer, -FRAME, -FRAME, 12, 28, FRAME, FRAME, r, g, b );
|
||||
renderTexture( transform, buffer, 0, -FRAME, 0, 0, width, FRAME, r, g, b );
|
||||
renderTexture( transform, buffer, width, -FRAME, 24, 28, FRAME, FRAME, r, g, b );
|
||||
|
||||
// Left and bright border
|
||||
renderTexture( buffer, -FRAME, 0, 0, 28, FRAME, height, r, g, b );
|
||||
renderTexture( buffer, width, 0, 36, 28, FRAME, height, r, g, b );
|
||||
renderTexture( transform, buffer, -FRAME, 0, 0, 28, FRAME, height, r, g, b );
|
||||
renderTexture( transform, buffer, width, 0, 36, 28, FRAME, height, r, g, b );
|
||||
|
||||
// Bottom left, middle, right. We do this in three portions: the top inner corners, an extended region for
|
||||
// lights, and then the bottom outer corners.
|
||||
renderTexture( buffer, -FRAME, height, 12, 40, FRAME, FRAME / 2, r, g, b );
|
||||
renderTexture( buffer, 0, height, 0, 12, width, FRAME / 2, r, g, b );
|
||||
renderTexture( buffer, width, height, 24, 40, FRAME, FRAME / 2, r, g, b );
|
||||
renderTexture( transform, buffer, -FRAME, height, 12, 40, FRAME, FRAME / 2, r, g, b );
|
||||
renderTexture( transform, buffer, 0, height, 0, 12, width, FRAME / 2, r, g, b );
|
||||
renderTexture( transform, buffer, width, height, 24, 40, FRAME, FRAME / 2, r, g, b );
|
||||
|
||||
renderTexture( buffer, -FRAME, height + FRAME / 2, 12, 44, FRAME, LIGHT_HEIGHT, FRAME, 4, r, g, b );
|
||||
renderTexture( buffer, 0, height + FRAME / 2, 0, 16, width, LIGHT_HEIGHT, FRAME, 4, r, g, b );
|
||||
renderTexture( buffer, width, height + FRAME / 2, 24, 44, FRAME, LIGHT_HEIGHT, FRAME, 4, r, g, b );
|
||||
renderTexture( transform, buffer, -FRAME, height + FRAME / 2, 12, 44, FRAME, LIGHT_HEIGHT, FRAME, 4, r, g, b );
|
||||
renderTexture( transform, buffer, 0, height + FRAME / 2, 0, 16, width, LIGHT_HEIGHT, FRAME, 4, r, g, b );
|
||||
renderTexture( transform, buffer, width, height + FRAME / 2, 24, 44, FRAME, LIGHT_HEIGHT, FRAME, 4, r, g, b );
|
||||
|
||||
renderTexture( buffer, -FRAME, height + LIGHT_HEIGHT + FRAME / 2, 12, 40 + FRAME / 2, FRAME, FRAME / 2, r, g, b );
|
||||
renderTexture( buffer, 0, height + LIGHT_HEIGHT + FRAME / 2, 0, 12 + FRAME / 2, width, FRAME / 2, r, g, b );
|
||||
renderTexture( buffer, width, height + LIGHT_HEIGHT + FRAME / 2, 24, 40 + FRAME / 2, FRAME, FRAME / 2, r, g, b );
|
||||
renderTexture( transform, buffer, -FRAME, height + LIGHT_HEIGHT + FRAME / 2, 12, 40 + FRAME / 2, FRAME, FRAME / 2, r, g, b );
|
||||
renderTexture( transform, buffer, 0, height + LIGHT_HEIGHT + FRAME / 2, 0, 12 + FRAME / 2, width, FRAME / 2, r, g, b );
|
||||
renderTexture( transform, buffer, width, height + LIGHT_HEIGHT + FRAME / 2, 24, 40 + FRAME / 2, FRAME, FRAME / 2, r, g, b );
|
||||
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
private static void renderLight( int colour, int width, int height )
|
||||
private static void renderLight( Matrix4f transform, int colour, int width, int height )
|
||||
{
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableTexture();
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.disableTexture();
|
||||
|
||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||
@@ -169,26 +168,26 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
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();
|
||||
buffer.pos( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.pos( transform, width, height + LIGHT_HEIGHT + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.pos( transform, width, height + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.pos( transform, width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
GlStateManager.enableTexture();
|
||||
RenderSystem.enableTexture();
|
||||
}
|
||||
|
||||
private static void renderTexture( BufferBuilder builder, int x, int y, int textureX, int textureY, int width, int height, float r, float g, float b )
|
||||
private static void renderTexture( Matrix4f transform, IVertexBuilder builder, int x, int y, int textureX, int textureY, int width, int height, float r, float g, float b )
|
||||
{
|
||||
renderTexture( builder, x, y, textureX, textureY, width, height, width, height, r, g, b );
|
||||
renderTexture( transform, builder, x, y, textureX, textureY, width, height, width, height, r, g, b );
|
||||
}
|
||||
|
||||
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 )
|
||||
private static void renderTexture( Matrix4f transform, IVertexBuilder 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.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();
|
||||
builder.pos( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).tex( textureX * scale, (textureY + textureHeight) * scale ).endVertex();
|
||||
builder.pos( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).tex( (textureX + textureWidth) * scale, (textureY + textureHeight) * scale ).endVertex();
|
||||
builder.pos( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).tex( (textureX + textureWidth) * scale, textureY * scale ).endVertex();
|
||||
builder.pos( transform, x, y, 0 ).color( r, g, b, 1.0f ).tex( textureX * scale, textureY * scale ).endVertex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.client.event.RenderItemInFrameEvent;
|
||||
import net.minecraftforge.client.event.RenderSpecificHandEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@@ -34,30 +37,26 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderInHand( RenderSpecificHandEvent event )
|
||||
public static void onRenderInHand( RenderHandEvent event )
|
||||
{
|
||||
ItemStack stack = event.getItemStack();
|
||||
if( !(stack.getItem() instanceof ItemPrintout) ) return;
|
||||
|
||||
event.setCanceled( true );
|
||||
INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
|
||||
INSTANCE.renderItemFirstPerson(
|
||||
event.getMatrixStack(), event.getBuffers(), event.getLight(),
|
||||
event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderItem( ItemStack stack )
|
||||
protected void renderItem( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack )
|
||||
{
|
||||
// Setup various transformations. Note that these are partially adapated from the corresponding method
|
||||
// in FirstPersonRenderer.renderFirstPersonMap
|
||||
GlStateManager.disableLighting();
|
||||
transform.rotate( Vector3f.XP.rotationDegrees( 180f ) );
|
||||
transform.scale( 0.42f, 0.42f, -0.42f );
|
||||
transform.translate( -0.5f, -0.48f, 0.0f );
|
||||
|
||||
GlStateManager.rotatef( 180f, 0f, 1f, 0f );
|
||||
GlStateManager.rotatef( 180f, 0f, 0f, 1f );
|
||||
GlStateManager.scalef( 0.42f, 0.42f, -0.42f );
|
||||
GlStateManager.translatef( -0.5f, -0.48f, 0.0f );
|
||||
|
||||
drawPrintout( stack );
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
drawPrintout( transform, render, stack );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -65,24 +64,20 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
{
|
||||
ItemStack stack = event.getItem();
|
||||
if( !(stack.getItem() instanceof ItemPrintout) ) return;
|
||||
|
||||
event.setCanceled( true );
|
||||
|
||||
GlStateManager.disableLighting();
|
||||
MatrixStack transform = event.getMatrix();
|
||||
|
||||
// Move a little bit forward to ensure we're not clipping with the frame
|
||||
GlStateManager.translatef( 0.0f, 0.0f, -0.001f );
|
||||
GlStateManager.rotatef( 180f, 0f, 0f, 1f );
|
||||
GlStateManager.scalef( 0.95f, 0.95f, -0.95f );
|
||||
GlStateManager.translatef( -0.5f, -0.5f, 0.0f );
|
||||
transform.translate( 0.0f, 0.0f, -0.001f );
|
||||
transform.rotate( Vector3f.ZP.rotationDegrees( 180f ) );
|
||||
transform.scale( 0.95f, 0.95f, -0.95f );
|
||||
transform.translate( -0.5f, -0.5f, 0.0f );
|
||||
|
||||
drawPrintout( stack );
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.disableBlend();
|
||||
drawPrintout( transform, event.getBuffers(), stack );
|
||||
}
|
||||
|
||||
private static void drawPrintout( ItemStack stack )
|
||||
private static void drawPrintout( MatrixStack transform, IRenderTypeBuffer render, ItemStack stack )
|
||||
{
|
||||
int pages = ItemPrintout.getPageCount( stack );
|
||||
boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||
@@ -105,11 +100,14 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
double max = Math.max( visualHeight, visualWidth );
|
||||
|
||||
// Scale the printout to fit correctly.
|
||||
double scale = 1.0 / max;
|
||||
GlStateManager.scaled( scale, scale, scale );
|
||||
GlStateManager.translated( (max - width) / 2.0, (max - height) / 2.0, 0.0 );
|
||||
float scale = (float) (1.0 / max);
|
||||
transform.scale( scale, scale, scale );
|
||||
transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 );
|
||||
|
||||
drawBorder( 0, 0, -0.01, 0, pages, book );
|
||||
drawText( X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
|
||||
Matrix4f matrix = transform.getLast().getMatrix();
|
||||
drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book );
|
||||
drawText( matrix, render,
|
||||
X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
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.Direction;
|
||||
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.Point3f;
|
||||
import javax.vecmath.Vector3f;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Transforms vertices of a model, remaining aware of winding order, and rearranging
|
||||
* vertices if needed.
|
||||
*/
|
||||
public final class ModelTransformer
|
||||
{
|
||||
private static final Matrix4f identity;
|
||||
|
||||
static
|
||||
{
|
||||
identity = new Matrix4f();
|
||||
identity.setIdentity();
|
||||
}
|
||||
|
||||
private ModelTransformer()
|
||||
{
|
||||
}
|
||||
|
||||
public static void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> input, Matrix4f transform )
|
||||
{
|
||||
if( transform == null || transform.equals( identity ) )
|
||||
{
|
||||
output.addAll( input );
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4f normalMatrix = new Matrix4f( transform );
|
||||
normalMatrix.invert();
|
||||
normalMatrix.transpose();
|
||||
|
||||
for( BakedQuad quad : input ) output.add( doTransformQuad( quad, transform, normalMatrix ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static BakedQuad transformQuad( BakedQuad input, Matrix4f transform )
|
||||
{
|
||||
if( transform == null || transform.equals( identity ) ) return input;
|
||||
|
||||
Matrix4f normalMatrix = new Matrix4f( transform );
|
||||
normalMatrix.invert();
|
||||
normalMatrix.transpose();
|
||||
return doTransformQuad( input, transform, normalMatrix );
|
||||
}
|
||||
|
||||
private static BakedQuad doTransformQuad( BakedQuad input, Matrix4f positionMatrix, Matrix4f normalMatrix )
|
||||
{
|
||||
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder( input.getFormat() );
|
||||
NormalAwareTransformer transformer = new NormalAwareTransformer( builder, positionMatrix, normalMatrix );
|
||||
input.pipe( transformer );
|
||||
|
||||
if( transformer.areNormalsInverted() )
|
||||
{
|
||||
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 Direction 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 Direction 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 Direction 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,49 +5,45 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
|
||||
import net.minecraftforge.client.event.DrawHighlightEvent;
|
||||
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.Direction.*;
|
||||
|
||||
/**
|
||||
* Overrides monitor highlighting to only render the outline of the <em>whole</em> monitor, rather than the current
|
||||
* block. This means you do not get an intrusive outline on top of the screen.
|
||||
*/
|
||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
|
||||
public final class MonitorHighlightRenderer
|
||||
{
|
||||
private static final float EXPAND = 0.002f;
|
||||
|
||||
private MonitorHighlightRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void drawHighlight( DrawBlockHighlightEvent event )
|
||||
public static void drawHighlight( DrawHighlightEvent.HighlightBlock event )
|
||||
{
|
||||
if( event.getTarget().getType() != RayTraceResult.Type.BLOCK || event.getInfo().getRenderViewEntity().isSneaking() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Preserve normal behaviour when crouching.
|
||||
if( event.getInfo().getRenderViewEntity().isCrouching() ) return;
|
||||
|
||||
World world = event.getInfo().getRenderViewEntity().getEntityWorld();
|
||||
BlockPos pos = ((BlockRayTraceResult) event.getTarget()).getPos();
|
||||
BlockPos pos = event.getTarget().getPos();
|
||||
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
if( !(tile instanceof TileMonitor) ) return;
|
||||
@@ -64,53 +60,37 @@ public final class MonitorHighlightRenderer
|
||||
if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() );
|
||||
if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() );
|
||||
|
||||
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) Minecraft.getInstance().mainWindow.getFramebufferWidth() / 1920.0F * 2.5F ) );
|
||||
GlStateManager.disableTexture();
|
||||
GlStateManager.depthMask( false );
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
MatrixStack transformStack = event.getMatrix();
|
||||
Vec3d cameraPos = event.getInfo().getProjectedView();
|
||||
GlStateManager.translated( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() );
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR );
|
||||
transformStack.push();
|
||||
transformStack.translate( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() );
|
||||
|
||||
// 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 );
|
||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( buffer, 0, 0, 1, UP );
|
||||
if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( buffer, 1, 0, 0, UP );
|
||||
if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( buffer, 1, 0, 1, UP );
|
||||
if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( buffer, 0, 0, 0, EAST );
|
||||
if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( buffer, 0, 0, 1, EAST );
|
||||
if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, 0, 1, 0, EAST );
|
||||
if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( buffer, 0, 1, 1, EAST );
|
||||
if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( buffer, 0, 0, 0, SOUTH );
|
||||
if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( buffer, 1, 0, 0, SOUTH );
|
||||
if( faces.contains( WEST ) || faces.contains( UP ) ) line( buffer, 0, 1, 0, SOUTH );
|
||||
if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, 1, 1, 0, SOUTH );
|
||||
IVertexBuilder buffer = event.getBuffers().getBuffer( RenderType.getLines() );
|
||||
Matrix4f transform = transformStack.getLast().getMatrix();
|
||||
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, 0, 0, 0, UP );
|
||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( buffer, transform, 0, 0, 1, UP );
|
||||
if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( buffer, transform, 1, 0, 0, UP );
|
||||
if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( buffer, transform, 1, 0, 1, UP );
|
||||
if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( buffer, transform, 0, 0, 0, EAST );
|
||||
if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( buffer, transform, 0, 0, 1, EAST );
|
||||
if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, transform, 0, 1, 0, EAST );
|
||||
if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( buffer, transform, 0, 1, 1, EAST );
|
||||
if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( buffer, transform, 0, 0, 0, SOUTH );
|
||||
if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( buffer, transform, 1, 0, 0, SOUTH );
|
||||
if( faces.contains( WEST ) || faces.contains( UP ) ) line( buffer, transform, 0, 1, 0, SOUTH );
|
||||
if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, transform, 1, 1, 0, SOUTH );
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.depthMask( true );
|
||||
GlStateManager.enableTexture();
|
||||
GlStateManager.disableBlend();
|
||||
transformStack.pop();
|
||||
}
|
||||
|
||||
private static void line( BufferBuilder buffer, int x, int y, int z, Direction direction )
|
||||
private static void line( IVertexBuilder buffer, Matrix4f transform, float x, float y, float z, Direction direction )
|
||||
{
|
||||
double minX = x == 0 ? -EXPAND : 1 + EXPAND;
|
||||
double minY = y == 0 ? -EXPAND : 1 + EXPAND;
|
||||
double minZ = z == 0 ? -EXPAND : 1 + EXPAND;
|
||||
|
||||
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)
|
||||
buffer.pos( transform, x, y, z ).color( 0, 0, 0, 0.4f ).endVertex();
|
||||
buffer.pos( transform,
|
||||
x + direction.getXOffset(),
|
||||
y + direction.getYOffset(),
|
||||
z + direction.getZOffset()
|
||||
).color( 0, 0, 0, 0.4f ).endVertex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
*/
|
||||
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 com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderState;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -24,7 +23,7 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
|
||||
public final class PrintoutRenderer
|
||||
{
|
||||
private static final ResourceLocation BG = new ResourceLocation( "computercraft", "textures/gui/printout.png" );
|
||||
private static final double BG_SIZE = 256.0;
|
||||
private static final float BG_SIZE = 256.0f;
|
||||
|
||||
/**
|
||||
* Width of a page.
|
||||
@@ -61,27 +60,24 @@ public final class PrintoutRenderer
|
||||
|
||||
private PrintoutRenderer() {}
|
||||
|
||||
public static void drawText( int x, int y, int start, TextBuffer[] text, TextBuffer[] colours )
|
||||
public static void drawText( Matrix4f transform, IRenderTypeBuffer renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours )
|
||||
{
|
||||
IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString(
|
||||
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||
x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], null, Palette.DEFAULT,
|
||||
false, 0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawText( int x, int y, int start, String[] text, String[] colours )
|
||||
public static void drawText( Matrix4f transform, IRenderTypeBuffer renderer, int x, int y, int start, String[] text, String[] colours )
|
||||
{
|
||||
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.enableTexture();
|
||||
GlStateManager.blendFuncSeparate( SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO );
|
||||
|
||||
IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString(
|
||||
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||
x, y + line * FONT_HEIGHT,
|
||||
new TextBuffer( text[start + line] ), new TextBuffer( colours[start + line] ),
|
||||
null, Palette.DEFAULT, false, 0, 0
|
||||
@@ -89,55 +85,46 @@ public final class PrintoutRenderer
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawBorder( double x, double y, double z, int page, int pages, boolean isBook )
|
||||
public static void drawBorder( Matrix4f transform, IRenderTypeBuffer renderer, float x, float y, float z, int page, int pages, boolean isBook )
|
||||
{
|
||||
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.enableTexture();
|
||||
GlStateManager.blendFuncSeparate( SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO );
|
||||
|
||||
Minecraft.getInstance().getTextureManager().bindTexture( BG );
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX );
|
||||
|
||||
int leftPages = page;
|
||||
int rightPages = pages - page - 1;
|
||||
|
||||
IVertexBuilder buffer = renderer.getBuffer( Type.TYPE );
|
||||
|
||||
if( isBook )
|
||||
{
|
||||
// Border
|
||||
double offset = offsetAt( pages );
|
||||
final double left = x - 4 - offset;
|
||||
final double right = x + X_SIZE + offset - 4;
|
||||
float offset = offsetAt( pages );
|
||||
float left = x - 4 - offset;
|
||||
float right = x + X_SIZE + offset - 4;
|
||||
|
||||
// Left and right border
|
||||
drawTexture( buffer, left - 4, y - 8, z - 0.02, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
|
||||
drawTexture( buffer, right, y - 8, z - 0.02, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
|
||||
drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
|
||||
drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
|
||||
|
||||
// Draw centre panel (just stretched texture, sorry).
|
||||
drawTexture( buffer,
|
||||
x - offset, y, z - 0.02, X_SIZE + offset * 2, Y_SIZE,
|
||||
drawTexture( transform, buffer,
|
||||
x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE,
|
||||
COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE
|
||||
);
|
||||
|
||||
double borderX = left;
|
||||
float borderX = left;
|
||||
while( borderX < right )
|
||||
{
|
||||
double thisWidth = Math.min( right - borderX, X_SIZE );
|
||||
drawTexture( buffer, borderX, y - 8, z - 0.02, 0, COVER_Y, thisWidth, COVER_SIZE );
|
||||
drawTexture( buffer, borderX, y + Y_SIZE - 4, z - 0.02, 0, COVER_Y + COVER_SIZE, thisWidth, COVER_SIZE );
|
||||
drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE );
|
||||
drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE );
|
||||
borderX += thisWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Left half
|
||||
drawTexture( buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE );
|
||||
drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE );
|
||||
for( int n = 0; n <= leftPages; n++ )
|
||||
{
|
||||
drawTexture( buffer,
|
||||
x - offsetAt( n ), y, z - 1e-3 * n,
|
||||
drawTexture( transform, buffer,
|
||||
x - offsetAt( n ), y, z - 1e-3f * n,
|
||||
// Use the left "bold" fold for the outermost page
|
||||
n == leftPages ? 0 : X_FOLD_SIZE, 0,
|
||||
X_FOLD_SIZE, Y_SIZE
|
||||
@@ -145,38 +132,54 @@ public final class PrintoutRenderer
|
||||
}
|
||||
|
||||
// Right half
|
||||
drawTexture( buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE );
|
||||
drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE );
|
||||
for( int n = 0; n <= rightPages; n++ )
|
||||
{
|
||||
drawTexture( buffer,
|
||||
x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3 * n,
|
||||
drawTexture( transform, buffer,
|
||||
x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
|
||||
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
|
||||
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0,
|
||||
X_FOLD_SIZE, Y_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double u, double v, double width, double height )
|
||||
private static void drawTexture( Matrix4f matrix, IVertexBuilder buffer, float x, float y, float z, float u, float v, float width, float height )
|
||||
{
|
||||
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();
|
||||
buffer.pos( matrix, x, y + height, z ).tex( u / BG_SIZE, (v + height) / BG_SIZE ).endVertex();
|
||||
buffer.pos( matrix, x + width, y + height, z ).tex( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).endVertex();
|
||||
buffer.pos( matrix, x + width, y, z ).tex( (u + width) / BG_SIZE, v / BG_SIZE ).endVertex();
|
||||
buffer.pos( matrix, 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 )
|
||||
private static void drawTexture( Matrix4f matrix, IVertexBuilder buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight )
|
||||
{
|
||||
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();
|
||||
buffer.pos( matrix, x, y + height, z ).tex( u / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex();
|
||||
buffer.pos( matrix, x + width, y + height, z ).tex( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex();
|
||||
buffer.pos( matrix, x + width, y, z ).tex( (u + tWidth) / BG_SIZE, v / BG_SIZE ).endVertex();
|
||||
buffer.pos( matrix, x, y, z ).tex( u / BG_SIZE, v / BG_SIZE ).endVertex();
|
||||
}
|
||||
|
||||
public static double offsetAt( int page )
|
||||
public static float offsetAt( int page )
|
||||
{
|
||||
return 32 * (1 - Math.pow( 1.2, -page ));
|
||||
return (float) (32 * (1 - Math.pow( 1.2, -page )));
|
||||
}
|
||||
|
||||
private static final class Type extends RenderState
|
||||
{
|
||||
static final RenderType TYPE = RenderType.makeType(
|
||||
"printout_background", DefaultVertexFormats.POSITION_TEX, GL11.GL_QUADS, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.State.getBuilder()
|
||||
.texture( new RenderState.TextureState( BG, false, false ) ) // blur, minimap
|
||||
.alpha( DEFAULT_ALPHA )
|
||||
.lightmap( LIGHTMAP_DISABLED )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
private Type( String name, Runnable setup, Runnable destroy )
|
||||
{
|
||||
super( name, setup, destroy );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
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;
|
||||
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.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
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.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Render breaking animation only over part of a {@link TileCable}.
|
||||
*/
|
||||
public class TileEntityCableRenderer extends TileEntityRenderer<TileCable>
|
||||
{
|
||||
private static final ResourceLocation[] DESTROY_STAGES = new ResourceLocation[10];
|
||||
private static final Random random = new Random();
|
||||
|
||||
static
|
||||
{
|
||||
for( int i = 0; i < DESTROY_STAGES.length; i++ )
|
||||
{
|
||||
DESTROY_STAGES[i] = new ResourceLocation( "block/destroy_stage_" + i );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileCable te, double x, double y, double z, float partialTicks, int destroyStage )
|
||||
{
|
||||
if( destroyStage < 0 ) return;
|
||||
|
||||
BlockPos pos = te.getPos();
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
RayTraceResult hit = mc.objectMouseOver;
|
||||
if( hit == null || hit.getType() != RayTraceResult.Type.BLOCK || !((BlockRayTraceResult) hit).getPos().equals( pos ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
World world = te.getWorld();
|
||||
BlockState state = world.getBlockState( pos );
|
||||
Block block = state.getBlock();
|
||||
if( block != ComputerCraft.Blocks.cable ) return;
|
||||
|
||||
state = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getHitVec().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
|
||||
? block.getDefaultState().with( BlockCable.MODEM, state.get( BlockCable.MODEM ) )
|
||||
: state.with( BlockCable.MODEM, CableModemVariant.None );
|
||||
|
||||
IBakedModel model = mc.getBlockRendererDispatcher().getModelForState( state );
|
||||
|
||||
preRenderDamagedBlocks();
|
||||
|
||||
ForgeHooksClient.setRenderLayer( block.getRenderLayer() );
|
||||
|
||||
// See BlockRendererDispatcher#renderBlockDamage
|
||||
TextureAtlasSprite breakingTexture = mc.getTextureMap().getSprite( DESTROY_STAGES[destroyStage] );
|
||||
|
||||
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();
|
||||
|
||||
mc.getBlockRendererDispatcher().getBlockModelRenderer().renderModel(
|
||||
world,
|
||||
ForgeHooksClient.getDamageModel( model, breakingTexture, state, world, pos, 0 ),
|
||||
state, pos, buffer, true, random, state.getPositionRandom( pos ), EmptyModelData.INSTANCE
|
||||
);
|
||||
|
||||
ForgeHooksClient.setRenderLayer( BlockRenderLayer.SOLID );
|
||||
|
||||
buffer.setTranslation( 0, 0, 0 );
|
||||
Tessellator.getInstance().draw();
|
||||
|
||||
postRenderDamagedBlocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the state for rendering block-breaking progress.
|
||||
*
|
||||
* @see WorldRenderer#preRenderDamagedBlocks()
|
||||
*/
|
||||
private void preRenderDamagedBlocks()
|
||||
{
|
||||
GlStateManager.disableLighting();
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFuncSeparate( GlStateManager.SourceFactor.DST_COLOR, GlStateManager.DestFactor.SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO );
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 0.5F );
|
||||
GlStateManager.polygonOffset( -3.0F, -3.0F );
|
||||
GlStateManager.enablePolygonOffset();
|
||||
GlStateManager.alphaFunc( 516, 0.1F );
|
||||
GlStateManager.enableAlphaTest();
|
||||
GlStateManager.pushMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down the state for rendering block-breaking progress.
|
||||
*
|
||||
* @see WorldRenderer#postRenderDamagedBlocks()
|
||||
*/
|
||||
private void postRenderDamagedBlocks()
|
||||
{
|
||||
GlStateManager.disableAlphaTest();
|
||||
GlStateManager.polygonOffset( 0.0F, 0.0F );
|
||||
GlStateManager.disablePolygonOffset();
|
||||
GlStateManager.disablePolygonOffset();
|
||||
GlStateManager.depthMask( true );
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GLX;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
@@ -14,25 +14,32 @@ import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.shared.peripheral.monitor.TileMonitor.RENDER_MARGIN;
|
||||
|
||||
public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
||||
{
|
||||
/**
|
||||
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between
|
||||
* the monitor frame and contents.
|
||||
*/
|
||||
private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1);
|
||||
|
||||
private static final Matrix4f IDENTITY = TransformationMatrix.identity().getMatrix();
|
||||
|
||||
public TileEntityMonitorRenderer( TileEntityRendererDispatcher rendererDispatcher )
|
||||
{
|
||||
super( rendererDispatcher );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileMonitor monitor, double posX, double posY, double posZ, float f, int i )
|
||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull MatrixStack transform, @Nonnull IRenderTypeBuffer renderer, int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render from the origin monitor
|
||||
ClientMonitor originTerminal = monitor.getClientMonitor();
|
||||
@@ -54,9 +61,6 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
||||
originTerminal.lastRenderPos = monitorPos;
|
||||
|
||||
BlockPos originPos = origin.getPos();
|
||||
posX += originPos.getX() - monitorPos.getX();
|
||||
posY += originPos.getY() - monitorPos.getY();
|
||||
posZ += originPos.getZ() - monitorPos.getZ();
|
||||
|
||||
// Determine orientation
|
||||
Direction dir = origin.getDirection();
|
||||
@@ -64,130 +68,94 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
||||
float yaw = dir.getHorizontalAngle();
|
||||
float pitch = DirectionUtil.toPitchAngle( front );
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
// Setup initial transform
|
||||
GlStateManager.translated( posX + 0.5, posY + 0.5, posZ + 0.5 );
|
||||
GlStateManager.rotatef( -yaw, 0.0f, 1.0f, 0.0f );
|
||||
GlStateManager.rotatef( pitch, 1.0f, 0.0f, 0.0f );
|
||||
GlStateManager.translated(
|
||||
-0.5 + TileMonitor.RENDER_BORDER + RENDER_MARGIN,
|
||||
origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + RENDER_MARGIN) + 0,
|
||||
transform.push();
|
||||
transform.translate(
|
||||
originPos.getX() - monitorPos.getX() + 0.5,
|
||||
originPos.getY() - monitorPos.getY() + 0.5,
|
||||
originPos.getZ() - monitorPos.getZ() + 0.5
|
||||
);
|
||||
|
||||
transform.rotate( Vector3f.YN.rotationDegrees( yaw ) );
|
||||
transform.rotate( Vector3f.XP.rotationDegrees( pitch ) );
|
||||
transform.translate(
|
||||
-0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN,
|
||||
origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0,
|
||||
0.5
|
||||
);
|
||||
double xSize = origin.getWidth() - 2.0 * (RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
double ySize = origin.getHeight() - 2.0 * (RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
|
||||
// Get renderers
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
// Set up render state for monitors. We disable writing to the depth buffer (we draw a "blocker" later),
|
||||
// and setup lighting so that we render with a glow.
|
||||
GlStateManager.depthMask( false );
|
||||
GLX.glMultiTexCoord2f( GLX.GL_TEXTURE1, 0xFFFF, 0xFFFF );
|
||||
GlStateManager.disableLighting();
|
||||
mc.gameRenderer.disableLightmap();
|
||||
double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
|
||||
// Draw the contents
|
||||
Terminal terminal = originTerminal.getTerminal();
|
||||
if( terminal != null )
|
||||
{
|
||||
boolean redraw = originTerminal.pollTerminalChanged();
|
||||
if( originTerminal.buffer == null )
|
||||
{
|
||||
originTerminal.createBuffer( MonitorRenderer.VBO );
|
||||
redraw = true;
|
||||
}
|
||||
VertexBuffer vbo = originTerminal.buffer;
|
||||
|
||||
// Draw a terminal
|
||||
double xScale = xSize / (terminal.getWidth() * FixedWidthFontRenderer.FONT_WIDTH);
|
||||
double yScale = ySize / (terminal.getHeight() * FixedWidthFontRenderer.FONT_HEIGHT);
|
||||
transform.push();
|
||||
transform.scale( (float) xScale, (float) -yScale, 1.0f );
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.scaled( (float) xScale, (float) -yScale, 1.0f );
|
||||
float xMargin = (float) (MARGIN / xScale);
|
||||
float yMargin = (float) (MARGIN / yScale);
|
||||
|
||||
renderTerminal( originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) );
|
||||
Matrix4f matrix = transform.getLast().getMatrix();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
if( redraw )
|
||||
{
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder builder = tessellator.getBuffer();
|
||||
builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor(
|
||||
IDENTITY, builder, 0, 0,
|
||||
terminal, !originTerminal.isColour(), yMargin, yMargin, xMargin, xMargin
|
||||
);
|
||||
|
||||
builder.finishDrawing();
|
||||
vbo.upload( builder );
|
||||
}
|
||||
|
||||
// Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate
|
||||
// render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick
|
||||
// for now.
|
||||
IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
|
||||
FixedWidthFontRenderer.TYPE.setupRenderState();
|
||||
|
||||
vbo.bindBuffer();
|
||||
FixedWidthFontRenderer.TYPE.getVertexFormat().setupBufferState( 0L );
|
||||
vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() );
|
||||
VertexBuffer.unbindBuffer();
|
||||
FixedWidthFontRenderer.TYPE.getVertexFormat().clearBufferState();
|
||||
|
||||
// We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is
|
||||
// reasonable.
|
||||
FixedWidthFontRenderer.drawCursor( matrix, buffer, 0, 0, terminal, !originTerminal.isColour() );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||
transform.getLast().getMatrix(), renderer,
|
||||
-MARGIN, MARGIN,
|
||||
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||
);
|
||||
}
|
||||
|
||||
// Tear down render state for monitors.
|
||||
GlStateManager.depthMask( true );
|
||||
mc.gameRenderer.enableLightmap();
|
||||
GlStateManager.enableLighting();
|
||||
|
||||
// Draw the depth blocker
|
||||
GlStateManager.colorMask( false, false, false, false );
|
||||
FixedWidthFontRenderer.drawBlocker(
|
||||
transform.getLast().getMatrix(), renderer,
|
||||
(float) -TileMonitor.RENDER_MARGIN, (float) TileMonitor.RENDER_MARGIN,
|
||||
(float) (xSize + 2 * TileMonitor.RENDER_MARGIN), (float) -(ySize + TileMonitor.RENDER_MARGIN * 2)
|
||||
);
|
||||
GlStateManager.colorMask( true, true, true, true );
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private static void renderTerminal( ClientMonitor monitor, float xMargin, float yMargin )
|
||||
{
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
boolean redraw = monitor.pollTerminalChanged();
|
||||
|
||||
// Setup the buffers if needed. We get the renderer here, to avoid the (unlikely) race condition between
|
||||
// creating the buffers and rendering.
|
||||
MonitorRenderer renderer = MonitorRenderer.current();
|
||||
if( monitor.createBuffer( renderer ) ) redraw = true;
|
||||
|
||||
FixedWidthFontRenderer.bindFont();
|
||||
|
||||
switch( renderer )
|
||||
{
|
||||
case VBO:
|
||||
{
|
||||
VertexBuffer vbo = monitor.buffer;
|
||||
if( redraw )
|
||||
{
|
||||
renderTerminalTo( monitor, buffer, xMargin, yMargin );
|
||||
buffer.finishDrawing();
|
||||
buffer.reset();
|
||||
vbo.bufferData( buffer.getByteBuffer() );
|
||||
}
|
||||
|
||||
vbo.bindBuffer();
|
||||
setupBufferFormat();
|
||||
vbo.drawArrays( GL11.GL_TRIANGLES );
|
||||
VertexBuffer.unbindBuffer();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't draw the cursor with a buffer, as it's dynamic and so we'll end up refreshing far more than is
|
||||
// reasonable.
|
||||
FixedWidthFontRenderer.begin( buffer );
|
||||
FixedWidthFontRenderer.drawCursor( buffer, 0, 0, monitor.getTerminal(), !monitor.isColour() );
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
private static void renderTerminalTo( ClientMonitor monitor, BufferBuilder buffer, float xMargin, float yMargin )
|
||||
{
|
||||
FixedWidthFontRenderer.begin( buffer );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor(
|
||||
buffer, 0, 0,
|
||||
monitor.getTerminal(), !monitor.isColour(), yMargin, yMargin, xMargin, xMargin
|
||||
);
|
||||
}
|
||||
|
||||
public static void setupBufferFormat()
|
||||
{
|
||||
int stride = FixedWidthFontRenderer.POSITION_COLOR_TEX.getSize();
|
||||
GlStateManager.vertexPointer( 3, GL11.GL_FLOAT, stride, 0 );
|
||||
GlStateManager.enableClientState( GL11.GL_VERTEX_ARRAY );
|
||||
|
||||
GlStateManager.colorPointer( 4, GL11.GL_UNSIGNED_BYTE, stride, 12 );
|
||||
GlStateManager.enableClientState( GL11.GL_COLOR_ARRAY );
|
||||
|
||||
GlStateManager.texCoordPointer( 2, GL11.GL_FLOAT, stride, 16 );
|
||||
GlStateManager.enableClientState( GL11.GL_TEXTURE_COORD_ARRAY );
|
||||
transform.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
@@ -13,31 +15,26 @@ 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.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.Atlases;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
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.AtlasTexture;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
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.opengl.GL11;
|
||||
|
||||
import javax.vecmath.Matrix4f;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -48,189 +45,147 @@ public class TileEntityTurtleRenderer extends TileEntityRenderer<TileTurtle>
|
||||
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 )
|
||||
private final Random random = new Random( 0 );
|
||||
|
||||
public TileEntityTurtleRenderer( TileEntityRendererDispatcher renderDispatcher )
|
||||
{
|
||||
if( tileEntity != null ) renderTurtleAt( tileEntity, posX, posY, posZ, partialTicks );
|
||||
super( renderDispatcher );
|
||||
}
|
||||
|
||||
public static ModelResourceLocation getTurtleModel( ComputerFamily family, boolean coloured )
|
||||
{
|
||||
switch( family )
|
||||
{
|
||||
case Normal:
|
||||
case NORMAL:
|
||||
default:
|
||||
return coloured ? COLOUR_TURTLE_MODEL : NORMAL_TURTLE_MODEL;
|
||||
case Advanced:
|
||||
case ADVANCED:
|
||||
return coloured ? COLOUR_TURTLE_MODEL : ADVANCED_TURTLE_MODEL;
|
||||
}
|
||||
}
|
||||
|
||||
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
||||
{
|
||||
if( overlay != null )
|
||||
{
|
||||
return new ModelResourceLocation( overlay, "inventory" );
|
||||
}
|
||||
else if( christmas )
|
||||
{
|
||||
return ELF_OVERLAY_MODEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( overlay != null ) return new ModelResourceLocation( overlay, "inventory" );
|
||||
if( christmas ) return ELF_OVERLAY_MODEL;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderTurtleAt( TileTurtle turtle, double posX, double posY, double posZ, float partialTicks )
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull IRenderTypeBuffer renderer, int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy().getLabel();
|
||||
RayTraceResult hit = rendererDispatcher.cameraHitResult;
|
||||
RayTraceResult hit = renderDispatcher.cameraHitResult;
|
||||
if( label != null && hit.getType() == RayTraceResult.Type.BLOCK && turtle.getPos().equals( ((BlockRayTraceResult) hit).getPos() ) )
|
||||
{
|
||||
setLightmapDisabled( true );
|
||||
GameRenderer.drawNameplate(
|
||||
getFontRenderer(), label,
|
||||
(float) posX + 0.5F, (float) posY + 1.2F, (float) posZ + 0.5F, 0,
|
||||
rendererDispatcher.renderInfo.getYaw(), rendererDispatcher.renderInfo.getPitch(), false
|
||||
);
|
||||
setLightmapDisabled( false );
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
FontRenderer font = renderDispatcher.fontRenderer;
|
||||
|
||||
transform.push();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.rotate( mc.getRenderManager().getCameraOrientation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.getLast().getMatrix();
|
||||
int opacity = (int) (mc.gameSettings.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.getStringWidth( label ) / 2.0f;
|
||||
font.renderString( label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord );
|
||||
font.renderString( label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
try
|
||||
transform.push();
|
||||
|
||||
// Setup the transform.
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
transform.translate( offset.x, offset.y, offset.z );
|
||||
|
||||
transform.translate( 0.5f, 0.5f, 0.5f );
|
||||
transform.rotate( Vector3f.YP.rotationDegrees( 180.0f - yaw ) );
|
||||
if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
|
||||
{
|
||||
BlockState state = turtle.getBlockState();
|
||||
// Setup the transform
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
GlStateManager.translated( posX + offset.x, posY + offset.y, posZ + offset.z );
|
||||
// Render the turtle
|
||||
GlStateManager.translatef( 0.5f, 0.5f, 0.5f );
|
||||
GlStateManager.rotatef( 180.0f - yaw, 0.0f, 1.0f, 0.0f );
|
||||
if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
|
||||
{
|
||||
// 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.CullFace.FRONT );
|
||||
}
|
||||
GlStateManager.translatef( -0.5f, -0.5f, -0.5f );
|
||||
// Render the turtle
|
||||
int colour = turtle.getColour();
|
||||
ComputerFamily family = turtle.getFamily();
|
||||
ResourceLocation overlay = turtle.getOverlay();
|
||||
|
||||
renderModel( state, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelResourceLocation overlayModel = getTurtleOverlayModel(
|
||||
overlay,
|
||||
HolidayUtil.getCurrentHoliday() == Holiday.Christmas
|
||||
);
|
||||
if( overlayModel != null )
|
||||
{
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA );
|
||||
try
|
||||
{
|
||||
renderModel( state, overlayModel, null );
|
||||
}
|
||||
finally
|
||||
{
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableCull();
|
||||
}
|
||||
}
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade( state, turtle, TurtleSide.Left, partialTicks );
|
||||
renderUpgrade( state, turtle, TurtleSide.Right, partialTicks );
|
||||
// Flip the model
|
||||
transform.scale( 1.0f, -1.0f, 1.0f );
|
||||
}
|
||||
finally
|
||||
transform.translate( -0.5f, -0.5f, -0.5f );
|
||||
|
||||
// Render the turtle
|
||||
int colour = turtle.getColour();
|
||||
ComputerFamily family = turtle.getFamily();
|
||||
ResourceLocation overlay = turtle.getOverlay();
|
||||
|
||||
IVertexBuilder buffer = renderer.getBuffer( Atlases.getTranslucentCullBlockType() );
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelResourceLocation overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.cullFace( GlStateManager.CullFace.BACK );
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
|
||||
}
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private void renderUpgrade( BlockState state, TileTurtle turtle, TurtleSide side, float f )
|
||||
private void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull IVertexBuilder renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade != null )
|
||||
{
|
||||
GlStateManager.pushMatrix();
|
||||
try
|
||||
{
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
GlStateManager.translatef( 0.0f, 0.5f, 0.5f );
|
||||
GlStateManager.rotatef( -toolAngle, 1.0f, 0.0f, 0.0f );
|
||||
GlStateManager.translatef( 0.0f, -0.5f, -0.5f );
|
||||
if( upgrade == null ) return;
|
||||
transform.push();
|
||||
|
||||
Pair<IBakedModel, Matrix4f> pair = upgrade.getModel( turtle.getAccess(), side );
|
||||
if( pair != null )
|
||||
{
|
||||
if( pair.getRight() != null )
|
||||
{
|
||||
ForgeHooksClient.multiplyCurrentGlMatrix( pair.getRight() );
|
||||
}
|
||||
if( pair.getLeft() != null )
|
||||
{
|
||||
renderModel( state, pair.getLeft(), null );
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
transform.translate( 0.0f, 0.5f, 0.5f );
|
||||
transform.rotate( Vector3f.XN.rotationDegrees( toolAngle ) );
|
||||
transform.translate( 0.0f, -0.5f, -0.5f );
|
||||
|
||||
TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
|
||||
model.getMatrix().push( transform );
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
|
||||
transform.pop();
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private void renderModel( BlockState state, ModelResourceLocation modelLocation, int[] tints )
|
||||
private void renderModel( @Nonnull MatrixStack transform, @Nonnull IVertexBuilder renderer, int lightmapCoord, int overlayLight, ModelResourceLocation modelLocation, int[] tints )
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ModelManager modelManager = mc.getItemRenderer().getItemModelMesher().getModelManager();
|
||||
renderModel( state, modelManager.getModel( modelLocation ), tints );
|
||||
ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelMesher().getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
private void renderModel( BlockState state, IBakedModel model, int[] tints )
|
||||
private void renderModel( @Nonnull MatrixStack transform, @Nonnull IVertexBuilder renderer, int lightmapCoord, int overlayLight, IBakedModel model, int[] tints )
|
||||
{
|
||||
Random random = new Random( 0 );
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
rendererDispatcher.textureManager.bindTexture( AtlasTexture.LOCATION_BLOCKS_TEXTURE );
|
||||
renderQuads( tessellator, model.getQuads( state, null, random, EmptyModelData.INSTANCE ), tints );
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random, EmptyModelData.INSTANCE ), tints );
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
renderQuads( tessellator, model.getQuads( state, facing, random, EmptyModelData.INSTANCE ), tints );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random, EmptyModelData.INSTANCE ), tints );
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderQuads( Tessellator tessellator, List<BakedQuad> quads, int[] tints )
|
||||
private static void renderQuads( @Nonnull MatrixStack transform, @Nonnull IVertexBuilder buffer, int lightmapCoord, int overlayLight, List<BakedQuad> quads, int[] tints )
|
||||
{
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
VertexFormat format = DefaultVertexFormats.ITEM;
|
||||
buffer.begin( GL11.GL_QUADS, format );
|
||||
for( BakedQuad quad : quads )
|
||||
MatrixStack.Entry matrix = transform.getLast();
|
||||
|
||||
for( BakedQuad bakedquad : quads )
|
||||
{
|
||||
VertexFormat quadFormat = quad.getFormat();
|
||||
if( quadFormat != format )
|
||||
int tint = -1;
|
||||
if( tints != null && bakedquad.hasTintIndex() )
|
||||
{
|
||||
tessellator.draw();
|
||||
format = quadFormat;
|
||||
buffer.begin( GL11.GL_QUADS, format );
|
||||
int idx = bakedquad.getTintIndex();
|
||||
if( idx >= 0 && idx < tints.length ) tint = tints[bakedquad.getTintIndex()];
|
||||
}
|
||||
|
||||
int colour = 0xFFFFFFFF;
|
||||
if( quad.hasTintIndex() && tints != null )
|
||||
{
|
||||
int index = quad.getTintIndex();
|
||||
if( index >= 0 && index < tints.length ) colour = tints[index] | 0xFF000000;
|
||||
}
|
||||
|
||||
LightUtil.renderQuadColor( buffer, quad, colour );
|
||||
float f = (float) (tint >> 16 & 255) / 255.0F;
|
||||
float f1 = (float) (tint >> 8 & 255) / 255.0F;
|
||||
float f2 = (float) (tint & 255) / 255.0F;
|
||||
buffer.addVertexData( matrix, bakedquad, f, f1, f2, lightmapCoord, overlayLight, true );
|
||||
}
|
||||
tessellator.draw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,28 +5,27 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.IUnbakedModel;
|
||||
import net.minecraft.client.renderer.model.ModelBakery;
|
||||
import net.minecraft.client.renderer.texture.ISprite;
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.JSONUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.ICustomModelLoader;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.IModelLoader;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class TurtleModelLoader implements ICustomModelLoader
|
||||
public final class TurtleModelLoader implements IModelLoader<TurtleModelLoader.TurtleModel>
|
||||
{
|
||||
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();
|
||||
@@ -40,32 +39,15 @@ public final class TurtleModelLoader implements ICustomModelLoader
|
||||
{
|
||||
}
|
||||
|
||||
@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
|
||||
@Override
|
||||
public IUnbakedModel loadModel( @Nonnull ResourceLocation name )
|
||||
public TurtleModel read( @Nonnull JsonDeserializationContext deserializationContext, @Nonnull JsonObject modelContents )
|
||||
{
|
||||
if( name.getNamespace().equals( ComputerCraft.MOD_ID ) )
|
||||
{
|
||||
switch( name.getPath() )
|
||||
{
|
||||
case "item/turtle_normal":
|
||||
return new TurtleModel( NORMAL_TURTLE_MODEL );
|
||||
case "item/turtle_advanced":
|
||||
return new TurtleModel( ADVANCED_TURTLE_MODEL );
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "Loader does not accept " + name );
|
||||
ResourceLocation model = new ResourceLocation( JSONUtils.getString( modelContents, "model" ) );
|
||||
return new TurtleModel( model );
|
||||
}
|
||||
|
||||
private static final class TurtleModel implements IUnbakedModel
|
||||
public static final class TurtleModel implements IModelGeometry<TurtleModel>
|
||||
{
|
||||
private final ResourceLocation family;
|
||||
|
||||
@@ -74,29 +56,21 @@ public final class TurtleModelLoader implements ICustomModelLoader
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
|
||||
{
|
||||
return Arrays.asList( family, COLOUR_TURTLE_MODEL );
|
||||
Set<Material> materials = new HashSet<>();
|
||||
materials.addAll( modelGetter.apply( family ).getTextures( modelGetter, missingTextureErrors ) );
|
||||
materials.addAll( modelGetter.apply( COLOUR_TURTLE_MODEL ).getTextures( modelGetter, missingTextureErrors ) );
|
||||
return materials;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<ResourceLocation> getTextures( @Nonnull Function<ResourceLocation, IUnbakedModel> modelGetter, @Nonnull Set<String> missingTextureErrors )
|
||||
{
|
||||
return getDependencies().stream()
|
||||
.flatMap( x -> modelGetter.apply( x ).getTextures( modelGetter, missingTextureErrors ).stream() )
|
||||
.collect( Collectors.toSet() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IBakedModel bake( @Nonnull ModelBakery bakery, @Nonnull Function<ResourceLocation, TextureAtlasSprite> spriteGetter, @Nonnull ISprite sprite, @Nonnull VertexFormat format )
|
||||
public IBakedModel bake( IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transform, ItemOverrideList overrides, ResourceLocation modelLocation )
|
||||
{
|
||||
return new TurtleSmartItemModel(
|
||||
bakery.getBakedModel( family, sprite, spriteGetter, format ),
|
||||
bakery.getBakedModel( COLOUR_TURTLE_MODEL, sprite, spriteGetter, format )
|
||||
bakery.getBakedModel( family, transform, spriteGetter ),
|
||||
bakery.getBakedModel( COLOUR_TURTLE_MODEL, transform, spriteGetter )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ItemOverrideList;
|
||||
@@ -13,32 +15,29 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
import net.minecraftforge.client.model.pipeline.TRSRTransformer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import java.util.*;
|
||||
|
||||
public class TurtleMultiModel implements IBakedModel
|
||||
{
|
||||
private final IBakedModel m_baseModel;
|
||||
private final IBakedModel m_overlayModel;
|
||||
private final Matrix4f m_generalTransform;
|
||||
private final IBakedModel m_leftUpgradeModel;
|
||||
private final Matrix4f m_leftUpgradeTransform;
|
||||
private final IBakedModel m_rightUpgradeModel;
|
||||
private final Matrix4f m_rightUpgradeTransform;
|
||||
private final TransformationMatrix m_generalTransform;
|
||||
private final TransformedModel m_leftUpgradeModel;
|
||||
private final TransformedModel m_rightUpgradeModel;
|
||||
private List<BakedQuad> m_generalQuads = null;
|
||||
private Map<Direction, List<BakedQuad>> m_faceQuads = new EnumMap<>( Direction.class );
|
||||
|
||||
public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, Matrix4f generalTransform, IBakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, IBakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
|
||||
public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, TransformationMatrix generalTransform, TransformedModel leftUpgradeModel, TransformedModel rightUpgradeModel )
|
||||
{
|
||||
// Get the models
|
||||
m_baseModel = baseModel;
|
||||
m_overlayModel = overlayModel;
|
||||
m_leftUpgradeModel = leftUpgradeModel;
|
||||
m_leftUpgradeTransform = leftUpgradeTransform;
|
||||
m_rightUpgradeModel = rightUpgradeModel;
|
||||
m_rightUpgradeTransform = rightUpgradeTransform;
|
||||
m_generalTransform = generalTransform;
|
||||
}
|
||||
|
||||
@@ -69,30 +68,22 @@ public class TurtleMultiModel implements IBakedModel
|
||||
private List<BakedQuad> buildQuads( BlockState state, Direction side, Random rand )
|
||||
{
|
||||
ArrayList<BakedQuad> quads = new ArrayList<>();
|
||||
ModelTransformer.transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform );
|
||||
|
||||
|
||||
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, EmptyModelData.INSTANCE ), m_generalTransform );
|
||||
transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform );
|
||||
}
|
||||
if( m_leftUpgradeModel != null )
|
||||
{
|
||||
Matrix4f upgradeTransform = m_generalTransform;
|
||||
if( m_leftUpgradeTransform != null )
|
||||
{
|
||||
upgradeTransform = new Matrix4f( m_generalTransform );
|
||||
upgradeTransform.mul( m_leftUpgradeTransform );
|
||||
}
|
||||
ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
|
||||
TransformationMatrix upgradeTransform = m_generalTransform.compose( m_leftUpgradeModel.getMatrix() );
|
||||
transformQuadsTo( quads, m_leftUpgradeModel.getModel().getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
|
||||
}
|
||||
if( m_rightUpgradeModel != null )
|
||||
{
|
||||
Matrix4f upgradeTransform = m_generalTransform;
|
||||
if( m_rightUpgradeTransform != null )
|
||||
{
|
||||
upgradeTransform = new Matrix4f( m_generalTransform );
|
||||
upgradeTransform.mul( m_rightUpgradeTransform );
|
||||
}
|
||||
ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
|
||||
TransformationMatrix upgradeTransform = m_generalTransform.compose( m_rightUpgradeModel.getMatrix() );
|
||||
transformQuadsTo( quads, m_rightUpgradeModel.getModel().getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
|
||||
}
|
||||
quads.trimToSize();
|
||||
return quads;
|
||||
@@ -116,6 +107,12 @@ public class TurtleMultiModel implements IBakedModel
|
||||
return m_baseModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
return m_baseModel.func_230044_c_();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
@@ -138,4 +135,15 @@ public class TurtleMultiModel implements IBakedModel
|
||||
{
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
private void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> quads, TransformationMatrix transform )
|
||||
{
|
||||
for( BakedQuad quad : quads )
|
||||
{
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
TRSRTransformer transformer = new TRSRTransformer( builder, transform );
|
||||
quad.pipe( transformer );
|
||||
output.add( builder.build() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.client.gui.GuiComputer;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
{
|
||||
@@ -22,16 +23,15 @@ public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
super( renderManager );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public void doRender( @Nonnull TurtlePlayer entity, double x, double y, double z, float entityYaw, float partialTicks )
|
||||
public ResourceLocation getEntityTexture( @Nonnull TurtlePlayer entity )
|
||||
{
|
||||
ComputerCraft.log.error( "Rendering TurtlePlayer on the client side, at {}", entity.getPosition() );
|
||||
return GuiComputer.BACKGROUND_NORMAL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture( @Nonnull TurtlePlayer entity )
|
||||
public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull MatrixStack transform, @Nonnull IRenderTypeBuffer buffer, int packedLightIn )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||
@@ -13,6 +15,7 @@ import dan200.computercraft.shared.util.Holiday;
|
||||
import dan200.computercraft.shared.util.HolidayUtil;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
@@ -21,28 +24,25 @@ import net.minecraft.util.Direction;
|
||||
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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TurtleSmartItemModel implements IBakedModel
|
||||
{
|
||||
private static final Matrix4f s_identity, s_flip;
|
||||
private static final TransformationMatrix identity, flip;
|
||||
|
||||
static
|
||||
{
|
||||
s_identity = new Matrix4f();
|
||||
s_identity.setIdentity();
|
||||
MatrixStack stack = new MatrixStack();
|
||||
stack.scale( 0, -1, 0 );
|
||||
stack.translate( 0, 0, 1 );
|
||||
|
||||
s_flip = new Matrix4f();
|
||||
s_flip.setIdentity();
|
||||
s_flip.m11 = -1; // Flip on the y axis
|
||||
s_flip.m13 = 1; // Models go from (0,0,0) to (1,1,1), so push back up.
|
||||
identity = TransformationMatrix.identity();
|
||||
flip = new TransformationMatrix( stack.getLast().getMatrix() );
|
||||
}
|
||||
|
||||
private static class TurtleModelCombination
|
||||
@@ -97,15 +97,14 @@ public class TurtleSmartItemModel implements IBakedModel
|
||||
private final IBakedModel familyModel;
|
||||
private final IBakedModel colourModel;
|
||||
|
||||
private HashMap<TurtleModelCombination, IBakedModel> m_cachedModels;
|
||||
private ItemOverrideList m_overrides;
|
||||
private final HashMap<TurtleModelCombination, IBakedModel> m_cachedModels = new HashMap<>();
|
||||
private final ItemOverrideList m_overrides;
|
||||
|
||||
public TurtleSmartItemModel( IBakedModel familyModel, IBakedModel colourModel )
|
||||
{
|
||||
this.familyModel = familyModel;
|
||||
this.colourModel = colourModel;
|
||||
|
||||
m_cachedModels = new HashMap<>();
|
||||
m_overrides = new ItemOverrideList()
|
||||
{
|
||||
@Nonnull
|
||||
@@ -114,10 +113,10 @@ public class TurtleSmartItemModel implements IBakedModel
|
||||
{
|
||||
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
||||
int colour = turtle.getColour( stack );
|
||||
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.Left );
|
||||
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
|
||||
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT );
|
||||
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT );
|
||||
ResourceLocation overlay = turtle.getOverlay( stack );
|
||||
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas;
|
||||
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 );
|
||||
@@ -144,25 +143,10 @@ public class TurtleSmartItemModel implements IBakedModel
|
||||
|
||||
IBakedModel baseModel = combo.m_colour ? colourModel : familyModel;
|
||||
IBakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
|
||||
Matrix4f transform = combo.m_flip ? s_flip : s_identity;
|
||||
Pair<IBakedModel, Matrix4f> leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
|
||||
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() );
|
||||
}
|
||||
else if( leftModel != null )
|
||||
{
|
||||
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel.getLeft(), leftModel.getRight(), null, null );
|
||||
}
|
||||
else if( rightModel != null )
|
||||
{
|
||||
return new TurtleMultiModel( baseModel, overlayModel, transform, null, null, rightModel.getLeft(), rightModel.getRight() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TurtleMultiModel( baseModel, overlayModel, transform, null, null, null, null );
|
||||
}
|
||||
TransformationMatrix transform = combo.m_flip ? flip : identity;
|
||||
TransformedModel leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.LEFT ) : null;
|
||||
TransformedModel rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null;
|
||||
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -199,6 +183,12 @@ public class TurtleSmartItemModel implements IBakedModel
|
||||
return familyModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
return familyModel.func_230044_c_();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.core.apis;
|
||||
|
||||
import com.google.common.net.InetAddresses;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Used to determine whether a domain or IP address matches a series of patterns.
|
||||
*/
|
||||
public class AddressPredicate
|
||||
{
|
||||
private static final class HostRange
|
||||
{
|
||||
private final byte[] min;
|
||||
private final byte[] max;
|
||||
|
||||
private HostRange( byte[] min, byte[] max )
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public boolean contains( InetAddress address )
|
||||
{
|
||||
byte[] entry = address.getAddress();
|
||||
if( entry.length != min.length ) return false;
|
||||
|
||||
for( int i = 0; i < entry.length; i++ )
|
||||
{
|
||||
int value = 0xFF & entry[i];
|
||||
if( value < (0xFF & min[i]) || value > (0xFF & max[i]) ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<Pattern> wildcards;
|
||||
private final List<HostRange> ranges;
|
||||
|
||||
public AddressPredicate( String... filters )
|
||||
{
|
||||
this( Arrays.asList( filters ) );
|
||||
}
|
||||
|
||||
public AddressPredicate( Iterable<? extends String> filters )
|
||||
{
|
||||
List<Pattern> wildcards = this.wildcards = new ArrayList<>();
|
||||
List<HostRange> ranges = this.ranges = new ArrayList<>();
|
||||
|
||||
for( String filter : filters )
|
||||
{
|
||||
int cidr = filter.indexOf( '/' );
|
||||
if( cidr >= 0 )
|
||||
{
|
||||
String addressStr = filter.substring( 0, cidr );
|
||||
String prefixSizeStr = filter.substring( cidr + 1 );
|
||||
|
||||
int prefixSize;
|
||||
try
|
||||
{
|
||||
prefixSize = Integer.parseInt( prefixSizeStr );
|
||||
}
|
||||
catch( NumberFormatException e )
|
||||
{
|
||||
ComputerCraft.log.error(
|
||||
"Malformed http whitelist/blacklist entry '{}': Cannot extract size of CIDR mask from '{}'.",
|
||||
filter, prefixSizeStr
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
InetAddress address;
|
||||
try
|
||||
{
|
||||
address = InetAddresses.forString( addressStr );
|
||||
}
|
||||
catch( IllegalArgumentException e )
|
||||
{
|
||||
ComputerCraft.log.error(
|
||||
"Malformed http whitelist/blacklist entry '{}': Cannot extract IP address from '{}'.",
|
||||
filter, prefixSizeStr
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mask the bytes of the IP address.
|
||||
byte[] minBytes = address.getAddress(), maxBytes = address.getAddress();
|
||||
int size = prefixSize;
|
||||
for( int i = 0; i < minBytes.length; i++ )
|
||||
{
|
||||
if( size <= 0 )
|
||||
{
|
||||
minBytes[i] &= 0;
|
||||
maxBytes[i] |= 0xFF;
|
||||
}
|
||||
else if( size < 8 )
|
||||
{
|
||||
minBytes[i] &= 0xFF << (8 - size);
|
||||
maxBytes[i] |= ~(0xFF << (8 - size));
|
||||
}
|
||||
|
||||
size -= 8;
|
||||
}
|
||||
|
||||
ranges.add( new HostRange( minBytes, maxBytes ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
wildcards.add( Pattern.compile( "^\\Q" + filter.replaceAll( "\\*", "\\\\E.*\\\\Q" ) + "\\E$" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a host name matches a series of patterns.
|
||||
*
|
||||
* This is intended to allow early exiting, before one has to look up the IP address. You should use
|
||||
* {@link #matches(InetAddress)} instead of/in addition to this one.
|
||||
*
|
||||
* @param domain The domain to match.
|
||||
* @return Whether the patterns were matched.
|
||||
*/
|
||||
public boolean matches( String domain )
|
||||
{
|
||||
for( Pattern domainPattern : wildcards )
|
||||
{
|
||||
if( domainPattern.matcher( domain ).matches() ) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchesAddress( InetAddress address )
|
||||
{
|
||||
String addressString = address.getHostAddress();
|
||||
for( Pattern domainPattern : wildcards )
|
||||
{
|
||||
if( domainPattern.matcher( addressString ).matches() ) return true;
|
||||
}
|
||||
|
||||
for( HostRange range : ranges )
|
||||
{
|
||||
if( range.contains( address ) ) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given address matches a series of patterns.
|
||||
*
|
||||
* @param address The address to check.
|
||||
* @return Whether it matches any of these patterns.
|
||||
*/
|
||||
public boolean matches( InetAddress address )
|
||||
{
|
||||
// Match the host name
|
||||
String host = address.getHostName();
|
||||
if( host != null && matches( host ) ) return true;
|
||||
|
||||
// Match the normal address
|
||||
if( matchesAddress( address ) ) return true;
|
||||
|
||||
// If we're an IPv4 address in disguise then let's check that.
|
||||
return address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
|
||||
&& matchesAddress( InetAddresses.get6to4IPv4Address( (Inet6Address) address ) );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.core.apis;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A stub for any mods which depended on this version of the argument helper.
|
||||
*
|
||||
* @deprecated Use {@link dan200.computercraft.api.lua.ArgumentHelper}.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ArgumentHelper
|
||||
{
|
||||
private ArgumentHelper()
|
||||
{
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String getType( @Nullable Object type )
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getType( type );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static LuaException badArgument( int index, @Nonnull String expected, @Nullable Object actual )
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.badArgumentOf( index, expected, actual );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual )
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.badArgument( index, expected, actual );
|
||||
}
|
||||
|
||||
public static double getNumber( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getDouble( args, index );
|
||||
}
|
||||
|
||||
public static int getInt( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getInt( args, index );
|
||||
}
|
||||
|
||||
public static long getLong( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getLong( args, index );
|
||||
}
|
||||
|
||||
public static double getReal( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getFiniteDouble( args, index );
|
||||
}
|
||||
|
||||
public static boolean getBoolean( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getBoolean( args, index );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String getString( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.getString( args, index );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public static Map<Object, Object> getTable( @Nonnull Object[] args, int index ) throws LuaException
|
||||
{
|
||||
return (Map<Object, Object>) dan200.computercraft.api.lua.ArgumentHelper.getTable( args, index );
|
||||
}
|
||||
|
||||
public static double optNumber( @Nonnull Object[] args, int index, double def ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.optDouble( args, index, def );
|
||||
}
|
||||
|
||||
public static int optInt( @Nonnull Object[] args, int index, int def ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.optInt( args, index, def );
|
||||
}
|
||||
|
||||
public static long optLong( @Nonnull Object[] args, int index, long def ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.optLong( args, index, def );
|
||||
}
|
||||
|
||||
public static double optReal( @Nonnull Object[] args, int index, double def ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.optFiniteDouble( args, index, def );
|
||||
}
|
||||
|
||||
public static boolean optBoolean( @Nonnull Object[] args, int index, boolean def ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.optBoolean( args, index, def );
|
||||
}
|
||||
|
||||
public static String optString( @Nonnull Object[] args, int index, String def ) throws LuaException
|
||||
{
|
||||
return dan200.computercraft.api.lua.ArgumentHelper.optString( args, index, def );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public static Map<Object, Object> optTable( @Nonnull Object[] args, int index, Map<Object, Object> def ) throws LuaException
|
||||
{
|
||||
return (Map<Object, Object>) dan200.computercraft.api.lua.ArgumentHelper.optTable( args, index, def );
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import dan200.computercraft.core.filesystem.FileSystem;
|
||||
import dan200.computercraft.core.filesystem.FileSystemException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@@ -123,7 +122,7 @@ public abstract class ComputerAccess implements IComputerAccess
|
||||
m_environment.queueEvent( event, arguments );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public IWorkMonitor getMainThreadMonitor()
|
||||
{
|
||||
|
||||
@@ -173,7 +173,7 @@ public class HTTPAPI implements ILuaAPI
|
||||
String address = getString( args, 0 );
|
||||
Map<?, ?> headerTbl = optTable( args, 1, Collections.emptyMap() );
|
||||
|
||||
if( !ComputerCraft.http_websocket_enable )
|
||||
if( !ComputerCraft.httpWebsocketEnabled )
|
||||
{
|
||||
throw new LuaException( "Websocket connections are disabled" );
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
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
|
||||
{
|
||||
void advance( double v );
|
||||
|
||||
@Override
|
||||
default void update()
|
||||
{
|
||||
advance( 0.05 );
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class OSAPI implements ILuaAPI
|
||||
double t = alarm.m_day * 24.0 + alarm.m_time;
|
||||
if( now >= t )
|
||||
{
|
||||
queueLuaEvent( "alarm", new Object[] { entry.getKey() } );
|
||||
queueLuaEvent( "alarm", new Object[] { entry.getIntKey() } );
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import dan200.computercraft.api.lua.ILuaAPI;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IWorkMonitor;
|
||||
import dan200.computercraft.api.peripheral.NotAttachedException;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
|
||||
@@ -122,53 +124,35 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
@Override
|
||||
public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName )
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
return super.mount( desiredLoc, mount, driveName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName )
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
return super.mountWritable( desiredLoc, mount, driveName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void unmount( String location )
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
super.unmount( location );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID()
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
return super.getID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueEvent( @Nonnull final String event, final Object[] arguments )
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
super.queueEvent( event, arguments );
|
||||
}
|
||||
|
||||
@@ -176,10 +160,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
@Override
|
||||
public String getAttachmentName()
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
return m_side;
|
||||
}
|
||||
|
||||
@@ -187,10 +168,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
@Override
|
||||
public Map<String, IPeripheral> getAvailablePeripherals()
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
|
||||
Map<String, IPeripheral> peripherals = new HashMap<>();
|
||||
for( PeripheralWrapper wrapper : m_peripherals )
|
||||
@@ -208,10 +186,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
@Override
|
||||
public IPeripheral getAvailablePeripheral( @Nonnull String name )
|
||||
{
|
||||
if( !m_attached )
|
||||
{
|
||||
throw new RuntimeException( "You are not attached to this Computer" );
|
||||
}
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
|
||||
for( PeripheralWrapper wrapper : m_peripherals )
|
||||
{
|
||||
@@ -222,6 +197,14 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IWorkMonitor getMainThreadMonitor()
|
||||
{
|
||||
if( !m_attached ) throw new NotAttachedException();
|
||||
return super.getMainThreadMonitor();
|
||||
}
|
||||
}
|
||||
|
||||
private final IAPIEnvironment m_environment;
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.core.apis.http;
|
||||
|
||||
import com.google.common.net.InetAddresses;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A pattern which matches an address, and controls whether it is accessible or not.
|
||||
*/
|
||||
public final class AddressRule
|
||||
{
|
||||
private static final class HostRange
|
||||
{
|
||||
private final byte[] min;
|
||||
private final byte[] max;
|
||||
|
||||
private HostRange( byte[] min, byte[] max )
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public boolean contains( InetAddress address )
|
||||
{
|
||||
byte[] entry = address.getAddress();
|
||||
if( entry.length != min.length ) return false;
|
||||
|
||||
for( int i = 0; i < entry.length; i++ )
|
||||
{
|
||||
int value = 0xFF & entry[i];
|
||||
if( value < (0xFF & min[i]) || value > (0xFF & max[i]) ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action
|
||||
{
|
||||
ALLOW,
|
||||
DENY,
|
||||
}
|
||||
|
||||
private final HostRange ip;
|
||||
private final Pattern domainPattern;
|
||||
private final Action action;
|
||||
|
||||
private AddressRule( HostRange ip, Pattern domainPattern, Action action )
|
||||
{
|
||||
this.ip = ip;
|
||||
this.domainPattern = domainPattern;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AddressRule parse( String filter, Action action )
|
||||
{
|
||||
int cidr = filter.indexOf( '/' );
|
||||
if( cidr >= 0 )
|
||||
{
|
||||
String addressStr = filter.substring( 0, cidr );
|
||||
String prefixSizeStr = filter.substring( cidr + 1 );
|
||||
|
||||
int prefixSize;
|
||||
try
|
||||
{
|
||||
prefixSize = Integer.parseInt( prefixSizeStr );
|
||||
}
|
||||
catch( NumberFormatException e )
|
||||
{
|
||||
ComputerCraft.log.error(
|
||||
"Malformed http whitelist/blacklist entry '{}': Cannot extract size of CIDR mask from '{}'.",
|
||||
filter, prefixSizeStr
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
InetAddress address;
|
||||
try
|
||||
{
|
||||
address = InetAddresses.forString( addressStr );
|
||||
}
|
||||
catch( IllegalArgumentException e )
|
||||
{
|
||||
ComputerCraft.log.error(
|
||||
"Malformed http whitelist/blacklist entry '{}': Cannot extract IP address from '{}'.",
|
||||
filter, prefixSizeStr
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Mask the bytes of the IP address.
|
||||
byte[] minBytes = address.getAddress(), maxBytes = address.getAddress();
|
||||
int size = prefixSize;
|
||||
for( int i = 0; i < minBytes.length; i++ )
|
||||
{
|
||||
if( size <= 0 )
|
||||
{
|
||||
minBytes[i] &= 0;
|
||||
maxBytes[i] |= 0xFF;
|
||||
}
|
||||
else if( size < 8 )
|
||||
{
|
||||
minBytes[i] &= 0xFF << (8 - size);
|
||||
maxBytes[i] |= ~(0xFF << (8 - size));
|
||||
}
|
||||
|
||||
size -= 8;
|
||||
}
|
||||
|
||||
return new AddressRule( new HostRange( minBytes, maxBytes ), null, action );
|
||||
}
|
||||
else
|
||||
{
|
||||
Pattern pattern = Pattern.compile( "^\\Q" + filter.replaceAll( "\\*", "\\\\E.*\\\\Q" ) + "\\E$" );
|
||||
return new AddressRule( null, pattern, action );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given address matches a series of patterns.
|
||||
*
|
||||
* @param domain The domain to match
|
||||
* @param address The address to check.
|
||||
* @return Whether it matches any of these patterns.
|
||||
*/
|
||||
public boolean matches( String domain, InetAddress address )
|
||||
{
|
||||
if( domainPattern != null )
|
||||
{
|
||||
if( domainPattern.matcher( domain ).matches() ) return true;
|
||||
if( domainPattern.matcher( address.getHostName() ).matches() ) return true;
|
||||
}
|
||||
|
||||
// Match the normal address
|
||||
if( matchesAddress( address ) ) return true;
|
||||
|
||||
// If we're an IPv4 address in disguise then let's check that.
|
||||
return address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
|
||||
&& matchesAddress( InetAddresses.get6to4IPv4Address( (Inet6Address) address ) );
|
||||
}
|
||||
|
||||
private boolean matchesAddress( InetAddress address )
|
||||
{
|
||||
if( domainPattern != null && domainPattern.matcher( address.getHostAddress() ).matches() ) return true;
|
||||
return ip != null && ip.contains( address );
|
||||
}
|
||||
|
||||
public static Action apply( Iterable<? extends AddressRule> rules, String domain, InetAddress address )
|
||||
{
|
||||
for( AddressRule rule : rules )
|
||||
{
|
||||
if( rule.matches( domain, address ) ) return rule.action;
|
||||
}
|
||||
|
||||
return Action.DENY;
|
||||
}
|
||||
}
|
||||
@@ -97,20 +97,6 @@ public final class NetworkUtils
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a host is allowed.
|
||||
*
|
||||
* @param host The domain to check against
|
||||
* @throws HTTPRequestException If the host is not permitted.
|
||||
*/
|
||||
public static void checkHost( String host ) throws HTTPRequestException
|
||||
{
|
||||
if( !ComputerCraft.http_whitelist.matches( host ) || ComputerCraft.http_blacklist.matches( host ) )
|
||||
{
|
||||
throw new HTTPRequestException( "Domain not permitted" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link InetSocketAddress} from the resolved {@code host} and port.
|
||||
*
|
||||
@@ -130,7 +116,7 @@ public final class NetworkUtils
|
||||
if( socketAddress.isUnresolved() ) throw new HTTPRequestException( "Unknown host" );
|
||||
|
||||
InetAddress address = socketAddress.getAddress();
|
||||
if( !ComputerCraft.http_whitelist.matches( address ) || ComputerCraft.http_blacklist.matches( address ) )
|
||||
if( AddressRule.apply( ComputerCraft.httpRules, host, address ) == AddressRule.Action.DENY )
|
||||
{
|
||||
throw new HTTPRequestException( "Domain not permitted" );
|
||||
}
|
||||
|
||||
@@ -119,8 +119,6 @@ public class HttpRequest extends Resource<HttpRequest>
|
||||
{
|
||||
throw new HTTPRequestException( "Invalid protocol '" + scheme + "'" );
|
||||
}
|
||||
|
||||
NetworkUtils.checkHost( url.getHost() );
|
||||
}
|
||||
|
||||
public void request( URI uri, HttpMethod method )
|
||||
|
||||
@@ -110,7 +110,6 @@ public class Websocket extends Resource<Websocket>
|
||||
throw new HTTPRequestException( "Invalid scheme '" + scheme + "'" );
|
||||
}
|
||||
|
||||
NetworkUtils.checkHost( uri.getHost() );
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ final class ComputerExecutor
|
||||
apis.add( new FSAPI( environment ) );
|
||||
apis.add( new PeripheralAPI( environment ) );
|
||||
apis.add( new OSAPI( environment ) );
|
||||
if( ComputerCraft.http_enable ) apis.add( new HTTPAPI( environment ) );
|
||||
if( ComputerCraft.httpEnabled ) apis.add( new HTTPAPI( environment ) );
|
||||
|
||||
// Load in the externally registered APIs.
|
||||
for( ILuaAPIFactory factory : ApiFactories.getAll() )
|
||||
@@ -611,7 +611,7 @@ final class ComputerExecutor
|
||||
terminal.reset();
|
||||
|
||||
// Display our primary error message
|
||||
if( colour ) terminal.setTextColour( 15 - Colour.Red.ordinal() );
|
||||
if( colour ) terminal.setTextColour( 15 - Colour.RED.ordinal() );
|
||||
terminal.write( message );
|
||||
|
||||
if( extra != null )
|
||||
@@ -624,7 +624,7 @@ final class ComputerExecutor
|
||||
|
||||
// And display our generic "CC may be installed incorrectly" message.
|
||||
terminal.setCursorPos( 0, terminal.getCursorY() + 1 );
|
||||
if( colour ) terminal.setTextColour( 15 - Colour.White.ordinal() );
|
||||
if( colour ) terminal.setTextColour( 15 - Colour.WHITE.ordinal() );
|
||||
terminal.write( "ComputerCraft may be installed incorrectly" );
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,15 @@ import dan200.computercraft.api.filesystem.IFileSystem;
|
||||
import dan200.computercraft.api.lua.IComputerSystem;
|
||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.apis.ComputerAccess;
|
||||
import dan200.computercraft.core.apis.IAPIEnvironment;
|
||||
import dan200.computercraft.core.filesystem.FileSystem;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of {@link IComputerAccess}/{@link IComputerSystem} for usage by externally registered APIs.
|
||||
@@ -54,4 +57,19 @@ public class ComputerSystem extends ComputerAccess implements IComputerSystem
|
||||
{
|
||||
return environment.getLabel();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Map<String, IPeripheral> getAvailablePeripherals()
|
||||
{
|
||||
// TODO: Should this return peripherals on the current computer?
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IPeripheral getAvailablePeripheral( @Nonnull String name )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import dan200.computercraft.api.filesystem.IMount;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
@@ -116,8 +115,7 @@ public class ComboMount implements IMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
for( int i = m_parts.length - 1; i >= 0; --i )
|
||||
{
|
||||
@@ -130,21 +128,6 @@ public class ComboMount implements IMount
|
||||
throw new FileOperationException( path, "No such file" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
for( int i = m_parts.length - 1; i >= 0; --i )
|
||||
{
|
||||
IMount part = m_parts[i];
|
||||
if( part.exists( path ) && !part.isDirectory( path ) )
|
||||
{
|
||||
return part.openChannelForRead( path );
|
||||
}
|
||||
}
|
||||
throw new FileOperationException( path, "No such file" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException
|
||||
|
||||
@@ -10,7 +10,6 @@ import dan200.computercraft.api.filesystem.IMount;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.List;
|
||||
|
||||
@@ -41,16 +40,7 @@ public class EmptyMount implements IMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
throw new FileOperationException( path, "No such file" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
throw new FileOperationException( path, "No such file" );
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import dan200.computercraft.api.filesystem.FileOperationException;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.file.*;
|
||||
@@ -200,21 +201,7 @@ public class FileMount implements IWritableMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
if( created() )
|
||||
{
|
||||
File file = getRealPath( path );
|
||||
if( file.exists() && !file.isDirectory() ) return new FileInputStream( file );
|
||||
}
|
||||
|
||||
throw new FileOperationException( path, "No such file" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
if( created() )
|
||||
{
|
||||
@@ -313,23 +300,7 @@ public class FileMount implements IWritableMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public OutputStream openForWrite( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newOutputStream( openChannelForWrite( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public OutputStream openForAppend( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newOutputStream( openChannelForAppend( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
|
||||
public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException
|
||||
{
|
||||
create();
|
||||
File file = getRealPath( path );
|
||||
@@ -350,7 +321,7 @@ public class FileMount implements IWritableMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
|
||||
public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException
|
||||
{
|
||||
if( !created() )
|
||||
{
|
||||
|
||||
@@ -9,9 +9,6 @@ import dan200.computercraft.api.filesystem.IFileSystem;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.Collections;
|
||||
@@ -55,7 +52,7 @@ public class FileSystemWrapperMount implements IFileSystem
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -70,7 +67,7 @@ public class FileSystemWrapperMount implements IFileSystem
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
|
||||
public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -84,7 +81,7 @@ public class FileSystemWrapperMount implements IFileSystem
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
|
||||
public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -96,30 +93,6 @@ public class FileSystemWrapperMount implements IFileSystem
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newInputStream( openChannelForRead( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public OutputStream openForWrite( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newOutputStream( openChannelForWrite( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public OutputStream openForAppend( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newOutputStream( openChannelForAppend( path ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingSpace() throws IOException
|
||||
{
|
||||
|
||||
@@ -184,15 +184,7 @@ public class JarMount implements IMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newInputStream( openChannelForRead( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
FileEntry file = get( path );
|
||||
if( file != null && !file.isDirectory() )
|
||||
|
||||
@@ -20,11 +20,11 @@ import java.util.OptionalLong;
|
||||
|
||||
class MountWrapper
|
||||
{
|
||||
private String label;
|
||||
private String location;
|
||||
private final String label;
|
||||
private final String location;
|
||||
|
||||
private IMount mount;
|
||||
private IWritableMount writableMount;
|
||||
private final IMount mount;
|
||||
private final IWritableMount writableMount;
|
||||
|
||||
MountWrapper( String label, String location, IMount mount )
|
||||
{
|
||||
@@ -36,7 +36,9 @@ class MountWrapper
|
||||
|
||||
MountWrapper( String label, String location, IWritableMount mount )
|
||||
{
|
||||
this( label, location, (IMount) mount );
|
||||
this.label = label;
|
||||
this.location = location;
|
||||
this.mount = mount;
|
||||
writableMount = mount;
|
||||
}
|
||||
|
||||
@@ -154,7 +156,7 @@ class MountWrapper
|
||||
{
|
||||
if( mount.exists( path ) && !mount.isDirectory( path ) )
|
||||
{
|
||||
return mount.openChannelForRead( path );
|
||||
return mount.openForRead( path );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -232,7 +234,7 @@ class MountWrapper
|
||||
writableMount.makeDirectory( dir );
|
||||
}
|
||||
}
|
||||
return writableMount.openChannelForWrite( path );
|
||||
return writableMount.openForWrite( path );
|
||||
}
|
||||
}
|
||||
catch( AccessDeniedException e )
|
||||
@@ -262,7 +264,7 @@ class MountWrapper
|
||||
writableMount.makeDirectory( dir );
|
||||
}
|
||||
}
|
||||
return writableMount.openChannelForWrite( path );
|
||||
return writableMount.openForWrite( path );
|
||||
}
|
||||
else if( mount.isDirectory( path ) )
|
||||
{
|
||||
@@ -270,7 +272,7 @@ class MountWrapper
|
||||
}
|
||||
else
|
||||
{
|
||||
return writableMount.openChannelForAppend( path );
|
||||
return writableMount.openForAppend( path );
|
||||
}
|
||||
}
|
||||
catch( AccessDeniedException e )
|
||||
|
||||
@@ -223,15 +223,7 @@ public final class ResourceMount implements IMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return Channels.newInputStream( openChannelForRead( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
FileEntry file = get( path );
|
||||
if( file != null && !file.isDirectory() )
|
||||
|
||||
@@ -9,7 +9,6 @@ import dan200.computercraft.api.filesystem.IMount;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.List;
|
||||
@@ -51,19 +50,11 @@ public class SubMount implements IMount
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public InputStream openForRead( @Nonnull String path ) throws IOException
|
||||
public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return parent.openForRead( getFullPath( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
|
||||
{
|
||||
return parent.openChannelForRead( getFullPath( path ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException
|
||||
|
||||
@@ -312,19 +312,6 @@ public class Terminal
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this terminal has changed.
|
||||
*
|
||||
* @return If this terminal is dirty.
|
||||
* @deprecated All {@code *Changed()} methods are deprecated: one should pass in a callback
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final boolean getChanged()
|
||||
{
|
||||
return m_changed;
|
||||
}
|
||||
|
||||
public final void setChanged()
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
@@ -14,9 +14,10 @@ import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DirectoryCache;
|
||||
import net.minecraft.data.IDataProvider;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.storage.loot.LootParameterSets;
|
||||
import net.minecraft.world.storage.loot.LootTable;
|
||||
import net.minecraft.world.storage.loot.LootTableManager;
|
||||
import net.minecraft.world.storage.loot.ValidationResults;
|
||||
import net.minecraft.world.storage.loot.ValidationTracker;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
@@ -42,17 +43,17 @@ public abstract class LootTableProvider implements IDataProvider
|
||||
@Override
|
||||
public void act( @Nonnull DirectoryCache cache )
|
||||
{
|
||||
|
||||
ValidationResults validation = new ValidationResults();
|
||||
Map<ResourceLocation, LootTable> tables = new HashMap<>();
|
||||
ValidationTracker validation = new ValidationTracker( LootParameterSets.GENERIC, x -> null, tables::get );
|
||||
|
||||
registerLoot( ( id, table ) -> {
|
||||
if( tables.containsKey( id ) ) validation.addProblem( "Duplicate loot tables for " + id );
|
||||
if( tables.containsKey( id ) ) validation.func_227530_a_( "Duplicate loot tables for " + id );
|
||||
tables.put( id, table );
|
||||
} );
|
||||
|
||||
tables.forEach( ( key, value ) -> LootTableManager.func_215302_a( validation, key, value, tables::get ) );
|
||||
tables.forEach( ( key, value ) -> LootTableManager.func_227508_a_( validation, key, value ) );
|
||||
|
||||
Multimap<String, String> problems = validation.getProblems();
|
||||
Multimap<String, String> problems = validation.func_227527_a_();
|
||||
if( !problems.isEmpty() )
|
||||
{
|
||||
problems.forEach( ( child, problem ) ->
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
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.AddressRule;
|
||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -19,13 +20,14 @@ import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
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;
|
||||
|
||||
@@ -50,8 +52,7 @@ public final class Config
|
||||
|
||||
private static final ConfigValue<Boolean> httpEnabled;
|
||||
private static final ConfigValue<Boolean> httpWebsocketEnabled;
|
||||
private static final ConfigValue<List<? extends String>> httpWhitelist;
|
||||
private static final ConfigValue<List<? extends String>> httpBlacklist;
|
||||
private static final ConfigValue<List<? extends UnmodifiableConfig>> httpRules;
|
||||
|
||||
private static final ConfigValue<Integer> httpTimeout;
|
||||
private static final ConfigValue<Integer> httpMaxRequests;
|
||||
@@ -151,25 +152,25 @@ public final class Config
|
||||
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 );
|
||||
.comment( "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)." )
|
||||
.define( "enabled", ComputerCraft.httpEnabled );
|
||||
|
||||
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 );
|
||||
.define( "websocket_enabled", ComputerCraft.httpWebsocketEnabled );
|
||||
|
||||
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 );
|
||||
httpRules = builder
|
||||
.comment( "A list of rules which control which domains or IPs are allowed through the \"http\" API on computers.\n" +
|
||||
"Each rule is an item with a 'host' to match against, and an action. " +
|
||||
"The host may be a domain name (\"pastebin.com\"),\n" +
|
||||
"wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). 'action' maybe 'allow' or 'block'. If no rules" +
|
||||
"match, the domain will be blocked." )
|
||||
.defineList( "rules",
|
||||
Stream.concat(
|
||||
Stream.of( ComputerCraft.DEFAULT_HTTP_DENY ).map( x -> makeRule( x, "deny" ) ),
|
||||
Stream.of( ComputerCraft.DEFAULT_HTTP_ALLOW ).map( x -> makeRule( x, "allow" ) )
|
||||
).collect( Collectors.toList() ),
|
||||
x -> x instanceof UnmodifiableConfig && parseRule( (UnmodifiableConfig) x ) != null );
|
||||
|
||||
httpTimeout = builder
|
||||
.comment( "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." )
|
||||
@@ -286,10 +287,10 @@ public final class Config
|
||||
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.httpEnabled = httpEnabled.get();
|
||||
ComputerCraft.httpWebsocketEnabled = httpWebsocketEnabled.get();
|
||||
ComputerCraft.httpRules = Collections.unmodifiableList( httpRules.get().stream()
|
||||
.map( Config::parseRule ).filter( Objects::nonNull ).collect( Collectors.toList() ) );
|
||||
|
||||
ComputerCraft.httpTimeout = httpTimeout.get();
|
||||
ComputerCraft.httpMaxRequests = httpMaxRequests.get();
|
||||
@@ -324,7 +325,7 @@ public final class Config
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void sync( ModConfig.ConfigReloading event )
|
||||
public static void sync( ModConfig.Reloading event )
|
||||
{
|
||||
// Ensure file configs are reloaded. Forge should probably do this, so worth checking in the future.
|
||||
CommentedConfig config = event.getConfig().getConfigData();
|
||||
@@ -346,4 +347,28 @@ public final class Config
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static UnmodifiableConfig makeRule( String host, String action )
|
||||
{
|
||||
com.electronwill.nightconfig.core.Config config = com.electronwill.nightconfig.core.Config.inMemory();
|
||||
config.add( "host", host );
|
||||
config.add( "action", action );
|
||||
return config;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static AddressRule parseRule( UnmodifiableConfig builder )
|
||||
{
|
||||
Object hostObj = builder.get( "host" );
|
||||
Object actionObj = builder.get( "action" );
|
||||
if( !(hostObj instanceof String) || !(actionObj instanceof String) ) return null;
|
||||
|
||||
String host = (String) hostObj, action = (String) actionObj;
|
||||
for( AddressRule.Action candiate : AddressRule.Action.values() )
|
||||
{
|
||||
if( candiate.name().equalsIgnoreCase( action ) ) return AddressRule.parse( host, candiate );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,17 +84,17 @@ public final class Registry
|
||||
// Computers
|
||||
ComputerCraft.Blocks.computerNormal = new BlockComputer(
|
||||
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.0f ),
|
||||
ComputerFamily.Normal, TileComputer.FACTORY_NORMAL
|
||||
ComputerFamily.NORMAL, TileComputer.FACTORY_NORMAL
|
||||
);
|
||||
|
||||
ComputerCraft.Blocks.computerAdvanced = new BlockComputer(
|
||||
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.0f ),
|
||||
ComputerFamily.Advanced, TileComputer.FACTORY_ADVANCED
|
||||
ComputerFamily.ADVANCED, TileComputer.FACTORY_ADVANCED
|
||||
);
|
||||
|
||||
ComputerCraft.Blocks.computerCommand = new BlockComputer(
|
||||
Block.Properties.create( Material.ROCK ).hardnessAndResistance( -1, 6000000.0F ),
|
||||
ComputerFamily.Command, TileCommandComputer.FACTORY
|
||||
ComputerFamily.COMMAND, TileCommandComputer.FACTORY
|
||||
);
|
||||
|
||||
registry.registerAll(
|
||||
@@ -106,12 +106,12 @@ public final class Registry
|
||||
// Turtles
|
||||
ComputerCraft.Blocks.turtleNormal = new BlockTurtle(
|
||||
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f ),
|
||||
ComputerFamily.Normal, TileTurtle.FACTORY_NORMAL
|
||||
ComputerFamily.NORMAL, TileTurtle.FACTORY_NORMAL
|
||||
);
|
||||
|
||||
ComputerCraft.Blocks.turtleAdvanced = new BlockTurtle(
|
||||
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f ),
|
||||
ComputerFamily.Advanced, TileTurtle.FACTORY_ADVANCED
|
||||
ComputerFamily.ADVANCED, TileTurtle.FACTORY_ADVANCED
|
||||
);
|
||||
|
||||
registry.registerAll(
|
||||
@@ -234,8 +234,8 @@ public final class Registry
|
||||
);
|
||||
|
||||
// Pocket computer
|
||||
ComputerCraft.Items.pocketComputerNormal = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.Normal );
|
||||
ComputerCraft.Items.pocketComputerAdvanced = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.Advanced );
|
||||
ComputerCraft.Items.pocketComputerNormal = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.NORMAL );
|
||||
ComputerCraft.Items.pocketComputerAdvanced = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.ADVANCED );
|
||||
|
||||
registry.registerAll(
|
||||
ComputerCraft.Items.pocketComputerNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_normal" ) ),
|
||||
|
||||
@@ -205,7 +205,7 @@ public final class CommandComputerCraft
|
||||
int queued = 0;
|
||||
for( ServerComputer computer : computers )
|
||||
{
|
||||
if( computer.getFamily() == ComputerFamily.Command && computer.isOn() )
|
||||
if( computer.getFamily() == ComputerFamily.COMMAND && computer.isOn() )
|
||||
{
|
||||
computer.queueEvent( "computer_command", rest );
|
||||
queued++;
|
||||
|
||||
@@ -11,12 +11,14 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -45,12 +47,13 @@ public abstract class BlockGeneric extends Block
|
||||
if( tile instanceof TileGeneric ) ((TileGeneric) tile).destroy();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public final boolean onBlockActivated( BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public final ActionResultType onBlockActivated( BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
return tile instanceof TileGeneric && ((TileGeneric) tile).onActivate( player, hand, hit );
|
||||
return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate( player, hand, hit ) : ActionResultType.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +73,7 @@ public abstract class BlockGeneric extends Block
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void tick( BlockState state, World world, BlockPos pos, Random rand )
|
||||
public void tick( BlockState state, ServerWorld world, BlockPos pos, Random rand )
|
||||
{
|
||||
TileEntity te = world.getTileEntity( pos );
|
||||
if( te instanceof TileGeneric ) ((TileGeneric) te).blockTick();
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
@@ -37,9 +38,10 @@ public abstract class TileGeneric extends TileEntity
|
||||
getWorld().notifyBlockUpdate( pos, state, state, 3 );
|
||||
}
|
||||
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
@Nonnull
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
return false;
|
||||
return ActionResultType.PASS;
|
||||
}
|
||||
|
||||
public void onNeighbourChange( @Nonnull BlockPos neighbour )
|
||||
|
||||
@@ -32,7 +32,7 @@ public class TileCommandComputer extends TileComputer
|
||||
{
|
||||
public static final NamedTileEntityType<TileCommandComputer> FACTORY = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "command_computer" ),
|
||||
f -> new TileCommandComputer( ComputerFamily.Command, f )
|
||||
f -> new TileCommandComputer( ComputerFamily.COMMAND, f )
|
||||
);
|
||||
|
||||
public class CommandReceiver implements ICommandSource
|
||||
|
||||
@@ -27,12 +27,12 @@ public class TileComputer extends TileComputerBase
|
||||
{
|
||||
public static final NamedTileEntityType<TileComputer> FACTORY_NORMAL = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "computer_normal" ),
|
||||
f -> new TileComputer( ComputerFamily.Normal, f )
|
||||
f -> new TileComputer( ComputerFamily.NORMAL, f )
|
||||
);
|
||||
|
||||
public static final NamedTileEntityType<TileComputer> FACTORY_ADVANCED = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "computer_advanced" ),
|
||||
f -> new TileComputer( ComputerFamily.Advanced, f )
|
||||
f -> new TileComputer( ComputerFamily.ADVANCED, f )
|
||||
);
|
||||
|
||||
private ComputerProxy m_proxy;
|
||||
|
||||
@@ -30,6 +30,7 @@ import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.INameable;
|
||||
@@ -102,8 +103,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
ItemStack currentItem = player.getHeldItem( hand );
|
||||
if( !currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && canNameWithTag( player ) && currentItem.hasDisplayName() )
|
||||
@@ -114,9 +116,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
setLabel( currentItem.getDisplayName().getString() );
|
||||
currentItem.shrink( 1 );
|
||||
}
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
else if( !player.isSneaking() )
|
||||
else if( !player.isCrouching() )
|
||||
{
|
||||
// Regular right click to activate computer
|
||||
if( !getWorld().isRemote && isUsable( player, false ) )
|
||||
@@ -124,9 +126,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
createServerComputer().turnOn();
|
||||
new ComputerContainerData( createServerComputer() ).open( player, this );
|
||||
}
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
return false;
|
||||
return ActionResultType.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,7 +7,7 @@ package dan200.computercraft.shared.computer.core;
|
||||
|
||||
public enum ComputerFamily
|
||||
{
|
||||
Normal,
|
||||
Advanced,
|
||||
Command
|
||||
NORMAL,
|
||||
ADVANCED,
|
||||
COMMAND
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
|
||||
public ServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight )
|
||||
{
|
||||
super( family != ComputerFamily.Normal, terminalWidth, terminalHeight );
|
||||
super( family != ComputerFamily.NORMAL, terminalWidth, terminalHeight );
|
||||
m_instanceID = instanceID;
|
||||
|
||||
m_world = world;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class ContainerViewComputer extends ContainerComputerBase implements ICon
|
||||
}
|
||||
|
||||
// If we're a command computer then ensure we're in creative
|
||||
if( computer.getFamily() == ComputerFamily.Command )
|
||||
if( computer.getFamily() == ComputerFamily.COMMAND )
|
||||
{
|
||||
MinecraftServer server = player.getServer();
|
||||
if( server == null || !server.isCommandBlockEnabled() )
|
||||
|
||||
@@ -29,11 +29,11 @@ public final class ComputerItemFactory
|
||||
{
|
||||
switch( family )
|
||||
{
|
||||
case Normal:
|
||||
case NORMAL:
|
||||
return ComputerCraft.Items.computerNormal.create( id, label );
|
||||
case Advanced:
|
||||
case ADVANCED:
|
||||
return ComputerCraft.Items.computerAdvanced.create( id, label );
|
||||
case Command:
|
||||
case COMMAND:
|
||||
return ComputerCraft.Items.computerCommand.create( id, label );
|
||||
default:
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
@@ -80,7 +80,7 @@ public abstract class ItemComputerBase extends BlockItem implements IComputerIte
|
||||
public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world )
|
||||
{
|
||||
ComputerFamily family = getFamily();
|
||||
if( family != ComputerFamily.Command )
|
||||
if( family != ComputerFamily.COMMAND )
|
||||
{
|
||||
int id = getComputerID( stack );
|
||||
if( id >= 0 )
|
||||
|
||||
@@ -116,8 +116,8 @@ public class JEIComputerCraft implements IModPlugin
|
||||
StringBuilder name = new StringBuilder();
|
||||
|
||||
// Add left and right upgrades to the identifier
|
||||
ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.Left );
|
||||
ITurtleUpgrade right = turtle.getUpgrade( stack, TurtleSide.Right );
|
||||
ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.LEFT );
|
||||
ITurtleUpgrade right = turtle.getUpgrade( stack, TurtleSide.RIGHT );
|
||||
if( left != null ) name.append( left.getUpgradeID() );
|
||||
if( left != null && right != null ) name.append( '|' );
|
||||
if( right != null ) name.append( right.getUpgradeID() );
|
||||
|
||||
@@ -37,7 +37,7 @@ import static net.minecraft.util.NonNullList.from;
|
||||
|
||||
class RecipeResolver implements IRecipeManagerPlugin
|
||||
{
|
||||
static final ComputerFamily[] MAIN_FAMILIES = new ComputerFamily[] { ComputerFamily.Normal, ComputerFamily.Advanced };
|
||||
static final ComputerFamily[] MAIN_FAMILIES = new ComputerFamily[] { ComputerFamily.NORMAL, ComputerFamily.ADVANCED };
|
||||
|
||||
private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
|
||||
private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
|
||||
@@ -150,8 +150,8 @@ class RecipeResolver implements IRecipeManagerPlugin
|
||||
{
|
||||
// Suggest possible upgrades which can be applied to this turtle
|
||||
ITurtleItem item = (ITurtleItem) stack.getItem();
|
||||
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.Left );
|
||||
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.Right );
|
||||
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
|
||||
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
|
||||
if( left != null && right != null ) return Collections.emptyList();
|
||||
|
||||
List<Shaped> recipes = new ArrayList<>();
|
||||
@@ -231,8 +231,8 @@ class RecipeResolver implements IRecipeManagerPlugin
|
||||
ITurtleItem item = (ITurtleItem) stack.getItem();
|
||||
List<Shaped> recipes = new ArrayList<>( 0 );
|
||||
|
||||
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.Left );
|
||||
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.Right );
|
||||
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
|
||||
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
|
||||
|
||||
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
|
||||
if( left != null )
|
||||
|
||||
@@ -126,6 +126,6 @@ public class ItemDisk extends Item implements IMedia, IColouredItem
|
||||
public int getColour( @Nonnull ItemStack stack )
|
||||
{
|
||||
int colour = IColouredItem.getColourBasic( stack );
|
||||
return colour == -1 ? Colour.White.getHex() : colour;
|
||||
return colour == -1 ? Colour.WHITE.getHex() : colour;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,6 @@ public class ItemTreasureDisk extends Item implements IMedia
|
||||
public static int getColour( @Nonnull ItemStack stack )
|
||||
{
|
||||
CompoundNBT nbt = stack.getTag();
|
||||
return nbt != null && nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : Colour.Blue.getHex();
|
||||
return nbt != null && nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : Colour.BLUE.getHex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class DiskRecipe extends SpecialRecipe
|
||||
}
|
||||
}
|
||||
|
||||
return ItemDisk.createFromIDAndColour( -1, null, tracker.hasColour() ? tracker.getColour() : Colour.Blue.getHex() );
|
||||
return ItemDisk.createFromIDAndColour( -1, null, tracker.hasColour() ? tracker.getColour() : Colour.BLUE.getHex() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +100,7 @@ public class DiskRecipe extends SpecialRecipe
|
||||
@Override
|
||||
public ItemStack getRecipeOutput()
|
||||
{
|
||||
return ItemDisk.createFromIDAndColour( -1, null, Colour.Blue.getHex() );
|
||||
return ItemDisk.createFromIDAndColour( -1, null, Colour.BLUE.getHex() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -76,12 +76,10 @@ public final class NetworkHandler
|
||||
{
|
||||
for( ServerPlayerEntity player : ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers() )
|
||||
{
|
||||
if( player.getEntityWorld() != world ) continue;
|
||||
|
||||
double x = pos.x - player.posX;
|
||||
double y = pos.y - player.posY;
|
||||
double z = pos.z - player.posZ;
|
||||
if( x * x + y * y + z * z < range * range ) sendToPlayer( player, packet );
|
||||
if( player.getEntityWorld() == world && player.getDistanceSq( pos ) < range * range )
|
||||
{
|
||||
sendToPlayer( player, packet );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,26 +99,27 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
if( player.isSneaking() )
|
||||
if( player.isCrouching() )
|
||||
{
|
||||
// Try to put a disk into the drive
|
||||
ItemStack disk = player.getHeldItem( hand );
|
||||
if( disk.isEmpty() ) return false;
|
||||
if( disk.isEmpty() ) return ActionResultType.PASS;
|
||||
if( !getWorld().isRemote && getStackInSlot( 0 ).isEmpty() && MediaProviders.get( disk ) != null )
|
||||
{
|
||||
setDiskStack( disk );
|
||||
player.setHeldItem( hand, ItemStack.EMPTY );
|
||||
}
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open the GUI
|
||||
if( !getWorld().isRemote ) NetworkHooks.openGui( (ServerPlayerEntity) player, this );
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,11 +250,4 @@ public class BlockCable extends BlockGeneric implements IWaterLoggable
|
||||
.with( WEST, false ).with( UP, false ).with( DOWN, false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean hasCustomBreakingProgress( BlockState state )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@@ -238,12 +239,14 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
if( !canAttachPeripheral() || player.isSneaking() ) return false;
|
||||
if( player.isCrouching() ) return ActionResultType.PASS;
|
||||
if( !canAttachPeripheral() ) return ActionResultType.FAIL;
|
||||
|
||||
if( getWorld().isRemote ) return true;
|
||||
if( getWorld().isRemote ) return ActionResultType.SUCCESS;
|
||||
|
||||
String oldName = m_peripheral.getConnectedName();
|
||||
togglePeripheralAccess();
|
||||
@@ -262,7 +265,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@@ -184,10 +185,11 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
if( getWorld().isRemote ) return true;
|
||||
if( getWorld().isRemote ) return ActionResultType.SUCCESS;
|
||||
|
||||
// On server, we interacted if a peripheral was found
|
||||
Set<String> oldPeriphNames = getConnectedPeripheralNames();
|
||||
@@ -200,7 +202,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
sendPeripheralChanges( player, "chat.computercraft.wired_modem.peripheral_connected", periphNames );
|
||||
}
|
||||
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
private static void sendPeripheralChanges( PlayerEntity player, String kind, Collection<String> peripherals )
|
||||
|
||||
@@ -374,7 +374,7 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
m_computer.queueEvent( event, arguments );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public IWorkMonitor getMainThreadMonitor()
|
||||
{
|
||||
|
||||
@@ -18,12 +18,10 @@ import net.minecraft.state.EnumProperty;
|
||||
import net.minecraft.state.StateContainer;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockMonitor extends BlockGeneric
|
||||
@@ -38,28 +36,13 @@ public class BlockMonitor extends BlockGeneric
|
||||
public BlockMonitor( Properties settings, NamedTileEntityType<? extends TileGeneric> type )
|
||||
{
|
||||
super( settings, type );
|
||||
// TODO: Test underwater - do we need isSolid at all?
|
||||
setDefaultState( getStateContainer().getBaseState()
|
||||
.with( ORIENTATION, Direction.NORTH )
|
||||
.with( FACING, Direction.NORTH )
|
||||
.with( STATE, MonitorEdgeState.NONE ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public BlockRenderLayer getRenderLayer()
|
||||
{
|
||||
// We use the CUTOUT layer, as otherwise monitor rendering will cause flickering.
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean isSolid( BlockState state )
|
||||
{
|
||||
// We override isSolid, as our overriding of getRenderLayer means that it would otherwise return false.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer( StateContainer.Builder<Block, BlockState> builder )
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ public final class ClientMonitor extends ClientTerminal
|
||||
if( buffer != null ) return false;
|
||||
|
||||
deleteBuffers();
|
||||
buffer = new VertexBuffer( FixedWidthFontRenderer.POSITION_COLOR_TEX );
|
||||
buffer = new VertexBuffer( FixedWidthFontRenderer.TYPE.getVertexFormat() );
|
||||
addMonitor();
|
||||
return true;
|
||||
|
||||
@@ -75,7 +75,7 @@ public final class ClientMonitor extends ClientTerminal
|
||||
{
|
||||
if( buffer != null )
|
||||
{
|
||||
buffer.deleteGlBuffers();
|
||||
buffer.close();
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import com.mojang.blaze3d.platform.GLX;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||
|
||||
@@ -73,22 +72,7 @@ public enum MonitorRenderer
|
||||
public static MonitorRenderer current()
|
||||
{
|
||||
MonitorRenderer current = ComputerCraft.monitorRenderer;
|
||||
switch( current )
|
||||
{
|
||||
case BEST:
|
||||
return best();
|
||||
case VBO:
|
||||
if( !GLX.useVbo() )
|
||||
{
|
||||
ComputerCraft.log.warn( "VBOs are not supported on your graphics card. Falling back to default." );
|
||||
ComputerCraft.monitorRenderer = BEST;
|
||||
return best();
|
||||
}
|
||||
|
||||
return VBO;
|
||||
default:
|
||||
return current;
|
||||
}
|
||||
return current == MonitorRenderer.BEST ? best() : current;
|
||||
}
|
||||
|
||||
private static MonitorRenderer best()
|
||||
|
||||
@@ -18,9 +18,11 @@ import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
@@ -104,10 +106,11 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
if( !player.isSneaking() && getFront() == hit.getFace() )
|
||||
if( !player.isCrouching() && getFront() == hit.getFace() )
|
||||
{
|
||||
if( !getWorld().isRemote )
|
||||
{
|
||||
@@ -117,10 +120,10 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
(float) (hit.getHitVec().z - hit.getPos().getZ())
|
||||
);
|
||||
}
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
return false;
|
||||
return ActionResultType.PASS;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -651,13 +654,12 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
m_computers.remove( computer );
|
||||
}
|
||||
|
||||
/*
|
||||
@Nonnull
|
||||
@Override
|
||||
public AxisAlignedBB getRenderBoundingBox()
|
||||
{
|
||||
TileMonitor start = getNeighbour( 0, 0 );
|
||||
TileMonitor end = getNeighbour( width - 1, height - 1 );
|
||||
TileMonitor end = getNeighbour( m_width - 1, m_height - 1 );
|
||||
if( start != null && end != null )
|
||||
{
|
||||
BlockPos startPos = start.getPos();
|
||||
@@ -676,5 +678,4 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
return new AxisAlignedBB( pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ import net.minecraft.inventory.container.INamedContainerProvider;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
@@ -94,13 +94,14 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
if( player.isSneaking() ) return false;
|
||||
if( player.isCrouching() ) return ActionResultType.PASS;
|
||||
|
||||
if( !getWorld().isRemote ) NetworkHooks.openGui( (ServerPlayerEntity) player, this );
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -424,11 +425,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
setInventorySlotContents( i, ItemStack.EMPTY );
|
||||
|
||||
// Spawn the item in the world
|
||||
BlockPos pos = getPos();
|
||||
double x = pos.getX() + 0.5;
|
||||
double y = pos.getY() + 0.75;
|
||||
double z = pos.getZ() + 0.5;
|
||||
WorldUtil.dropItemStack( stack, getWorld(), x, y, z );
|
||||
WorldUtil.dropItemStack( stack, getWorld(), new Vec3d( getPos() ).add( 0.5, 0.75, 0.5 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class PocketAPI implements ILuaAPI
|
||||
stack = InventoryUtil.storeItems( stack, new PlayerMainInvWrapper( inventory ), inventory.currentItem );
|
||||
if( !stack.isEmpty() )
|
||||
{
|
||||
WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.posX, player.posY, player.posZ );
|
||||
WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPositionVec() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class PocketAPI implements ILuaAPI
|
||||
stack = InventoryUtil.storeItems( stack, new PlayerMainInvWrapper( inventory ), inventory.currentItem );
|
||||
if( stack.isEmpty() )
|
||||
{
|
||||
WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.posX, player.posY, player.posZ );
|
||||
WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPositionVec() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ public final class PocketComputerItemFactory
|
||||
{
|
||||
switch( family )
|
||||
{
|
||||
case Normal:
|
||||
case NORMAL:
|
||||
return ComputerCraft.Items.pocketComputerNormal.create( id, label, colour, upgrade );
|
||||
case Advanced:
|
||||
case ADVANCED:
|
||||
return ComputerCraft.Items.pocketComputerAdvanced.create( id, label, colour, upgrade );
|
||||
default:
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
@@ -37,7 +37,7 @@ public final class PocketComputerUpgradeRecipe extends SpecialRecipe
|
||||
@Override
|
||||
public ItemStack getRecipeOutput()
|
||||
{
|
||||
return PocketComputerItemFactory.create( -1, null, -1, ComputerFamily.Normal, null );
|
||||
return PocketComputerItemFactory.create( -1, null, -1, ComputerFamily.NORMAL, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,7 +11,6 @@ import dan200.computercraft.api.media.IMedia;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
import dan200.computercraft.core.tracking.Tracking;
|
||||
import dan200.computercraft.shared.Config;
|
||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
import dan200.computercraft.shared.command.arguments.ArgumentSerializers;
|
||||
import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider;
|
||||
@@ -36,7 +35,6 @@ import net.minecraft.world.storage.loot.conditions.LootConditionManager;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
|
||||
@@ -133,12 +131,6 @@ public final class ComputerCraftProxyCommon
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onConfigChanged( ConfigChangedEvent.OnConfigChangedEvent event )
|
||||
{
|
||||
if( event.getModID().equals( ComputerCraft.MOD_ID ) ) Config.sync();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onContainerOpen( PlayerContainerEvent.Open event )
|
||||
{
|
||||
|
||||
@@ -133,11 +133,11 @@ public class TurtleAPI implements ILuaAPI
|
||||
}
|
||||
else if( side.equalsIgnoreCase( "left" ) )
|
||||
{
|
||||
return TurtleSide.Left;
|
||||
return TurtleSide.LEFT;
|
||||
}
|
||||
else if( side.equalsIgnoreCase( "right" ) )
|
||||
{
|
||||
return TurtleSide.Right;
|
||||
return TurtleSide.RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -152,58 +152,58 @@ public class TurtleAPI implements ILuaAPI
|
||||
{
|
||||
case 0: // forward
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.Forward ) );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.FORWARD ) );
|
||||
case 1: // back
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.Back ) );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.BACK ) );
|
||||
case 2: // up
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.Up ) );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.UP ) );
|
||||
case 3: // down
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.Down ) );
|
||||
return tryCommand( context, new TurtleMoveCommand( MoveDirection.DOWN ) );
|
||||
case 4: // turnLeft
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleTurnCommand( TurnDirection.Left ) );
|
||||
return tryCommand( context, new TurtleTurnCommand( TurnDirection.LEFT ) );
|
||||
case 5: // turnRight
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleTurnCommand( TurnDirection.Right ) );
|
||||
return tryCommand( context, new TurtleTurnCommand( TurnDirection.RIGHT ) );
|
||||
case 6:
|
||||
{
|
||||
// dig
|
||||
TurtleSide side = parseSide( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, TurtleToolCommand.dig( InteractDirection.Forward, side ) );
|
||||
return tryCommand( context, TurtleToolCommand.dig( InteractDirection.FORWARD, side ) );
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
// digUp
|
||||
TurtleSide side = parseSide( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, TurtleToolCommand.dig( InteractDirection.Up, side ) );
|
||||
return tryCommand( context, TurtleToolCommand.dig( InteractDirection.UP, side ) );
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
// digDown
|
||||
TurtleSide side = parseSide( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, TurtleToolCommand.dig( InteractDirection.Down, side ) );
|
||||
return tryCommand( context, TurtleToolCommand.dig( InteractDirection.DOWN, side ) );
|
||||
}
|
||||
case 9: // place
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtlePlaceCommand( InteractDirection.Forward, args ) );
|
||||
return tryCommand( context, new TurtlePlaceCommand( InteractDirection.FORWARD, args ) );
|
||||
case 10: // placeUp
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtlePlaceCommand( InteractDirection.Up, args ) );
|
||||
return tryCommand( context, new TurtlePlaceCommand( InteractDirection.UP, args ) );
|
||||
case 11: // placeDown
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtlePlaceCommand( InteractDirection.Down, args ) );
|
||||
return tryCommand( context, new TurtlePlaceCommand( InteractDirection.DOWN, args ) );
|
||||
case 12:
|
||||
{
|
||||
// drop
|
||||
int count = parseCount( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleDropCommand( InteractDirection.Forward, count ) );
|
||||
return tryCommand( context, new TurtleDropCommand( InteractDirection.FORWARD, count ) );
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
@@ -229,72 +229,72 @@ public class TurtleAPI implements ILuaAPI
|
||||
return new Object[] { stack.isEmpty() ? 64 : Math.min( stack.getMaxStackSize(), 64 ) - stack.getCount() };
|
||||
}
|
||||
case 16: // detect
|
||||
return tryCommand( context, new TurtleDetectCommand( InteractDirection.Forward ) );
|
||||
return tryCommand( context, new TurtleDetectCommand( InteractDirection.FORWARD ) );
|
||||
case 17: // detectUp
|
||||
return tryCommand( context, new TurtleDetectCommand( InteractDirection.Up ) );
|
||||
return tryCommand( context, new TurtleDetectCommand( InteractDirection.UP ) );
|
||||
case 18: // detectDown
|
||||
return tryCommand( context, new TurtleDetectCommand( InteractDirection.Down ) );
|
||||
return tryCommand( context, new TurtleDetectCommand( InteractDirection.DOWN ) );
|
||||
case 19: // compare
|
||||
return tryCommand( context, new TurtleCompareCommand( InteractDirection.Forward ) );
|
||||
return tryCommand( context, new TurtleCompareCommand( InteractDirection.FORWARD ) );
|
||||
case 20: // compareUp
|
||||
return tryCommand( context, new TurtleCompareCommand( InteractDirection.Up ) );
|
||||
return tryCommand( context, new TurtleCompareCommand( InteractDirection.UP ) );
|
||||
case 21: // compareDown
|
||||
return tryCommand( context, new TurtleCompareCommand( InteractDirection.Down ) );
|
||||
return tryCommand( context, new TurtleCompareCommand( InteractDirection.DOWN ) );
|
||||
case 22:
|
||||
{
|
||||
// attack
|
||||
TurtleSide side = parseSide( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, TurtleToolCommand.attack( InteractDirection.Forward, side ) );
|
||||
return tryCommand( context, TurtleToolCommand.attack( InteractDirection.FORWARD, side ) );
|
||||
}
|
||||
case 23:
|
||||
{
|
||||
// attackUp
|
||||
TurtleSide side = parseSide( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, TurtleToolCommand.attack( InteractDirection.Up, side ) );
|
||||
return tryCommand( context, TurtleToolCommand.attack( InteractDirection.UP, side ) );
|
||||
}
|
||||
case 24:
|
||||
{
|
||||
// attackDown
|
||||
TurtleSide side = parseSide( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, TurtleToolCommand.attack( InteractDirection.Down, side ) );
|
||||
return tryCommand( context, TurtleToolCommand.attack( InteractDirection.DOWN, side ) );
|
||||
}
|
||||
case 25:
|
||||
{
|
||||
// dropUp
|
||||
int count = parseCount( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleDropCommand( InteractDirection.Up, count ) );
|
||||
return tryCommand( context, new TurtleDropCommand( InteractDirection.UP, count ) );
|
||||
}
|
||||
case 26:
|
||||
{
|
||||
// dropDown
|
||||
int count = parseCount( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleDropCommand( InteractDirection.Down, count ) );
|
||||
return tryCommand( context, new TurtleDropCommand( InteractDirection.DOWN, count ) );
|
||||
}
|
||||
case 27:
|
||||
{
|
||||
// suck
|
||||
int count = parseCount( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleSuckCommand( InteractDirection.Forward, count ) );
|
||||
return tryCommand( context, new TurtleSuckCommand( InteractDirection.FORWARD, count ) );
|
||||
}
|
||||
case 28:
|
||||
{
|
||||
// suckUp
|
||||
int count = parseCount( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleSuckCommand( InteractDirection.Up, count ) );
|
||||
return tryCommand( context, new TurtleSuckCommand( InteractDirection.UP, count ) );
|
||||
}
|
||||
case 29:
|
||||
{
|
||||
// suckDown
|
||||
int count = parseCount( args, 0 );
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleSuckCommand( InteractDirection.Down, count ) );
|
||||
return tryCommand( context, new TurtleSuckCommand( InteractDirection.DOWN, count ) );
|
||||
}
|
||||
case 30: // getFuelLevel
|
||||
return new Object[] { m_turtle.isFuelNeeded() ? m_turtle.getFuelLevel() : "unlimited" };
|
||||
@@ -324,16 +324,16 @@ public class TurtleAPI implements ILuaAPI
|
||||
return new Object[] { m_turtle.isFuelNeeded() ? m_turtle.getFuelLimit() : "unlimited" };
|
||||
case 36: // equipLeft
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleEquipCommand( TurtleSide.Left ) );
|
||||
return tryCommand( context, new TurtleEquipCommand( TurtleSide.LEFT ) );
|
||||
case 37: // equipRight
|
||||
m_environment.addTrackingChange( TrackingField.TURTLE_OPS );
|
||||
return tryCommand( context, new TurtleEquipCommand( TurtleSide.Right ) );
|
||||
return tryCommand( context, new TurtleEquipCommand( TurtleSide.RIGHT ) );
|
||||
case 38: // inspect
|
||||
return tryCommand( context, new TurtleInspectCommand( InteractDirection.Forward ) );
|
||||
return tryCommand( context, new TurtleInspectCommand( InteractDirection.FORWARD ) );
|
||||
case 39: // inspectUp
|
||||
return tryCommand( context, new TurtleInspectCommand( InteractDirection.Up ) );
|
||||
return tryCommand( context, new TurtleInspectCommand( InteractDirection.UP ) );
|
||||
case 40: // inspectDown
|
||||
return tryCommand( context, new TurtleInspectCommand( InteractDirection.Down ) );
|
||||
return tryCommand( context, new TurtleInspectCommand( InteractDirection.DOWN ) );
|
||||
case 41: // getItemDetail
|
||||
{
|
||||
// FIXME: There's a race condition here if the stack is being modified (mutating NBT, etc...)
|
||||
|
||||
@@ -152,7 +152,7 @@ public class BlockTurtle extends BlockComputerBase<TileTurtle> implements IWater
|
||||
@Override
|
||||
public float getExplosionResistance( BlockState state, IWorldReader world, BlockPos pos, @Nullable Entity exploder, Explosion explosion )
|
||||
{
|
||||
if( getFamily() == ComputerFamily.Advanced || exploder instanceof LivingEntity || exploder instanceof DamagingProjectileEntity )
|
||||
if( getFamily() == ComputerFamily.ADVANCED || exploder instanceof LivingEntity || exploder instanceof DamagingProjectileEntity )
|
||||
{
|
||||
return 2000;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,7 @@ import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -60,12 +57,12 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
|
||||
public static final NamedTileEntityType<TileTurtle> FACTORY_NORMAL = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "turtle_normal" ),
|
||||
type -> new TileTurtle( type, ComputerFamily.Normal )
|
||||
type -> new TileTurtle( type, ComputerFamily.NORMAL )
|
||||
);
|
||||
|
||||
public static final NamedTileEntityType<TileTurtle> FACTORY_ADVANCED = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ),
|
||||
type -> new TileTurtle( type, ComputerFamily.Advanced )
|
||||
type -> new TileTurtle( type, ComputerFamily.ADVANCED )
|
||||
);
|
||||
|
||||
enum MoveState
|
||||
@@ -164,8 +161,9 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public ActionResultType onActivate( PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
{
|
||||
// Apply dye
|
||||
ItemStack currentItem = player.getHeldItem( hand );
|
||||
@@ -186,7 +184,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
else if( currentItem.getItem() == Items.WATER_BUCKET && m_brain.getColour() != -1 )
|
||||
{
|
||||
@@ -203,7 +201,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,10 +526,10 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
switch( side )
|
||||
{
|
||||
case RIGHT:
|
||||
upgrade = getUpgrade( TurtleSide.Right );
|
||||
upgrade = getUpgrade( TurtleSide.RIGHT );
|
||||
break;
|
||||
case LEFT:
|
||||
upgrade = getUpgrade( TurtleSide.Left );
|
||||
upgrade = getUpgrade( TurtleSide.LEFT );
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -10,20 +10,20 @@ import net.minecraft.util.Direction;
|
||||
|
||||
public enum InteractDirection
|
||||
{
|
||||
Forward,
|
||||
Up,
|
||||
Down;
|
||||
FORWARD,
|
||||
UP,
|
||||
DOWN;
|
||||
|
||||
public Direction toWorldDir( ITurtleAccess turtle )
|
||||
{
|
||||
switch( this )
|
||||
{
|
||||
case Forward:
|
||||
case FORWARD:
|
||||
default:
|
||||
return turtle.getDirection();
|
||||
case Up:
|
||||
case UP:
|
||||
return Direction.UP;
|
||||
case Down:
|
||||
case DOWN:
|
||||
return Direction.DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user