mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +00:00 
			
		
		
		
	Update to 1.15
Most of the port is pretty simple. The main problems are regarding
changes to Minecraft's rendering system.
 - Remove several rendering tweaks until Forge's compatibility it
   brought up-to-date
    - Map rendering for pocket computers and printouts
    - Item frame rendering for printouts
    - Custom block outlines for monitors and cables/wired modems
    - Custom breaking progress for cables/wired modems
 - Turtle "Dinnerbone" rendering is currently broken, as normals are not
   correctly transformed.
 - Rewrite FixedWidthFontRenderer to to the buffer in a single sweep.
   In order to do this, the term_font now also bundles a "background"
   section, which is just a blank region of the screen.
 - Render monitors using a VBO instead of a call list. I haven't
   compared performance yet, but it manages to render a 6x5 array of
   _static_ monitors at almost 60fps, which seems pretty reasonable.
			
			
This commit is contained in:
		
							
								
								
									
										29
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								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.159' | ||||
|         classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2' | ||||
|         classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0' | ||||
|     } | ||||
| @@ -73,14 +73,6 @@ repositories { | ||||
|         name "SquidDev" | ||||
|         url "https://squiddev.cc/maven" | ||||
|     } | ||||
|     ivy { | ||||
|         name "Charset" | ||||
|         artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]" | ||||
|     } | ||||
|     maven { | ||||
|         name "Amadornes" | ||||
|         url "https://maven.amadornes.com/" | ||||
|     } | ||||
|     maven { | ||||
|         name "CraftTweaker" | ||||
|         url "https://maven.blamejared.com/" | ||||
| @@ -98,10 +90,8 @@ dependencies { | ||||
|  | ||||
|     minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" | ||||
|  | ||||
|     compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.25:api") | ||||
|     compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.14.4:5.0.1.150") | ||||
|  | ||||
|     runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.25") | ||||
|     compileOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.2:api") | ||||
|     runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.2") | ||||
|  | ||||
|     shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT' | ||||
|  | ||||
| @@ -111,6 +101,15 @@ dependencies { | ||||
|     deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0" | ||||
| } | ||||
|  | ||||
| sourceSets { | ||||
|     main { | ||||
|         java { | ||||
|             exclude 'dan200/computercraft/client/render_old' | ||||
|             exclude 'dan200/computercraft/shared/integration/crafttweaker' | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Compile tasks | ||||
|  | ||||
| javadoc { | ||||
| @@ -372,7 +371,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 { | ||||
| @@ -450,7 +449,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.86.2 | ||||
|  | ||||
| # 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.0.1 | ||||
| mappings_version=20200124-1.15.1 | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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().getBasePath().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 | ||||
| @@ -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,195 +5,322 @@ | ||||
|  */ | ||||
| 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.texture.TextureManager; | ||||
| import net.minecraft.client.renderer.*; | ||||
| import net.minecraft.client.renderer.vertex.DefaultVertexFormats; | ||||
| import net.minecraft.client.renderer.vertex.VertexFormat; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import org.lwjgl.opengl.GL11; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import javax.annotation.Nonnull; | ||||
| 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" ); | ||||
|     public static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/term_background.png" ); | ||||
|  | ||||
|     public static final int FONT_HEIGHT = 9; | ||||
|     public static final int FONT_WIDTH = 6; | ||||
|     public static final float WIDTH = 256.0f; | ||||
|  | ||||
|     private static FixedWidthFontRenderer instance; | ||||
|     public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; | ||||
|     public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; | ||||
|  | ||||
|     public static FixedWidthFontRenderer instance() | ||||
|     { | ||||
|         if( instance != null ) return instance; | ||||
|         return instance = new FixedWidthFontRenderer(); | ||||
|     } | ||||
|  | ||||
|     private final TextureManager m_textureManager; | ||||
|     public static final RenderType TYPE = Type.MAIN; | ||||
|  | ||||
|     private FixedWidthFontRenderer() | ||||
|     { | ||||
|         m_textureManager = Minecraft.getInstance().getTextureManager(); | ||||
|     } | ||||
|  | ||||
|     private static void greyscaleify( double[] rgb ) | ||||
|     private static float toGreyscale( double[] rgb ) | ||||
|     { | ||||
|         Arrays.fill( rgb, (rgb[0] + rgb[1] + rgb[2]) / 3.0f ); | ||||
|         return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3); | ||||
|     } | ||||
|  | ||||
|     private void drawChar( BufferBuilder renderer, double x, double y, int index, int color, Palette p, boolean greyscale ) | ||||
|     private static void drawChar( Matrix4f transform, IVertexBuilder buffer, float x, float y, int index, float r, float g, float b ) | ||||
|     { | ||||
|         int column = index % 16; | ||||
|         int row = index / 16; | ||||
|  | ||||
|         double[] colour = p.getColour( 15 - color ); | ||||
|         if( greyscale ) | ||||
|         { | ||||
|             greyscaleify( colour ); | ||||
|         } | ||||
|         float r = (float) colour[0]; | ||||
|         float g = (float) colour[1]; | ||||
|         float b = (float) colour[2]; | ||||
|  | ||||
|         int xStart = 1 + column * (FONT_WIDTH + 2); | ||||
|         int yStart = 1 + row * (FONT_HEIGHT + 2); | ||||
|  | ||||
|         renderer.pos( x, y, 0.0 ).tex( xStart / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x + FONT_WIDTH, y + FONT_HEIGHT, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         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 void drawQuad( BufferBuilder renderer, double x, double y, int color, double width, Palette p, boolean greyscale ) | ||||
|     private static void drawQuad( Matrix4f transform, IVertexBuilder buffer, float x, float y, float width, float height, float r, float g, float b ) | ||||
|     { | ||||
|         double[] colour = p.getColour( 15 - color ); | ||||
|         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 drawBackground( | ||||
|         @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 ) | ||||
|         { | ||||
|             double[] colour = palette.getColour( 15 - "0123456789abcdef".indexOf( backgroundColour.charAt( 0 ) ) ); | ||||
|             float r, g, b; | ||||
|             if( greyscale ) | ||||
|             { | ||||
|             greyscaleify( colour ); | ||||
|                 r = g = b = toGreyscale( colour ); | ||||
|             } | ||||
|         float r = (float) colour[0]; | ||||
|         float g = (float) colour[1]; | ||||
|         float b = (float) colour[2]; | ||||
|  | ||||
|         renderer.pos( x, y, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x + width, y, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x + width, y, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|         renderer.pos( x + width, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|             else | ||||
|             { | ||||
|                 r = (float) colour[0]; | ||||
|                 g = (float) colour[1]; | ||||
|                 b = (float) colour[2]; | ||||
|             } | ||||
|  | ||||
|     private boolean isGreyScale( int colour ) | ||||
|     { | ||||
|         return colour == 0 || colour == 15 || colour == 7 || colour == 8; | ||||
|             drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, r, g, b ); | ||||
|         } | ||||
|  | ||||
|     public void drawStringBackgroundPart( int x, int y, TextBuffer backgroundColour, double leftMarginSize, double rightMarginSize, boolean greyScale, Palette p ) | ||||
|         if( rightMarginSize > 0 ) | ||||
|         { | ||||
|         // Draw the quads | ||||
|         Tessellator tessellator = Tessellator.getInstance(); | ||||
|         BufferBuilder renderer = tessellator.getBuffer(); | ||||
|         renderer.begin( GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR ); | ||||
|         if( leftMarginSize > 0.0 ) | ||||
|             double[] colour = palette.getColour( 15 - "0123456789abcdef".indexOf( backgroundColour.charAt( backgroundColour.length() - 1 ) ) ); | ||||
|             float r, g, b; | ||||
|             if( greyscale ) | ||||
|             { | ||||
|             int colour1 = "0123456789abcdef".indexOf( backgroundColour.charAt( 0 ) ); | ||||
|             if( colour1 < 0 || (greyScale && !isGreyScale( colour1 )) ) | ||||
|             { | ||||
|                 colour1 = 15; | ||||
|                 r = g = b = toGreyscale( colour ); | ||||
|             } | ||||
|             drawQuad( renderer, x - leftMarginSize, y, colour1, leftMarginSize, p, greyScale ); | ||||
|         } | ||||
|         if( rightMarginSize > 0.0 ) | ||||
|             else | ||||
|             { | ||||
|             int colour2 = "0123456789abcdef".indexOf( backgroundColour.charAt( backgroundColour.length() - 1 ) ); | ||||
|             if( colour2 < 0 || (greyScale && !isGreyScale( colour2 )) ) | ||||
|             { | ||||
|                 colour2 = 15; | ||||
|                 r = (float) colour[0]; | ||||
|                 g = (float) colour[1]; | ||||
|                 b = (float) colour[2]; | ||||
|             } | ||||
|             drawQuad( renderer, x + backgroundColour.length() * FONT_WIDTH, y, colour2, rightMarginSize, p, greyScale ); | ||||
|  | ||||
|             drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, r, g, b ); | ||||
|         } | ||||
|  | ||||
|         for( int i = 0; i < backgroundColour.length(); i++ ) | ||||
|         { | ||||
|             int colour = "0123456789abcdef".indexOf( backgroundColour.charAt( i ) ); | ||||
|             if( colour < 0 || (greyScale && !isGreyScale( colour )) ) | ||||
|             double[] colour = palette.getColour( 15 - "0123456789abcdef".indexOf( backgroundColour.charAt( i ) ) ); | ||||
|             float r, g, b; | ||||
|             if( greyscale ) | ||||
|             { | ||||
|                 colour = 15; | ||||
|                 r = g = b = toGreyscale( colour ); | ||||
|             } | ||||
|             drawQuad( renderer, x + i * FONT_WIDTH, y, colour, FONT_WIDTH, p, greyScale ); | ||||
|         } | ||||
|         GlStateManager.disableTexture(); | ||||
|         tessellator.draw(); | ||||
|         GlStateManager.enableTexture(); | ||||
|             else | ||||
|             { | ||||
|                 r = (float) colour[0]; | ||||
|                 g = (float) colour[1]; | ||||
|                 b = (float) colour[2]; | ||||
|             } | ||||
|  | ||||
|     public void drawStringTextPart( int x, int y, TextBuffer s, TextBuffer textColour, boolean greyScale, Palette p ) | ||||
|             drawQuad( transform, renderer, x + i * FONT_WIDTH, y, FONT_WIDTH, height, r, g, b ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void drawString( | ||||
|         @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 | ||||
|     ) | ||||
|     { | ||||
|         // Draw the quads | ||||
|         Tessellator tessellator = Tessellator.getInstance(); | ||||
|         BufferBuilder renderer = tessellator.getBuffer(); | ||||
|         renderer.begin( GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_COLOR ); | ||||
|         for( int i = 0; i < s.length(); i++ ) | ||||
|         if( backgroundColour != null ) | ||||
|         { | ||||
|             // Switch colour | ||||
|             int colour = "0123456789abcdef".indexOf( textColour.charAt( i ) ); | ||||
|             if( colour < 0 || (greyScale && !isGreyScale( colour )) ) | ||||
|             drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT ); | ||||
|         } | ||||
|  | ||||
|         for( int i = 0; i < text.length(); i++ ) | ||||
|         { | ||||
|                 colour = 0; | ||||
|             double[] colour = palette.getColour( 15 - "0123456789abcdef".indexOf( textColour.charAt( i ) ) ); | ||||
|             float r, g, b; | ||||
|             if( greyscale ) | ||||
|             { | ||||
|                 r = g = b = toGreyscale( colour ); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 r = (float) colour[0]; | ||||
|                 g = (float) colour[1]; | ||||
|                 b = (float) colour[2]; | ||||
|             } | ||||
|  | ||||
|             // Draw char | ||||
|             int index = s.charAt( i ); | ||||
|             if( index < 0 || index > 255 ) | ||||
|             { | ||||
|                 index = '?'; | ||||
|             } | ||||
|             drawChar( renderer, x + i * FONT_WIDTH, y, index, colour, p, greyScale ); | ||||
|         } | ||||
|         tessellator.draw(); | ||||
|             int index = text.charAt( i ); | ||||
|             if( index > 255 ) index = '?'; | ||||
|             drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b ); | ||||
|         } | ||||
|  | ||||
|     public void drawString( TextBuffer s, int x, int y, TextBuffer textColour, TextBuffer backgroundColour, double leftMarginSize, double rightMarginSize, boolean greyScale, Palette p ) | ||||
|     { | ||||
|         // Draw background | ||||
|         if( backgroundColour != null ) | ||||
|         { | ||||
|             // Bind the background texture | ||||
|             m_textureManager.bindTexture( BACKGROUND ); | ||||
|  | ||||
|             // Draw the quads | ||||
|             drawStringBackgroundPart( x, y, backgroundColour, leftMarginSize, rightMarginSize, greyScale, p ); | ||||
|     } | ||||
|  | ||||
|         // Draw text | ||||
|         if( s != null && textColour != null ) | ||||
|     public static void drawString( | ||||
|         float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, | ||||
|         @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize | ||||
|     ) | ||||
|     { | ||||
|             // Bind the font texture | ||||
|             bindFont(); | ||||
|         Minecraft.getInstance().getTextureManager().bindTexture( FONT ); | ||||
|         // TODO: RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); | ||||
|  | ||||
|             // Draw the quads | ||||
|             drawStringTextPart( x, y, s, textColour, greyScale, p ); | ||||
|         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 Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y, | ||||
|         @Nonnull Terminal terminal, boolean greyscale, | ||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||
|     ) | ||||
|     { | ||||
|         Palette palette = terminal.getPalette(); | ||||
|         int height = terminal.getHeight(); | ||||
|  | ||||
|         // Top and bottom margins | ||||
|         drawBackground( | ||||
|             transform, buffer, x, y - topMarginSize, | ||||
|             terminal.getBackgroundColourLine( 0 ), palette, greyscale, | ||||
|             leftMarginSize, rightMarginSize, topMarginSize | ||||
|         ); | ||||
|  | ||||
|         drawBackground( | ||||
|             transform, buffer, x, y + height * FONT_HEIGHT, | ||||
|             terminal.getBackgroundColourLine( height - 1 ), palette, greyscale, | ||||
|             leftMarginSize, rightMarginSize, bottomMarginSize | ||||
|         ); | ||||
|  | ||||
|         // The main text | ||||
|         for( int i = 0; i < height; i++ ) | ||||
|         { | ||||
|             drawString( | ||||
|                 transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i, | ||||
|                 terminal.getLine( i ), terminal.getTextColourLine( i ), terminal.getBackgroundColourLine( i ), | ||||
|                 palette, greyscale, leftMarginSize, rightMarginSize | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public int getStringWidth( String s ) | ||||
|     public static void drawCursor( | ||||
|         @Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y, | ||||
|         @Nonnull Terminal terminal, boolean greyscale | ||||
|     ) | ||||
|     { | ||||
|         if( s == null ) | ||||
|         Palette palette = terminal.getPalette(); | ||||
|         int width = terminal.getWidth(); | ||||
|         int height = terminal.getHeight(); | ||||
|  | ||||
|         int cursorX = terminal.getCursorX(); | ||||
|         int cursorY = terminal.getCursorY(); | ||||
|         if( terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height && FrameInfo.getGlobalCursorBlink() ) | ||||
|         { | ||||
|             return 0; | ||||
|             double[] colour = palette.getColour( 15 - terminal.getTextColour() ); | ||||
|             float r, g, b; | ||||
|             if( greyscale ) | ||||
|             { | ||||
|                 r = g = b = toGreyscale( colour ); | ||||
|             } | ||||
|         return s.length() * FONT_WIDTH; | ||||
|             else | ||||
|             { | ||||
|                 r = (float) colour[0]; | ||||
|                 g = (float) colour[1]; | ||||
|                 b = (float) colour[2]; | ||||
|             } | ||||
|  | ||||
|     public void bindFont() | ||||
|             drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void drawTerminal( | ||||
|         @Nonnull Matrix4f transform, @Nonnull IVertexBuilder buffer, float x, float y, | ||||
|         @Nonnull Terminal terminal, boolean greyscale, | ||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||
|     ) | ||||
|     { | ||||
|         m_textureManager.bindTexture( FONT ); | ||||
|         GlStateManager.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); | ||||
|         drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); | ||||
|         drawCursor( transform, buffer, x, y, terminal, greyscale ); | ||||
|     } | ||||
|  | ||||
|     public static void drawTerminal( | ||||
|         float x, float y, @Nonnull Terminal terminal, boolean greyscale, | ||||
|         float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize | ||||
|     ) | ||||
|     { | ||||
|         Minecraft.getInstance().getTextureManager().bindTexture( FONT ); | ||||
|         // TODO: Is this the most sane thing? | ||||
|         RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); | ||||
|  | ||||
|         IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource(); | ||||
|         IVertexBuilder buffer = renderer.getBuffer( TYPE ); | ||||
|         drawTerminal( IDENTITY, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); | ||||
|         renderer.finish( TYPE ); | ||||
|     } | ||||
|  | ||||
|     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( float x, float y, float width, float height ) | ||||
|     { | ||||
|         Minecraft.getInstance().getTextureManager().bindTexture( FONT ); | ||||
|         RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); | ||||
|  | ||||
|         IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource(); | ||||
|         drawEmptyTerminal( IDENTITY, renderer, x, y, width, height ); | ||||
|         renderer.finish(); | ||||
|     } | ||||
|  | ||||
|     public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull IRenderTypeBuffer renderer, float x, float y, float width, float height ) | ||||
|     { | ||||
|         Colour colour = Colour.Black; | ||||
|         drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); | ||||
|     } | ||||
|  | ||||
|     private static final class Type extends RenderState | ||||
|     { | ||||
|         private static final int GL_MODE = GL11.GL_TRIANGLES; | ||||
|  | ||||
|         private static final VertexFormat FORMAT = DefaultVertexFormats.POSITION_COLOR_TEX; | ||||
|  | ||||
|         static final RenderType MAIN = RenderType.get( | ||||
|             "terminal_font", FORMAT, GL_MODE, 1024, | ||||
|             false, false, // useDelegate, needsSorting | ||||
|             RenderType.State.builder() | ||||
|                 .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.get( | ||||
|             "terminal_blocker", FORMAT, GL_MODE, 256, | ||||
|             false, false, // useDelegate, needsSorting | ||||
|             RenderType.State.builder() | ||||
|                 .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,7 +134,7 @@ 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: | ||||
|   | ||||
| @@ -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,7 +5,7 @@ | ||||
|  */ | ||||
| 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; | ||||
| @@ -88,10 +88,10 @@ 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 ); | ||||
|         drawBorder( guiLeft, guiTop, getBlitOffset(), 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 ); | ||||
|     } | ||||
|  | ||||
| @@ -99,9 +99,9 @@ public class GuiPrintout extends ContainerScreen<ContainerHeldItem> | ||||
|     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 ); | ||||
| @@ -114,7 +114,7 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle> | ||||
|         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 ); | ||||
|  | ||||
|   | ||||
| @@ -5,28 +5,20 @@ | ||||
|  */ | ||||
| package dan200.computercraft.client.gui.widgets; | ||||
|  | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import dan200.computercraft.client.FrameInfo; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.computer.core.ClientComputer; | ||||
| import dan200.computercraft.shared.computer.core.IComputer; | ||||
| import dan200.computercraft.shared.util.Colour; | ||||
| import dan200.computercraft.shared.util.Palette; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.gui.IGuiEventListener; | ||||
| import net.minecraft.client.renderer.BufferBuilder; | ||||
| import net.minecraft.client.renderer.Tessellator; | ||||
| import net.minecraft.client.renderer.vertex.DefaultVertexFormats; | ||||
| import net.minecraft.util.SharedConstants; | ||||
| import org.lwjgl.glfw.GLFW; | ||||
| import org.lwjgl.opengl.GL11; | ||||
|  | ||||
| import java.util.BitSet; | ||||
| import java.util.function.Supplier; | ||||
|  | ||||
| import static dan200.computercraft.client.gui.FixedWidthFontRenderer.BACKGROUND; | ||||
| import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; | ||||
| import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; | ||||
|  | ||||
| public class WidgetTerminal implements IGuiEventListener | ||||
| { | ||||
| @@ -184,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 ); | ||||
|  | ||||
| @@ -208,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 ); | ||||
|  | ||||
| @@ -235,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 ); | ||||
|  | ||||
| @@ -260,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 ); | ||||
|  | ||||
| @@ -329,89 +321,15 @@ public class WidgetTerminal implements IGuiEventListener | ||||
|             Terminal terminal = computer != null ? computer.getTerminal() : null; | ||||
|             if( terminal != null ) | ||||
|             { | ||||
|                 // Draw the terminal | ||||
|                 boolean greyscale = !computer.isColour(); | ||||
|                 Palette palette = terminal.getPalette(); | ||||
|  | ||||
|                 // Get the data from the terminal first | ||||
|                 // Unfortunately we have to keep the lock for the whole of drawing, so the text doesn't change under us. | ||||
|                 FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance(); | ||||
|                 boolean tblink = terminal.getCursorBlink() && FrameInfo.getGlobalCursorBlink(); | ||||
|                 int tw = terminal.getWidth(); | ||||
|                 int th = terminal.getHeight(); | ||||
|                 int tx = terminal.getCursorX(); | ||||
|                 int ty = terminal.getCursorY(); | ||||
|  | ||||
|                 // Draw margins | ||||
|                 TextBuffer emptyLine = new TextBuffer( ' ', tw ); | ||||
|                 if( topMargin > 0 ) | ||||
|                 { | ||||
|                     fontRenderer.drawString( emptyLine, originX, originY - topMargin, | ||||
|                         terminal.getTextColourLine( 0 ), terminal.getBackgroundColourLine( 0 ), | ||||
|                         leftMargin, rightMargin, greyscale, palette ); | ||||
|                 } | ||||
|  | ||||
|                 if( bottomMargin > 0 ) | ||||
|                 { | ||||
|                     fontRenderer.drawString( emptyLine, originX, originY + bottomMargin + (th - 1) * FixedWidthFontRenderer.FONT_HEIGHT, | ||||
|                         terminal.getTextColourLine( th - 1 ), terminal.getBackgroundColourLine( th - 1 ), | ||||
|                         leftMargin, rightMargin, greyscale, palette ); | ||||
|                 } | ||||
|  | ||||
|                 // Draw lines | ||||
|                 int y = originY; | ||||
|                 for( int line = 0; line < th; line++ ) | ||||
|                 { | ||||
|                     TextBuffer text = terminal.getLine( line ); | ||||
|                     TextBuffer colour = terminal.getTextColourLine( line ); | ||||
|                     TextBuffer backgroundColour = terminal.getBackgroundColourLine( line ); | ||||
|                     fontRenderer.drawString( text, originX, y, colour, backgroundColour, leftMargin, rightMargin, greyscale, palette ); | ||||
|                     y += FixedWidthFontRenderer.FONT_HEIGHT; | ||||
|                 } | ||||
|  | ||||
|                 if( tblink && tx >= 0 && ty >= 0 && tx < tw && ty < th ) | ||||
|                 { | ||||
|                     TextBuffer cursor = new TextBuffer( '_', 1 ); | ||||
|                     TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 ); | ||||
|  | ||||
|                     fontRenderer.drawString( | ||||
|                         cursor, | ||||
|                         originX + FixedWidthFontRenderer.FONT_WIDTH * tx, | ||||
|                         originY + FixedWidthFontRenderer.FONT_HEIGHT * ty, | ||||
|                         cursorColour, null, | ||||
|                         0, 0, | ||||
|                         greyscale, | ||||
|                         palette | ||||
|                     ); | ||||
|                 } | ||||
|                 FixedWidthFontRenderer.drawTerminal( originX, originY, terminal, !computer.isColour(), topMargin, bottomMargin, leftMargin, rightMargin ); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Draw a black background | ||||
|                 Colour black = Colour.Black; | ||||
|                 GlStateManager.color4f( black.getR(), black.getG(), black.getB(), 1.0f ); | ||||
|                 try | ||||
|                 { | ||||
|                     int x = originX - leftMargin; | ||||
|                     int y = originY - rightMargin; | ||||
|                     int width = termWidth * FixedWidthFontRenderer.FONT_WIDTH + leftMargin + rightMargin; | ||||
|                     int height = termHeight * FixedWidthFontRenderer.FONT_HEIGHT + topMargin + bottomMargin; | ||||
|  | ||||
|                     client.getTextureManager().bindTexture( BACKGROUND ); | ||||
|  | ||||
|                     Tessellator tesslector = Tessellator.getInstance(); | ||||
|                     BufferBuilder buffer = tesslector.getBuffer(); | ||||
|                     buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX ); | ||||
|                     buffer.pos( x, y + height, 0 ).tex( 0 / 256.0, height / 256.0 ).endVertex(); | ||||
|                     buffer.pos( x + width, y + height, 0 ).tex( width / 256.0, height / 256.0 ).endVertex(); | ||||
|                     buffer.pos( x + width, y, 0 ).tex( width / 256.0, 0 / 256.0 ).endVertex(); | ||||
|                     buffer.pos( x, y, 0 ).tex( 0 / 256.0, 0 / 256.0 ).endVertex(); | ||||
|                     tesslector.draw(); | ||||
|                 } | ||||
|                 finally | ||||
|                 { | ||||
|                     GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f ); | ||||
|                 } | ||||
|                 FixedWidthFontRenderer.drawEmptyTerminal( | ||||
|                     originX - leftMargin, originY - rightMargin, | ||||
|                     termWidth * FONT_WIDTH + leftMargin + rightMargin, | ||||
|                     termHeight * FONT_HEIGHT + topMargin + bottomMargin | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -7,14 +7,12 @@ 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.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; | ||||
| @@ -22,6 +20,8 @@ import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; | ||||
| import dan200.computercraft.shared.turtle.blocks.TileTurtle; | ||||
| 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; | ||||
| @@ -37,10 +37,21 @@ public final class ComputerCraftProxyClient | ||||
|     { | ||||
|         registerContainers(); | ||||
|  | ||||
|         // While turtles themselves are not transparent, their upgrades may be. | ||||
|         RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.turtleNormal, RenderType.translucent() ); | ||||
|         RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.turtleAdvanced, RenderType.translucent() ); | ||||
|  | ||||
|         // Monitors' textures have _entirely_ transparent sections which, while not translucent, requires being rendered | ||||
|         // as transparent. | ||||
|         RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.monitorNormal, RenderType.translucent() ); | ||||
|         RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.monitorAdvanced, RenderType.translucent() ); | ||||
|  | ||||
|         // Setup TESRs | ||||
|         ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() ); | ||||
|         ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() ); | ||||
|         ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() ); | ||||
|         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() ); | ||||
|     } | ||||
|  | ||||
|     private static void registerContainers() | ||||
|   | ||||
| @@ -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.client.render; | ||||
|  | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.renderer.FirstPersonRenderer; | ||||
| import net.minecraft.entity.player.PlayerEntity; | ||||
| import net.minecraft.item.ItemStack; | ||||
| import net.minecraft.util.Hand; | ||||
| import net.minecraft.util.HandSide; | ||||
| import net.minecraft.util.math.MathHelper; | ||||
|  | ||||
| public abstract class ItemMapLikeRenderer | ||||
| { | ||||
|     /** | ||||
|      * The main rendering method for the item. | ||||
|      * | ||||
|      * @param stack The stack to render | ||||
|      * @see FirstPersonRenderer#renderMapFirstPerson(ItemStack) | ||||
|      */ | ||||
|     protected abstract void renderItem( ItemStack stack ); | ||||
|  | ||||
|     protected void renderItemFirstPerson( Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack ) | ||||
|     { | ||||
|         PlayerEntity player = Minecraft.getInstance().player; | ||||
|  | ||||
|         GlStateManager.pushMatrix(); | ||||
|         if( hand == Hand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() ) | ||||
|         { | ||||
|             renderItemFirstPersonCenter( pitch, equipProgress, swingProgress, stack ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             renderItemFirstPersonSide( | ||||
|                 hand == Hand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(), | ||||
|                 equipProgress, swingProgress, stack | ||||
|             ); | ||||
|         } | ||||
|         GlStateManager.popMatrix(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Renders the item to one side of the player. | ||||
|      * | ||||
|      * @param side          The side to render on | ||||
|      * @param equipProgress The equip progress of this item | ||||
|      * @param swingProgress The swing progress of this item | ||||
|      * @param stack         The stack to render | ||||
|      * @see FirstPersonRenderer#renderMapFirstPersonSide(float, HandSide, float, ItemStack) | ||||
|      */ | ||||
|     private void renderItemFirstPersonSide( 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 ); | ||||
|  | ||||
|         // 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(); | ||||
|         } | ||||
|  | ||||
|         // 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 ); | ||||
|         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 ); | ||||
|  | ||||
|         renderItem( stack ); | ||||
|  | ||||
|         GlStateManager.popMatrix(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Render an item in the middle of the screen. | ||||
|      * | ||||
|      * @param pitch         The pitch of the player | ||||
|      * @param equipProgress The equip progress of this item | ||||
|      * @param swingProgress The swing progress of this item | ||||
|      * @param stack         The stack to render | ||||
|      * @see FirstPersonRenderer#renderMapFirstPerson(float, float, float) | ||||
|      */ | ||||
|     private void renderItemFirstPersonCenter( float pitch, float equipProgress, float swingProgress, ItemStack stack ) | ||||
|     { | ||||
|         FirstPersonRenderer renderer = Minecraft.getInstance().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 ); | ||||
|  | ||||
|         renderItem( 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,9 +5,9 @@ | ||||
|  */ | ||||
| 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.systems.RenderSystem; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.util.Palette; | ||||
| @@ -24,7 +24,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. | ||||
| @@ -63,35 +63,21 @@ public final class PrintoutRenderer | ||||
|  | ||||
|     public static void drawText( int x, int y, int start, TextBuffer[] text, TextBuffer[] colours ) | ||||
|     { | ||||
|         FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance(); | ||||
|  | ||||
|         for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) | ||||
|         { | ||||
|             fontRenderer.drawString( text[start + line], x, y + line * FONT_HEIGHT, colours[start + line], null, 0, 0, false, Palette.DEFAULT ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void drawText( 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 ); | ||||
|  | ||||
|         FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance(); | ||||
|  | ||||
|         for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) | ||||
|         { | ||||
|             fontRenderer.drawString( new TextBuffer( text[start + line] ), x, y + line * FONT_HEIGHT, new TextBuffer( colours[start + line] ), null, 0, 0, false, Palette.DEFAULT ); | ||||
|             FixedWidthFontRenderer.drawString( | ||||
|                 x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], null, Palette.DEFAULT, | ||||
|                 false, 0, 0 | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void drawBorder( double x, double y, double 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 ); | ||||
|         RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f ); | ||||
|         RenderSystem.enableBlend(); | ||||
|         RenderSystem.enableTexture(); | ||||
|         RenderSystem.blendFuncSeparate( SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO ); | ||||
|  | ||||
|         Minecraft.getInstance().getTextureManager().bindTexture( BG ); | ||||
|  | ||||
| @@ -123,8 +109,8 @@ public final class PrintoutRenderer | ||||
|             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( buffer, borderX, y - 8, z - 0.02, 0, COVER_Y, (float) thisWidth, COVER_SIZE ); | ||||
|                 drawTexture( buffer, borderX, y + Y_SIZE - 4, z - 0.02, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE ); | ||||
|                 borderX += thisWidth; | ||||
|             } | ||||
|         } | ||||
| @@ -156,7 +142,7 @@ public final class PrintoutRenderer | ||||
|         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( BufferBuilder buffer, double x, double y, double 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(); | ||||
| @@ -164,7 +150,7 @@ public final class PrintoutRenderer | ||||
|         buffer.pos( x, y, z ).tex( u / BG_SIZE, v / BG_SIZE ).endVertex(); | ||||
|     } | ||||
|  | ||||
|     private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double width, double height, double u, double v, double tWidth, double tHeight ) | ||||
|     private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double width, double 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(); | ||||
|   | ||||
| @@ -5,38 +5,40 @@ | ||||
|  */ | ||||
| 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; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; | ||||
| import dan200.computercraft.shared.peripheral.monitor.TileMonitor; | ||||
| import dan200.computercraft.shared.util.Colour; | ||||
| import dan200.computercraft.shared.util.DirectionUtil; | ||||
| import dan200.computercraft.shared.util.Palette; | ||||
| import net.minecraft.client.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.vertex.DefaultVertexFormats; | ||||
| 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; | ||||
|  | ||||
| public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor> | ||||
| { | ||||
|     @Override | ||||
|     public void render( TileMonitor tileEntity, double posX, double posY, double posZ, float f, int i ) | ||||
|     /** | ||||
|      * {@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 ) | ||||
|     { | ||||
|         if( tileEntity != null ) | ||||
|         { | ||||
|             renderMonitorAt( tileEntity, posX, posY, posZ, f, i ); | ||||
|         } | ||||
|         super( rendererDispatcher ); | ||||
|     } | ||||
|  | ||||
|     private static void renderMonitorAt( TileMonitor monitor, double posX, double posY, double posZ, float f, int i ) | ||||
|     @Override | ||||
|     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(); | ||||
| @@ -58,9 +60,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(); | ||||
| @@ -68,14 +67,17 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor> | ||||
|         float yaw = dir.getHorizontalAngle(); | ||||
|         float pitch = DirectionUtil.toPitchAngle( front ); | ||||
|  | ||||
|         GlStateManager.pushMatrix(); | ||||
|         try | ||||
|         { | ||||
|         // 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( | ||||
|         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 | ||||
| @@ -83,209 +85,76 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor> | ||||
|         double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER); | ||||
|         double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER); | ||||
|  | ||||
|             // Get renderers | ||||
|             Minecraft mc = Minecraft.getInstance(); | ||||
|             Tessellator tessellator = Tessellator.getInstance(); | ||||
|             BufferBuilder renderer = tessellator.getBuffer(); | ||||
|  | ||||
|             // Get terminal | ||||
|             boolean redraw = originTerminal.pollTerminalChanged(); | ||||
|  | ||||
|         // Draw the contents | ||||
|             GlStateManager.depthMask( false ); | ||||
|             GLX.glMultiTexCoord2f( GLX.GL_TEXTURE1, 0xFFFF, 0xFFFF ); | ||||
|             GlStateManager.disableLighting(); | ||||
|             mc.gameRenderer.disableLightmap(); | ||||
|             try | ||||
|             { | ||||
|         Terminal terminal = originTerminal.getTerminal(); | ||||
|         if( terminal != null ) | ||||
|         { | ||||
|                     Palette palette = terminal.getPalette(); | ||||
|  | ||||
|                     // Allocate display lists | ||||
|                     if( originTerminal.renderDisplayLists == null ) | ||||
|             boolean redraw = originTerminal.pollTerminalChanged(); | ||||
|             if( originTerminal.buffer == null ) | ||||
|             { | ||||
|                         originTerminal.createLists(); | ||||
|                 originTerminal.createBuffer(); | ||||
|                 redraw = true; | ||||
|             } | ||||
|             VertexBuffer vbo = originTerminal.buffer; | ||||
|  | ||||
|             // Draw a terminal | ||||
|                     boolean greyscale = !originTerminal.isColour(); | ||||
|                     int width = terminal.getWidth(); | ||||
|                     int height = terminal.getHeight(); | ||||
|                     int cursorX = terminal.getCursorX(); | ||||
|                     int cursorY = terminal.getCursorY(); | ||||
|                     FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance(); | ||||
|             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(); | ||||
|                     try | ||||
|                     { | ||||
|                         double xScale = xSize / (width * FixedWidthFontRenderer.FONT_WIDTH); | ||||
|                         double yScale = ySize / (height * FixedWidthFontRenderer.FONT_HEIGHT); | ||||
|                         GlStateManager.scaled( xScale, -yScale, 1.0 ); | ||||
|             float xMargin = (float) (MARGIN / xScale); | ||||
|             float yMargin = (float) (MARGIN / yScale); | ||||
|  | ||||
|             Matrix4f matrix = transform.getLast().getPositionMatrix(); | ||||
|  | ||||
|                         // Draw background | ||||
|                         mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND ); | ||||
|             if( redraw ) | ||||
|             { | ||||
|                             // Build background display list | ||||
|                             GlStateManager.newList( originTerminal.renderDisplayLists[0], GL11.GL_COMPILE ); | ||||
|                             try | ||||
|                             { | ||||
|                                 double marginXSize = TileMonitor.RENDER_MARGIN / xScale; | ||||
|                                 double marginYSize = TileMonitor.RENDER_MARGIN / yScale; | ||||
|                                 double marginSquash = marginYSize / FixedWidthFontRenderer.FONT_HEIGHT; | ||||
|  | ||||
|                                 // Top and bottom margins | ||||
|                                 GlStateManager.pushMatrix(); | ||||
|                                 try | ||||
|                                 { | ||||
|                                     GlStateManager.scaled( 1.0, marginSquash, 1.0 ); | ||||
|                                     GlStateManager.translated( 0.0, -marginYSize / marginSquash, 0.0 ); | ||||
|                                     fontRenderer.drawStringBackgroundPart( 0, 0, terminal.getBackgroundColourLine( 0 ), marginXSize, marginXSize, greyscale, palette ); | ||||
|                                     GlStateManager.translated( 0.0, (marginYSize + height * FixedWidthFontRenderer.FONT_HEIGHT) / marginSquash, 0.0 ); | ||||
|                                     fontRenderer.drawStringBackgroundPart( 0, 0, terminal.getBackgroundColourLine( height - 1 ), marginXSize, marginXSize, greyscale, palette ); | ||||
|                                 } | ||||
|                                 finally | ||||
|                                 { | ||||
|                                     GlStateManager.popMatrix(); | ||||
|                                 } | ||||
|  | ||||
|                                 // Backgrounds | ||||
|                                 for( int y = 0; y < height; y++ ) | ||||
|                                 { | ||||
|                                     fontRenderer.drawStringBackgroundPart( | ||||
|                                         0, FixedWidthFontRenderer.FONT_HEIGHT * y, | ||||
|                                         terminal.getBackgroundColourLine( y ), | ||||
|                                         marginXSize, marginXSize, | ||||
|                                         greyscale, | ||||
|                                         palette | ||||
|                 Tessellator tessellator = Tessellator.getInstance(); | ||||
|                 BufferBuilder builder = tessellator.getBuffer(); | ||||
|                 builder.begin( FixedWidthFontRenderer.TYPE.getGlMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() ); | ||||
|                 FixedWidthFontRenderer.drawTerminalWithoutCursor( | ||||
|                     IDENTITY, builder, 0, 0, | ||||
|                     terminal, !originTerminal.isColour(), yMargin, yMargin, xMargin, xMargin | ||||
|                 ); | ||||
|                                 } | ||||
|                             } | ||||
|                             finally | ||||
|                             { | ||||
|                                 GlStateManager.endList(); | ||||
|                             } | ||||
|                         } | ||||
|                         GlStateManager.callList( originTerminal.renderDisplayLists[0] ); | ||||
|                         GlStateManager.clearCurrentColor(); | ||||
|  | ||||
|                         // Draw text | ||||
|                         fontRenderer.bindFont(); | ||||
|                         if( redraw ) | ||||
|                         { | ||||
|                             // Build text display list | ||||
|                             GlStateManager.newList( originTerminal.renderDisplayLists[1], GL11.GL_COMPILE ); | ||||
|                             try | ||||
|                             { | ||||
|                                 // Lines | ||||
|                                 for( int y = 0; y < height; y++ ) | ||||
|                                 { | ||||
|                                     fontRenderer.drawStringTextPart( | ||||
|                                         0, FixedWidthFontRenderer.FONT_HEIGHT * y, | ||||
|                                         terminal.getLine( y ), | ||||
|                                         terminal.getTextColourLine( y ), | ||||
|                                         greyscale, | ||||
|                                         palette | ||||
|                                     ); | ||||
|                 builder.finishDrawing(); | ||||
|                 vbo.upload( builder ); | ||||
|             } | ||||
|                             } | ||||
|                             finally | ||||
|                             { | ||||
|                                 GlStateManager.endList(); | ||||
|                             } | ||||
|                         } | ||||
|                         GlStateManager.callList( originTerminal.renderDisplayLists[1] ); | ||||
|                         GlStateManager.clearCurrentColor(); | ||||
|  | ||||
|                         // Draw cursor | ||||
|                         fontRenderer.bindFont(); | ||||
|                         if( redraw ) | ||||
|                         { | ||||
|                             // Build cursor display list | ||||
|                             GlStateManager.newList( originTerminal.renderDisplayLists[2], GL11.GL_COMPILE ); | ||||
|                             try | ||||
|                             { | ||||
|                                 // Cursor | ||||
|                                 if( terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height ) | ||||
|                                 { | ||||
|                                     TextBuffer cursor = new TextBuffer( "_" ); | ||||
|                                     TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 ); | ||||
|                                     fontRenderer.drawString( | ||||
|                                         cursor, | ||||
|                                         FixedWidthFontRenderer.FONT_WIDTH * cursorX, | ||||
|                                         FixedWidthFontRenderer.FONT_HEIGHT * cursorY, | ||||
|                                         cursorColour, null, | ||||
|                                         0, 0, | ||||
|                                         greyscale, | ||||
|                                         palette | ||||
|                                     ); | ||||
|                                 } | ||||
|                             } | ||||
|                             finally | ||||
|                             { | ||||
|                                 GlStateManager.endList(); | ||||
|                             } | ||||
|                         } | ||||
|                         if( FrameInfo.getGlobalCursorBlink() ) | ||||
|                         { | ||||
|                             GlStateManager.callList( originTerminal.renderDisplayLists[2] ); | ||||
|                             GlStateManager.clearCurrentColor(); | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     { | ||||
|                         GlStateManager.popMatrix(); | ||||
|                     } | ||||
|             // 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.enable(); | ||||
|  | ||||
|             vbo.bindBuffer(); | ||||
|             FixedWidthFontRenderer.TYPE.getVertexFormat().setupBufferState( 0L ); | ||||
|             vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getGlMode() ); | ||||
|             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 | ||||
|         { | ||||
|                     // Draw a big black quad | ||||
|                     mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND ); | ||||
|                     final Colour colour = Colour.Black; | ||||
|  | ||||
|                     final float r = colour.getR(); | ||||
|                     final float g = colour.getG(); | ||||
|                     final float b = colour.getB(); | ||||
|  | ||||
|                     renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR ); | ||||
|                     renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 0.0, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|                     renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|                     renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 1.0, 0.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|                     renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 1.0, 1.0 ).color( r, g, b, 1.0f ).endVertex(); | ||||
|                     tessellator.draw(); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 GlStateManager.depthMask( true ); | ||||
|                 mc.gameRenderer.enableLightmap(); | ||||
|                 GlStateManager.enableLighting(); | ||||
|             FixedWidthFontRenderer.drawEmptyTerminal( | ||||
|                 transform.getLast().getPositionMatrix(), renderer, | ||||
|                 -MARGIN, MARGIN, | ||||
|                 (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|             // Draw the depth blocker | ||||
|             GlStateManager.colorMask( false, false, false, false ); | ||||
|             try | ||||
|             { | ||||
|                 mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND ); | ||||
|                 renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION ); | ||||
|                 renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex(); | ||||
|                 renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex(); | ||||
|                 renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex(); | ||||
|                 renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex(); | ||||
|                 tessellator.draw(); | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 GlStateManager.colorMask( true, true, true, true ); | ||||
|             } | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f ); | ||||
|             GlStateManager.popMatrix(); | ||||
|         } | ||||
|         FixedWidthFontRenderer.drawBlocker( | ||||
|             transform.getLast().getPositionMatrix(), renderer, | ||||
|             (float) -TileMonitor.RENDER_MARGIN, (float) TileMonitor.RENDER_MARGIN, | ||||
|             (float) (xSize + 2 * TileMonitor.RENDER_MARGIN), (float) -(ySize + TileMonitor.RENDER_MARGIN * 2) | ||||
|         ); | ||||
|  | ||||
|         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,10 +45,11 @@ 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 ) | ||||
| @@ -68,169 +66,126 @@ public class TileEntityTurtleRenderer extends TileEntityRenderer<TileTurtle> | ||||
|  | ||||
|     public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas ) | ||||
|     { | ||||
|         if( overlay != null ) | ||||
|         { | ||||
|             return new ModelResourceLocation( overlay, "inventory" ); | ||||
|         } | ||||
|         else if( christmas ) | ||||
|         { | ||||
|             return ELF_OVERLAY_MODEL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|         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().getPositionMatrix(); | ||||
|             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 | ||||
|         { | ||||
|             BlockState state = turtle.getBlockState(); | ||||
|             // Setup the transform | ||||
|         transform.push(); | ||||
|  | ||||
|         // 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 ); | ||||
|         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" )) ) | ||||
|         { | ||||
|                 // 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 ); | ||||
|             // Flip the model | ||||
|             transform.scale( 1.0f, -1.0f, 1.0f ); | ||||
|         } | ||||
|             GlStateManager.translatef( -0.5f, -0.5f, -0.5f ); | ||||
|         transform.translate( -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 } ); | ||||
|         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 | ||||
|             ); | ||||
|         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(); | ||||
|                 } | ||||
|             renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null ); | ||||
|         } | ||||
|  | ||||
|         // Render the upgrades | ||||
|             renderUpgrade( state, turtle, TurtleSide.Left, partialTicks ); | ||||
|             renderUpgrade( state, turtle, TurtleSide.Right, partialTicks ); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             GlStateManager.popMatrix(); | ||||
|             GlStateManager.cullFace( GlStateManager.CullFace.BACK ); | ||||
|         } | ||||
|         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 | ||||
|             { | ||||
|         if( upgrade == null ) return; | ||||
|         transform.push(); | ||||
|  | ||||
|         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 ); | ||||
|         transform.translate( 0.0f, 0.5f, 0.5f ); | ||||
|         transform.rotate( Vector3f.XN.rotationDegrees( toolAngle ) ); | ||||
|         transform.translate( 0.0f, -0.5f, -0.5f ); | ||||
|  | ||||
|                 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(); | ||||
|             } | ||||
|         } | ||||
|         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; | ||||
|             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 ); | ||||
|         } | ||||
|  | ||||
|             LightUtil.renderQuadColor( buffer, quad, colour ); | ||||
|         } | ||||
|         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 ); | ||||
|             } | ||||
|         ResourceLocation model = new ResourceLocation( JSONUtils.getString( modelContents, "model" ) ); | ||||
|         return new TurtleModel( model ); | ||||
|     } | ||||
|  | ||||
|         throw new IllegalStateException( "Loader does not accept " + name ); | ||||
|     } | ||||
|  | ||||
|     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,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().getPositionMatrix() ); | ||||
|     } | ||||
|  | ||||
|     private static class TurtleModelCombination | ||||
| @@ -144,25 +144,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 +184,12 @@ public class TurtleSmartItemModel implements IBakedModel | ||||
|         return familyModel.isBuiltInRenderer(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean func_230044_c_() | ||||
|     { | ||||
|         return familyModel.func_230044_c_(); | ||||
|     } | ||||
|  | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     @Deprecated | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| package dan200.computercraft.client.render; | ||||
| 
 | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.shared.peripheral.modem.wired.BlockCable; | ||||
| import dan200.computercraft.shared.peripheral.modem.wired.CableShapes; | ||||
| @@ -21,7 +22,7 @@ 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; | ||||
| @@ -40,11 +41,9 @@ public final class CableHighlightRenderer | ||||
|      * @see WorldRenderer#drawSelectionBox(ActiveRenderInfo, RayTraceResult, int) | ||||
|      */ | ||||
|     @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(); | ||||
| @@ -61,14 +60,14 @@ public final class CableHighlightRenderer | ||||
| 
 | ||||
|         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 ); | ||||
|         RenderSystem.enableBlend(); | ||||
|         RenderSystem.blendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO ); | ||||
|         RenderSystem.lineWidth( Math.max( 2.5F, mc.getMainWindow().getFramebufferWidth() / 1920.0F * 2.5F ) ); | ||||
|         RenderSystem.disableTexture(); | ||||
|         RenderSystem.depthMask( false ); | ||||
|         RenderSystem.matrixMode( GL11.GL_PROJECTION ); | ||||
|         RenderSystem.pushMatrix(); | ||||
|         RenderSystem.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 ) | ||||
| @@ -80,10 +79,10 @@ public final class CableHighlightRenderer | ||||
|             0.0F, 0.0F, 0.0F, 0.4F | ||||
|         ); | ||||
| 
 | ||||
|         GlStateManager.popMatrix(); | ||||
|         GlStateManager.matrixMode( GL11.GL_MODELVIEW ); | ||||
|         GlStateManager.depthMask( true ); | ||||
|         GlStateManager.enableTexture(); | ||||
|         GlStateManager.disableBlend(); | ||||
|         RenderSystem.popMatrix(); | ||||
|         RenderSystem.matrixMode( GL11.GL_MODELVIEW ); | ||||
|         RenderSystem.depthMask( true ); | ||||
|         RenderSystem.enableTexture(); | ||||
|         RenderSystem.disableBlend(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,133 @@ | ||||
| /* | ||||
|  * 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.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; | ||||
| import net.minecraft.util.HandSide; | ||||
| import net.minecraft.util.math.MathHelper; | ||||
|  | ||||
| public abstract class ItemMapLikeRenderer | ||||
| { | ||||
|     /** | ||||
|      * The main rendering method for the item. | ||||
|      * | ||||
|      * @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( MatrixStack transform, IRenderTypeBuffer render, 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; | ||||
|  | ||||
|         transform.push(); | ||||
|         if( hand == Hand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() ) | ||||
|         { | ||||
|             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 | ||||
|             ); | ||||
|         } | ||||
|         transform.pop(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Renders the item to one side of the player. | ||||
|      * | ||||
|      * @param side          The side to render on | ||||
|      * @param equipProgress The equip progress of this item | ||||
|      * @param swingProgress The swing progress of this item | ||||
|      * @param stack         The stack to render | ||||
|      * @see FirstPersonRenderer#renderMapFirstPersonSide(MatrixStack, IRenderTypeBuffer, int, float, HandSide, float, ItemStack) | ||||
|      */ | ||||
|     private void renderItemFirstPersonSide( MatrixStack transform, IRenderTypeBuffer render, int lightTexture, HandSide side, float equipProgress, float swingProgress, ItemStack stack ) | ||||
|     { | ||||
|         Minecraft minecraft = Minecraft.getInstance(); | ||||
|         float offset = side == HandSide.RIGHT ? 1f : -1f; | ||||
|         transform.translate( offset * 0.125f, -0.125f, 0f ); | ||||
|  | ||||
|         // If the player is not invisible then render a single arm | ||||
|         if( !minecraft.player.isInvisible() ) | ||||
|         { | ||||
|             transform.push(); | ||||
|             transform.rotate( Vector3f.field_229183_f_.func_229187_a_( offset * 10f ) ); | ||||
|             minecraft.getFirstPersonRenderer().renderArmFirstPerson( transform, render, lightTexture, equipProgress, swingProgress, side ); | ||||
|             transform.pop(); | ||||
|         } | ||||
|  | ||||
|         // Setup the appropriate transformations. This is just copied from the | ||||
|         // corresponding method in ItemRenderer. | ||||
|         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 ); | ||||
|         transform.translate( offset * f3, f4 - 0.3f * f2, f5 ); | ||||
|         transform.rotate( Vector3f.field_229179_b_.func_229187_a_( f2 * -45f ) ); | ||||
|         transform.rotate( Vector3f.field_229181_d_.func_229187_a_( offset * f2 * -30f ) ); | ||||
|  | ||||
|         renderItem( transform, render, stack ); | ||||
|  | ||||
|         transform.pop(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Render an item in the middle of the screen. | ||||
|      * | ||||
|      * @param pitch         The pitch of the player | ||||
|      * @param equipProgress The equip progress of this item | ||||
|      * @param swingProgress The swing progress of this item | ||||
|      * @param stack         The stack to render | ||||
|      * @see FirstPersonRenderer#renderMapFirstPerson(MatrixStack, IRenderTypeBuffer, int, float, float, float) | ||||
|      */ | ||||
|     private void renderItemFirstPersonCenter( MatrixStack transform, IRenderTypeBuffer render, int lightTexture, float pitch, float equipProgress, float swingProgress, ItemStack stack ) | ||||
|     { | ||||
|         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 ); | ||||
|         transform.translate( 0, -tX / 2, tZ ); | ||||
|  | ||||
|         float pitchAngle = renderer.getMapAngleFromPitch( pitch ); | ||||
|         transform.translate( 0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f ); | ||||
|         transform.rotate( Vector3f.field_229179_b_.func_229187_a_( pitchAngle * -85.0f ) ); | ||||
|         if( !minecraft.player.isInvisible() ) | ||||
|         { | ||||
|             transform.push(); | ||||
|             transform.rotate( Vector3f.field_229181_d_.func_229187_a_( 90.0F ) ); | ||||
|             renderer.renderArm( transform, render, lightTexture, HandSide.RIGHT ); | ||||
|             renderer.renderArm( transform, render, lightTexture, HandSide.LEFT ); | ||||
|             transform.pop(); | ||||
|         } | ||||
|  | ||||
|         float rX = MathHelper.sin( swingRt * (float) Math.PI ); | ||||
|         transform.rotate( Vector3f.field_229179_b_.func_229187_a_( 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.FrameInfo; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| @@ -18,6 +20,7 @@ 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.IRenderTypeBuffer; | ||||
| import net.minecraft.client.renderer.Tessellator; | ||||
| import net.minecraft.client.renderer.vertex.DefaultVertexFormats; | ||||
| import net.minecraft.item.ItemStack; | ||||
| @@ -53,11 +56,16 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
|         if( !(stack.getItem() instanceof ItemPocketComputer) ) return; | ||||
| 
 | ||||
|         event.setCanceled( true ); | ||||
|         INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() ); | ||||
|         Minecraft minecraft = Minecraft.getInstance(); | ||||
|         INSTANCE.renderItemFirstPerson( | ||||
|             event.getMatrixStack(), minecraft.func_228019_au_().func_228487_b_(), | ||||
|             minecraft.getRenderManager().func_229085_a_( minecraft.player, event.getPartialTicks() ), | ||||
|             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(); | ||||
| @@ -79,18 +87,17 @@ 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(); | ||||
|         // TODO: RenderSystem.disableLighting(); | ||||
|         // TODO: RenderSystem.disableDepthTest(); | ||||
| 
 | ||||
|         GlStateManager.disableLighting(); | ||||
|         GlStateManager.disableDepthTest(); | ||||
|         RenderSystem.rotatef( 180f, 0f, 1f, 0f ); | ||||
|         RenderSystem.rotatef( 180f, 0f, 0f, 1f ); | ||||
|         transform.scale( 0.5f, 0.5f, 0.5f ); | ||||
| 
 | ||||
|         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(); | ||||
| @@ -106,7 +113,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
|         if( computer != null && terminal != null ) | ||||
|         { | ||||
|             // If we've a computer and terminal then attempt to render it. | ||||
|             renderTerminal( terminal, !computer.isColour(), width, height ); | ||||
|             renderTerminal( terminal, !computer.isColour() ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| @@ -122,9 +129,9 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
|             tessellator.draw(); | ||||
|         } | ||||
| 
 | ||||
|         GlStateManager.enableDepthTest(); | ||||
|         GlStateManager.enableLighting(); | ||||
|         GlStateManager.popMatrix(); | ||||
|         // TODO: RenderSystem.enableDepthTest(); | ||||
|         // TODO: RenderSystem.enableLighting(); | ||||
|         transform.pop(); | ||||
|     } | ||||
| 
 | ||||
|     private static void renderFrame( ComputerFamily family, int colour, int width, int height ) | ||||
| @@ -171,8 +178,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
| 
 | ||||
|     private static void renderLight( 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; | ||||
| @@ -187,10 +194,10 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
|         buffer.pos( width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex(); | ||||
| 
 | ||||
|         tessellator.draw(); | ||||
|         GlStateManager.enableTexture(); | ||||
|         RenderSystem.enableTexture(); | ||||
|     } | ||||
| 
 | ||||
|     private static void renderTerminal( Terminal terminal, boolean greyscale, int width, int height ) | ||||
|     private static void renderTerminal( Terminal terminal, boolean greyscale ) | ||||
|     { | ||||
|         synchronized( terminal ) | ||||
|         { | ||||
| @@ -237,12 +244,12 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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( 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 ); | ||||
|     } | ||||
| 
 | ||||
|     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( 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(); | ||||
| @@ -5,7 +5,7 @@ | ||||
|  */ | ||||
| package dan200.computercraft.client.render; | ||||
| 
 | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.shared.media.items.ItemPrintout; | ||||
| import net.minecraft.item.ItemStack; | ||||
| @@ -48,16 +48,16 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer | ||||
|     { | ||||
|         // Setup various transformations. Note that these are partially adapated from the corresponding method | ||||
|         // in FirstPersonRenderer.renderFirstPersonMap | ||||
|         GlStateManager.disableLighting(); | ||||
|         RenderSystem.disableLighting(); | ||||
| 
 | ||||
|         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 ); | ||||
|         RenderSystem.rotatef( 180f, 0f, 1f, 0f ); | ||||
|         RenderSystem.rotatef( 180f, 0f, 0f, 1f ); | ||||
|         RenderSystem.scalef( 0.42f, 0.42f, -0.42f ); | ||||
|         RenderSystem.translatef( -0.5f, -0.48f, 0.0f ); | ||||
| 
 | ||||
|         drawPrintout( stack ); | ||||
| 
 | ||||
|         GlStateManager.enableLighting(); | ||||
|         RenderSystem.enableLighting(); | ||||
|     } | ||||
| 
 | ||||
|     @SubscribeEvent | ||||
| @@ -68,18 +68,18 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer | ||||
| 
 | ||||
|         event.setCanceled( true ); | ||||
| 
 | ||||
|         GlStateManager.disableLighting(); | ||||
|         RenderSystem.disableLighting(); | ||||
| 
 | ||||
|         // 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 ); | ||||
|         RenderSystem.translatef( 0.0f, 0.0f, -0.001f ); | ||||
|         RenderSystem.rotatef( 180f, 0f, 0f, 1f ); | ||||
|         RenderSystem.scalef( 0.95f, 0.95f, -0.95f ); | ||||
|         RenderSystem.translatef( -0.5f, -0.5f, 0.0f ); | ||||
| 
 | ||||
|         drawPrintout( stack ); | ||||
| 
 | ||||
|         GlStateManager.enableLighting(); | ||||
|         GlStateManager.disableBlend(); | ||||
|         RenderSystem.enableLighting(); | ||||
|         RenderSystem.disableBlend(); | ||||
|     } | ||||
| 
 | ||||
|     private static void drawPrintout( ItemStack stack ) | ||||
| @@ -106,8 +106,8 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer | ||||
| 
 | ||||
|         // 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 ); | ||||
|         RenderSystem.scaled( scale, scale, scale ); | ||||
|         RenderSystem.translated( (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 ) ); | ||||
| @@ -5,25 +5,22 @@ | ||||
|  */ | ||||
| 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; | ||||
| 
 | ||||
| @@ -39,15 +36,12 @@ public final class 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; | ||||
|         } | ||||
|         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,50 +58,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(); | ||||
|         IVertexBuilder buffer = Minecraft.getInstance().func_228019_au_().func_228487_b_().getBuffer( RenderType.lines() ); | ||||
| 
 | ||||
|         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.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 ); | ||||
|         Matrix4f transform = transformStack.getLast().getPositionMatrix(); | ||||
|         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; | ||||
|         float minX = x == 0 ? -EXPAND : 1 + EXPAND; | ||||
|         float minY = y == 0 ? -EXPAND : 1 + EXPAND; | ||||
|         float minZ = z == 0 ? -EXPAND : 1 + EXPAND; | ||||
| 
 | ||||
|         buffer.pos( minX, minY, minZ ).color( 0, 0, 0, 0.4f ).endVertex(); | ||||
|         buffer.pos( | ||||
|         buffer.pos( transform, minX, minY, minZ ).color( 0, 0, 0, 0.4f ).endVertex(); | ||||
|         buffer.pos( transform, | ||||
|             minX + direction.getXOffset() * (1 + EXPAND * 2), | ||||
|             minY + direction.getYOffset() * (1 + EXPAND * 2), | ||||
|             minZ + direction.getZOffset() * (1 + EXPAND * 2) | ||||
| @@ -6,6 +6,7 @@ | ||||
| package dan200.computercraft.client.render; | ||||
| 
 | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.shared.peripheral.modem.wired.BlockCable; | ||||
| import dan200.computercraft.shared.peripheral.modem.wired.CableModemVariant; | ||||
| @@ -110,17 +111,17 @@ public class TileEntityCableRenderer extends TileEntityRenderer<TileCable> | ||||
|      */ | ||||
|     private void preRenderDamagedBlocks() | ||||
|     { | ||||
|         GlStateManager.disableLighting(); | ||||
|         RenderSystem.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(); | ||||
|         RenderSystem.enableBlend(); | ||||
|         RenderSystem.blendFuncSeparate( GlStateManager.SourceFactor.DST_COLOR, GlStateManager.DestFactor.SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO ); | ||||
|         RenderSystem.enableBlend(); | ||||
|         RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 0.5F ); | ||||
|         RenderSystem.polygonOffset( -3.0F, -3.0F ); | ||||
|         RenderSystem.enablePolygonOffset(); | ||||
|         RenderSystem.alphaFunc( 516, 0.1F ); | ||||
|         RenderSystem.enableAlphaTest(); | ||||
|         RenderSystem.pushMatrix(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -130,11 +131,11 @@ public class TileEntityCableRenderer extends TileEntityRenderer<TileCable> | ||||
|      */ | ||||
|     private void postRenderDamagedBlocks() | ||||
|     { | ||||
|         GlStateManager.disableAlphaTest(); | ||||
|         GlStateManager.polygonOffset( 0.0F, 0.0F ); | ||||
|         GlStateManager.disablePolygonOffset(); | ||||
|         GlStateManager.disablePolygonOffset(); | ||||
|         GlStateManager.depthMask( true ); | ||||
|         GlStateManager.popMatrix(); | ||||
|         RenderSystem.disableAlphaTest(); | ||||
|         RenderSystem.polygonOffset( 0.0F, 0.0F ); | ||||
|         RenderSystem.disablePolygonOffset(); | ||||
|         RenderSystem.disablePolygonOffset(); | ||||
|         RenderSystem.depthMask( true ); | ||||
|         RenderSystem.popMatrix(); | ||||
|     } | ||||
| } | ||||
| @@ -324,7 +324,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(); | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
| @@ -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 ) | ||||
|     { | ||||
|   | ||||
| @@ -5,8 +5,9 @@ | ||||
|  */ | ||||
| package dan200.computercraft.shared.peripheral.monitor; | ||||
|  | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.shared.common.ClientTerminal; | ||||
| import net.minecraft.client.renderer.vertex.VertexBuffer; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| @@ -23,7 +24,7 @@ public class ClientMonitor extends ClientTerminal | ||||
|  | ||||
|     public long lastRenderFrame = -1; | ||||
|     public BlockPos lastRenderPos = null; | ||||
|     public int[] renderDisplayLists = null; | ||||
|     public VertexBuffer buffer = null; | ||||
|  | ||||
|     public ClientMonitor( boolean colour, TileMonitor origin ) | ||||
|     { | ||||
| @@ -37,17 +38,11 @@ public class ClientMonitor extends ClientTerminal | ||||
|     } | ||||
|  | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public void createLists() | ||||
|     public void createBuffer() | ||||
|     { | ||||
|         if( renderDisplayLists == null ) | ||||
|         if( buffer == null ) | ||||
|         { | ||||
|             renderDisplayLists = new int[3]; | ||||
|  | ||||
|             for( int i = 0; i < renderDisplayLists.length; i++ ) | ||||
|             { | ||||
|                 renderDisplayLists[i] = GlStateManager.genLists( 1 ); | ||||
|             } | ||||
|  | ||||
|             buffer = new VertexBuffer( FixedWidthFontRenderer.TYPE.getVertexFormat() ); | ||||
|             synchronized( allMonitors ) | ||||
|             { | ||||
|                 allMonitors.add( this ); | ||||
| @@ -58,19 +53,15 @@ public class ClientMonitor extends ClientTerminal | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public void destroy() | ||||
|     { | ||||
|         if( renderDisplayLists != null ) | ||||
|         if( buffer != null ) | ||||
|         { | ||||
|             synchronized( allMonitors ) | ||||
|             { | ||||
|                 allMonitors.remove( this ); | ||||
|             } | ||||
|  | ||||
|             for( int list : renderDisplayLists ) | ||||
|             { | ||||
|                 GlStateManager.deleteLists( list, 1 ); | ||||
|             } | ||||
|  | ||||
|             renderDisplayLists = null; | ||||
|             buffer.close(); | ||||
|             buffer = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -82,13 +73,10 @@ public class ClientMonitor extends ClientTerminal | ||||
|             for( Iterator<ClientMonitor> iterator = allMonitors.iterator(); iterator.hasNext(); ) | ||||
|             { | ||||
|                 ClientMonitor monitor = iterator.next(); | ||||
|                 if( monitor.renderDisplayLists != null ) | ||||
|                 if( monitor.buffer != null ) | ||||
|                 { | ||||
|                     for( int list : monitor.renderDisplayLists ) | ||||
|                     { | ||||
|                         GlStateManager.deleteLists( list, 1 ); | ||||
|                     } | ||||
|                     monitor.renderDisplayLists = null; | ||||
|                     monitor.buffer.close(); | ||||
|                     monitor.buffer = null; | ||||
|                 } | ||||
|  | ||||
|                 iterator.remove(); | ||||
|   | ||||
| @@ -18,6 +18,7 @@ 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; | ||||
| @@ -104,10 +105,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 +119,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 | ||||
|   | ||||
| @@ -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() ); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| @@ -127,12 +125,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 ) | ||||
|         { | ||||
|   | ||||
| @@ -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; | ||||
| @@ -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; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -337,8 +337,7 @@ public class TurtleBrain implements ITurtleAccess | ||||
|                     { | ||||
|                         // Copy the old turtle state into the new turtle | ||||
|                         TileTurtle newTurtle = (TileTurtle) newTile; | ||||
|                         newTurtle.setWorld( world ); | ||||
|                         newTurtle.setPos( pos ); | ||||
|                         newTurtle.setWorldAndPos( world, pos ); | ||||
|                         newTurtle.transferStateFrom( oldOwner ); | ||||
|                         newTurtle.createServerComputer().setWorld( world ); | ||||
|                         newTurtle.createServerComputer().setPosition( pos ); | ||||
|   | ||||
| @@ -170,16 +170,16 @@ public class TurtlePlaceCommand implements ITurtleCommand | ||||
|  | ||||
|     private static void orientPlayer( ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction direction ) | ||||
|     { | ||||
|         turtlePlayer.posX = position.getX() + 0.5; | ||||
|         turtlePlayer.posY = position.getY() + 0.5; | ||||
|         turtlePlayer.posZ = position.getZ() + 0.5; | ||||
|         double posX = position.getX() + 0.5; | ||||
|         double posY = position.getY() + 0.5; | ||||
|         double posZ = position.getZ() + 0.5; | ||||
|  | ||||
|         // Stop intersection with the turtle itself | ||||
|         if( turtle.getPosition().equals( position ) ) | ||||
|         { | ||||
|             turtlePlayer.posX += 0.48 * direction.getXOffset(); | ||||
|             turtlePlayer.posY += 0.48 * direction.getYOffset(); | ||||
|             turtlePlayer.posZ += 0.48 * direction.getZOffset(); | ||||
|             posX += 0.48 * direction.getXOffset(); | ||||
|             posY += 0.48 * direction.getYOffset(); | ||||
|             posZ += 0.48 * direction.getZOffset(); | ||||
|         } | ||||
|  | ||||
|         if( direction.getAxis() != Direction.Axis.Y ) | ||||
| @@ -193,9 +193,10 @@ public class TurtlePlaceCommand implements ITurtleCommand | ||||
|             turtlePlayer.rotationPitch = DirectionUtil.toPitchAngle( direction ); | ||||
|         } | ||||
|  | ||||
|         turtlePlayer.prevPosX = turtlePlayer.posX; | ||||
|         turtlePlayer.prevPosY = turtlePlayer.posY; | ||||
|         turtlePlayer.prevPosZ = turtlePlayer.posZ; | ||||
|         turtlePlayer.setRawPosition( posX, posY, posZ ); | ||||
|         turtlePlayer.prevPosX = posX; | ||||
|         turtlePlayer.prevPosY = posY; | ||||
|         turtlePlayer.prevPosZ = posZ; | ||||
|         turtlePlayer.prevRotationPitch = turtlePlayer.rotationPitch; | ||||
|         turtlePlayer.prevRotationYaw = turtlePlayer.rotationYaw; | ||||
|  | ||||
| @@ -209,7 +210,7 @@ public class TurtlePlaceCommand implements ITurtleCommand | ||||
|         // See if there is an entity present | ||||
|         final World world = turtle.getWorld(); | ||||
|         final BlockPos position = turtle.getPosition(); | ||||
|         Vec3d turtlePos = new Vec3d( turtlePlayer.posX, turtlePlayer.posY, turtlePlayer.posZ ); | ||||
|         Vec3d turtlePos = turtlePlayer.getPositionVec(); | ||||
|         Vec3d rayDir = turtlePlayer.getLook( 1.0f ); | ||||
|         Pair<Entity, Vec3d> hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); | ||||
|         if( hit == null ) | ||||
|   | ||||
| @@ -65,9 +65,7 @@ public final class TurtlePlayer extends FakePlayer | ||||
|         } | ||||
|  | ||||
|         BlockPos position = turtle.getPosition(); | ||||
|         posX = position.getX() + 0.5; | ||||
|         posY = position.getY() + 0.5; | ||||
|         posZ = position.getZ() + 0.5; | ||||
|         setRawPosition( position.getX() + 0.5, position.getY() + 0.5, position.getZ() + 0.5 ); | ||||
|  | ||||
|         rotationYaw = turtle.getDirection().getHorizontalAngle(); | ||||
|         rotationPitch = 0.0f; | ||||
| @@ -137,10 +135,9 @@ public final class TurtlePlayer extends FakePlayer | ||||
|     @Override | ||||
|     public Vec3d getPositionVector() | ||||
|     { | ||||
|         return new Vec3d( posX, posY, posZ ); | ||||
|         return getPositionVec(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     public float getEyeHeight( @Nonnull Pose pose ) | ||||
|     { | ||||
|   | ||||
| @@ -6,22 +6,18 @@ | ||||
| package dan200.computercraft.shared.turtle.upgrades; | ||||
|  | ||||
| import dan200.computercraft.api.AbstractTurtleUpgrade; | ||||
| import dan200.computercraft.api.client.TransformedModel; | ||||
| import dan200.computercraft.api.peripheral.IPeripheral; | ||||
| import dan200.computercraft.api.turtle.ITurtleAccess; | ||||
| import dan200.computercraft.api.turtle.TurtleSide; | ||||
| import dan200.computercraft.api.turtle.TurtleUpgradeType; | ||||
| import net.minecraft.block.Blocks; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.renderer.model.IBakedModel; | ||||
| import net.minecraft.client.renderer.model.ModelManager; | ||||
| import net.minecraft.client.renderer.model.ModelResourceLocation; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.vecmath.Matrix4f; | ||||
|  | ||||
| public class TurtleCraftingTable extends AbstractTurtleUpgrade | ||||
| { | ||||
| @@ -55,19 +51,9 @@ public class TurtleCraftingTable extends AbstractTurtleUpgrade | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public Pair<IBakedModel, Matrix4f> getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     { | ||||
|         loadModelLocations(); | ||||
|  | ||||
|         Matrix4f transform = null; | ||||
|         ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelMesher().getModelManager(); | ||||
|         if( side == TurtleSide.Left ) | ||||
|         { | ||||
|             return Pair.of( modelManager.getModel( m_leftModel ), transform ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return Pair.of( modelManager.getModel( m_rightModel ), transform ); | ||||
|         } | ||||
|         return TransformedModel.of( side == TurtleSide.Left ? m_leftModel : m_rightModel ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,13 +7,11 @@ package dan200.computercraft.shared.turtle.upgrades; | ||||
|  | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.api.AbstractTurtleUpgrade; | ||||
| import dan200.computercraft.api.client.TransformedModel; | ||||
| import dan200.computercraft.api.peripheral.IPeripheral; | ||||
| import dan200.computercraft.api.turtle.*; | ||||
| import dan200.computercraft.shared.peripheral.modem.ModemState; | ||||
| import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.renderer.model.IBakedModel; | ||||
| import net.minecraft.client.renderer.model.ModelManager; | ||||
| import net.minecraft.client.renderer.model.ModelResourceLocation; | ||||
| import net.minecraft.nbt.CompoundNBT; | ||||
| import net.minecraft.util.Direction; | ||||
| @@ -23,10 +21,8 @@ import net.minecraft.util.math.Vec3d; | ||||
| import net.minecraft.world.World; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.vecmath.Matrix4f; | ||||
|  | ||||
| public class TurtleModem extends AbstractTurtleUpgrade | ||||
| { | ||||
| @@ -129,7 +125,7 @@ public class TurtleModem extends AbstractTurtleUpgrade | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public Pair<IBakedModel, Matrix4f> getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     { | ||||
|         loadModelLocations(); | ||||
|  | ||||
| @@ -137,28 +133,12 @@ public class TurtleModem extends AbstractTurtleUpgrade | ||||
|         if( turtle != null ) | ||||
|         { | ||||
|             CompoundNBT turtleNBT = turtle.getUpgradeNBTData( side ); | ||||
|             if( turtleNBT.contains( "active" ) ) | ||||
|             { | ||||
|                 active = turtleNBT.getBoolean( "active" ); | ||||
|             } | ||||
|             active = turtleNBT.contains( "active" ) && turtleNBT.getBoolean( "active" ); | ||||
|         } | ||||
|  | ||||
|         Matrix4f transform = null; | ||||
|         ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelMesher().getModelManager(); | ||||
|         if( side == TurtleSide.Left ) | ||||
|         { | ||||
|             return Pair.of( | ||||
|                 active ? modelManager.getModel( m_leftOnModel ) : modelManager.getModel( m_leftOffModel ), | ||||
|                 transform | ||||
|             ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return Pair.of( | ||||
|                 active ? modelManager.getModel( m_rightOnModel ) : modelManager.getModel( m_rightOffModel ), | ||||
|                 transform | ||||
|             ); | ||||
|         } | ||||
|         return side == TurtleSide.Left | ||||
|             ? TransformedModel.of( active ? m_leftOnModel : m_leftOffModel ) | ||||
|             : TransformedModel.of( active ? m_rightOnModel : m_rightOffModel ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -8,14 +8,12 @@ package dan200.computercraft.shared.turtle.upgrades; | ||||
|  | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.api.AbstractTurtleUpgrade; | ||||
| import dan200.computercraft.api.client.TransformedModel; | ||||
| import dan200.computercraft.api.peripheral.IPeripheral; | ||||
| import dan200.computercraft.api.turtle.ITurtleAccess; | ||||
| import dan200.computercraft.api.turtle.TurtleSide; | ||||
| import dan200.computercraft.api.turtle.TurtleUpgradeType; | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.renderer.model.IBakedModel; | ||||
| import net.minecraft.client.renderer.model.ModelManager; | ||||
| import net.minecraft.client.renderer.model.ModelResourceLocation; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| @@ -23,10 +21,8 @@ import net.minecraft.util.math.Vec3d; | ||||
| import net.minecraft.world.World; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.vecmath.Matrix4f; | ||||
|  | ||||
| public class TurtleSpeaker extends AbstractTurtleUpgrade | ||||
| { | ||||
| @@ -89,19 +85,10 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public Pair<IBakedModel, Matrix4f> getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     { | ||||
|         loadModelLocations(); | ||||
|         ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelMesher().getModelManager(); | ||||
|  | ||||
|         if( side == TurtleSide.Left ) | ||||
|         { | ||||
|             return Pair.of( modelManager.getModel( m_leftModel ), null ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return Pair.of( modelManager.getModel( m_rightModel ), null ); | ||||
|         } | ||||
|         return TransformedModel.of( side == TurtleSide.Left ? m_leftModel : m_rightModel ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -7,6 +7,7 @@ package dan200.computercraft.shared.turtle.upgrades; | ||||
|  | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.api.AbstractTurtleUpgrade; | ||||
| import dan200.computercraft.api.client.TransformedModel; | ||||
| import dan200.computercraft.api.turtle.*; | ||||
| import dan200.computercraft.api.turtle.event.TurtleAttackEvent; | ||||
| import dan200.computercraft.api.turtle.event.TurtleBlockEvent; | ||||
| @@ -19,8 +20,8 @@ import dan200.computercraft.shared.util.WorldUtil; | ||||
| import net.minecraft.block.Block; | ||||
| import net.minecraft.block.BlockState; | ||||
| import net.minecraft.block.Blocks; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.renderer.model.IBakedModel; | ||||
| import net.minecraft.client.renderer.Matrix4f; | ||||
| import net.minecraft.client.renderer.TransformationMatrix; | ||||
| import net.minecraft.entity.Entity; | ||||
| import net.minecraft.entity.SharedMonsterAttributes; | ||||
| import net.minecraft.entity.item.ArmorStandEntity; | ||||
| @@ -42,7 +43,6 @@ import net.minecraftforge.event.world.BlockEvent; | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.vecmath.Matrix4f; | ||||
| import java.util.List; | ||||
| import java.util.function.Function; | ||||
|  | ||||
| @@ -71,20 +71,16 @@ public class TurtleTool extends AbstractTurtleUpgrade | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     public Pair<IBakedModel, Matrix4f> getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) | ||||
|     { | ||||
|         float xOffset = side == TurtleSide.Left ? -0.40625f : 0.40625f; | ||||
|         Matrix4f transform = new Matrix4f( | ||||
|         Matrix4f transform = new Matrix4f( new float[] { | ||||
|             0.0f, 0.0f, -1.0f, 1.0f + xOffset, | ||||
|             1.0f, 0.0f, 0.0f, 0.0f, | ||||
|             0.0f, -1.0f, 0.0f, 1.0f, | ||||
|             0.0f, 0.0f, 0.0f, 1.0f | ||||
|         ); | ||||
|         Minecraft mc = Minecraft.getInstance(); | ||||
|         return Pair.of( | ||||
|             mc.getItemRenderer().getItemModelMesher().getItemModel( getCraftingItem() ), | ||||
|             transform | ||||
|         ); | ||||
|             0.0f, 0.0f, 0.0f, 1.0f, | ||||
|         } ); | ||||
|         return TransformedModel.of( getCraftingItem(), new TransformationMatrix( transform ) ); | ||||
|     } | ||||
|  | ||||
|     @Nonnull | ||||
| @@ -124,7 +120,7 @@ public class TurtleTool extends AbstractTurtleUpgrade | ||||
|         final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction ); | ||||
|  | ||||
|         // See if there is an entity present | ||||
|         Vec3d turtlePos = new Vec3d( turtlePlayer.posX, turtlePlayer.posY, turtlePlayer.posZ ); | ||||
|         Vec3d turtlePos = turtlePlayer.getPositionVec(); | ||||
|         Vec3d rayDir = turtlePlayer.getLook( 1.0f ); | ||||
|         Pair<Entity, Vec3d> hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); | ||||
|         if( hit != null ) | ||||
|   | ||||
| @@ -20,9 +20,9 @@ public final class NBTUtil | ||||
|     private static INBT toNBTTag( Object object ) | ||||
|     { | ||||
|         if( object == null ) return null; | ||||
|         if( object instanceof Boolean ) return new ByteNBT( (byte) ((boolean) (Boolean) object ? 1 : 0) ); | ||||
|         if( object instanceof Number ) return new DoubleNBT( ((Number) object).doubleValue() ); | ||||
|         if( object instanceof String ) return new StringNBT( object.toString() ); | ||||
|         if( object instanceof Boolean ) return ByteNBT.valueOf( (byte) ((boolean) (Boolean) object ? 1 : 0) ); | ||||
|         if( object instanceof Number ) return DoubleNBT.valueOf( ((Number) object).doubleValue() ); | ||||
|         if( object instanceof String ) return StringNBT.valueOf( object.toString() ); | ||||
|         if( object instanceof Map ) | ||||
|         { | ||||
|             Map<?, ?> m = (Map<?, ?>) object; | ||||
|   | ||||
| @@ -172,17 +172,17 @@ public final class WorldUtil | ||||
|         double xPos = pos.getX() + 0.5 + xDir * 0.4; | ||||
|         double yPos = pos.getY() + 0.5 + yDir * 0.4; | ||||
|         double zPos = pos.getZ() + 0.5 + zDir * 0.4; | ||||
|         dropItemStack( stack, world, xPos, yPos, zPos, xDir, yDir, zDir ); | ||||
|         dropItemStack( stack, world, new Vec3d( xPos, yPos, zPos ), xDir, yDir, zDir ); | ||||
|     } | ||||
|  | ||||
|     public static void dropItemStack( @Nonnull ItemStack stack, World world, double xPos, double yPos, double zPos ) | ||||
|     public static void dropItemStack( @Nonnull ItemStack stack, World world, Vec3d pos ) | ||||
|     { | ||||
|         dropItemStack( stack, world, xPos, yPos, zPos, 0.0, 0.0, 0.0 ); | ||||
|         dropItemStack( stack, world, pos, 0.0, 0.0, 0.0 ); | ||||
|     } | ||||
|  | ||||
|     public static void dropItemStack( @Nonnull ItemStack stack, World world, double xPos, double yPos, double zPos, double xDir, double yDir, double zDir ) | ||||
|     public static void dropItemStack( @Nonnull ItemStack stack, World world, Vec3d pos, double xDir, double yDir, double zDir ) | ||||
|     { | ||||
|         ItemEntity item = new ItemEntity( world, xPos, yPos, zPos, stack.copy() ); | ||||
|         ItemEntity item = new ItemEntity( world, pos.x, pos.y, pos.z, stack.copy() ); | ||||
|         item.setMotion( | ||||
|             xDir * 0.7 + world.getRandom().nextFloat() * 0.2 - 0.1, | ||||
|             yDir * 0.7 + world.getRandom().nextFloat() * 0.2 - 0.1, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # ItemPocketRenderer/ItemPrintoutRenderer | ||||
| public net.minecraft.client.renderer.FirstPersonRenderer func_187466_c()V # renderArms | ||||
| public net.minecraft.client.renderer.FirstPersonRenderer func_178100_c(F)F # getMapAngleFromPitch | ||||
| public net.minecraft.client.renderer.FirstPersonRenderer func_187456_a(FFLnet/minecraft/util/HandSide;)V # renderArmFirstPerson | ||||
| public net.minecraft.client.renderer.FirstPersonRenderer func_228401_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;IFFLnet/minecraft/util/HandSide;)V # renderArmFirstPerson | ||||
| public net.minecraft.client.renderer.FirstPersonRenderer func_228403_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;ILnet/minecraft/util/HandSide;)V # renderArm | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| modLoader="javafml" | ||||
| loaderVersion="[28,29)" | ||||
| loaderVersion="[31,32)" | ||||
|  | ||||
| issueTrackerURL="https://github.com/SquidDev-CC/CC-Tweaked/issues" | ||||
| displayURL="https://github.com/SquidDev-CC/CC-Tweaked" | ||||
| @@ -19,6 +19,6 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a | ||||
| [[dependencies.computercraft]] | ||||
|     modId="forge" | ||||
|     mandatory=true | ||||
|     versionRange="[28.1.71,29)" | ||||
|     versionRange="[31.0.1,32)" | ||||
|     ordering="NONE" | ||||
|     side="BOTH" | ||||
|   | ||||
| @@ -1,6 +1,4 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_base", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_advanced" | ||||
|     } | ||||
|     "loader": "computercraft:turtle", | ||||
|     "model": "computercraft:block/turtle_advanced_base" | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,6 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_base", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_advanced" | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_normal_overlay", | ||||
|     "parent": "computercraft:block/turtle_overlay", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_elf_overlay" | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,4 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_base", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_normal" | ||||
|     } | ||||
|     "loader": "computercraft:turtle", | ||||
|     "model": "computercraft:block/turtle_normal_base" | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,6 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_base", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_normal" | ||||
|     } | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 123 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 3.8 KiB | 
| @@ -1,6 +1,8 @@ | ||||
| # New features in CC: Tweaked 1.86.2 | ||||
|  | ||||
| * Fix peripheral.getMethods returning an empty table | ||||
| * Update to Minecraft 1.15.2. This is currently alpha-quality and so is missing | ||||
|   missing features and may be unstable. | ||||
|  | ||||
| # New features in CC: Tweaked 1.86.1 | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| New features in CC: Tweaked 1.86.2 | ||||
|  | ||||
| * Fix peripheral.getMethods returning an empty table | ||||
| * Update to Minecraft 1.15.2. This is currently alpha-quality and so is missing | ||||
|   missing features and may be unstable. | ||||
|  | ||||
| Type "help changelog" to see the full version history. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 SquidDev
					SquidDev