1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-30 05:12:58 +00:00

Merge branch 'mc-1.14.x' into mc-1.15.x

This commit is contained in:
SquidDev
2020-05-13 14:36:39 +01:00
67 changed files with 1250 additions and 165 deletions

View File

@@ -70,7 +70,8 @@ public final class ComputerCraft
public static boolean disable_lua51_features = false;
public static String default_computer_settings = "";
public static boolean debug_enable = true;
public static boolean logPeripheralErrors = false;
public static boolean logPeripheralErrors = true;
public static boolean commandRequireCreative = true;
public static int computer_threads = 1;
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 );

View File

@@ -41,12 +41,12 @@ public final class FixedWidthFontRenderer
{
}
private static float toGreyscale( double[] rgb )
public static float toGreyscale( double[] rgb )
{
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
}
private static int getColour( char c, Colour def )
public static int getColour( char c, Colour def )
{
return 15 - Terminal.getColour( c, def );
}

View File

@@ -0,0 +1,174 @@
/*
* 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.google.common.base.Strings;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.texture.TextureUtil;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import java.io.InputStream;
import java.nio.FloatBuffer;
class MonitorTextureBufferShader
{
static final int TEXTURE_INDEX = GL13.GL_TEXTURE3;
private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 );
private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 );
private static int uniformMv;
private static int uniformP;
private static int uniformFont;
private static int uniformWidth;
private static int uniformHeight;
private static int uniformTbo;
private static int uniformPalette;
private static boolean initialised;
private static boolean ok;
private static int program;
static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale )
{
MATRIX_BUFFER.rewind();
transform.write( MATRIX_BUFFER );
MATRIX_BUFFER.rewind();
RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER );
// TODO: Cache this?
MATRIX_BUFFER.rewind();
GL11.glGetFloatv( GL11.GL_PROJECTION_MATRIX, MATRIX_BUFFER );
MATRIX_BUFFER.rewind();
RenderSystem.glUniformMatrix4( uniformP, false, MATRIX_BUFFER );
RenderSystem.glUniform1i( uniformWidth, width );
RenderSystem.glUniform1i( uniformHeight, height );
// TODO: Cache this? Maybe??
PALETTE_BUFFER.rewind();
for( int i = 0; i < 16; i++ )
{
double[] colour = palette.getColour( i );
if( greyscale )
{
float f = FixedWidthFontRenderer.toGreyscale( colour );
PALETTE_BUFFER.put( f ).put( f ).put( f );
}
else
{
PALETTE_BUFFER.put( (float) colour[0] ).put( (float) colour[1] ).put( (float) colour[2] );
}
}
PALETTE_BUFFER.flip();
RenderSystem.glUniform3( uniformPalette, PALETTE_BUFFER );
}
static boolean use()
{
if( initialised )
{
if( ok ) GlStateManager.useProgram( program );
return ok;
}
if( ok = load() )
{
GL20.glUseProgram( program );
RenderSystem.glUniform1i( uniformFont, 0 );
RenderSystem.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 );
}
return ok;
}
private static boolean load()
{
initialised = true;
try
{
int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" );
int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" );
program = GlStateManager.createProgram();
GlStateManager.attachShader( program, vertexShader );
GlStateManager.attachShader( program, fragmentShader );
GL20.glBindAttribLocation( program, 0, "v_pos" );
GlStateManager.linkProgram( program );
boolean ok = GlStateManager.getProgram( program, GL20.GL_LINK_STATUS ) != 0;
String log = GlStateManager.getProgramInfoLog( program, Short.MAX_VALUE ).trim();
if( !Strings.isNullOrEmpty( log ) )
{
ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log );
}
GL20.glDetachShader( program, vertexShader );
GL20.glDetachShader( program, fragmentShader );
GlStateManager.deleteShader( vertexShader );
GlStateManager.deleteShader( fragmentShader );
if( !ok ) return false;
uniformMv = getUniformLocation( program, "u_mv" );
uniformP = getUniformLocation( program, "u_p" );
uniformFont = getUniformLocation( program, "u_font" );
uniformWidth = getUniformLocation( program, "u_width" );
uniformHeight = getUniformLocation( program, "u_height" );
uniformTbo = getUniformLocation( program, "u_tbo" );
uniformPalette = getUniformLocation( program, "u_palette" );
ComputerCraft.log.info( "Loaded monitor shader." );
return true;
}
catch( Exception e )
{
ComputerCraft.log.error( "Cannot load monitor shaders", e );
return false;
}
}
private static int loadShader( int kind, String path )
{
InputStream stream = TileEntityMonitorRenderer.class.getClassLoader().getResourceAsStream( path );
if( stream == null ) throw new IllegalArgumentException( "Cannot find " + path );
String contents = TextureUtil.readResourceAsString( stream );
int shader = GlStateManager.createShader( kind );
GlStateManager.shaderSource( shader, contents );
GlStateManager.compileShader( shader );
boolean ok = GlStateManager.getShader( shader, GL20.GL_COMPILE_STATUS ) != 0;
String log = GlStateManager.getShaderInfoLog( shader, Short.MAX_VALUE ).trim();
if( !Strings.isNullOrEmpty( log ) )
{
ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log );
}
if( !ok ) throw new IllegalStateException( "Cannot compile shader " + path );
return shader;
}
private static int getUniformLocation( int program, String name )
{
int uniform = GlStateManager.getUniformLocation( program, name );
if( uniform == -1 ) throw new IllegalStateException( "Cannot find uniform " + name );
return uniform;
}
}

View File

@@ -6,22 +6,33 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
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.MonitorRenderer;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexBuffer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL31;
import javax.annotation.Nonnull;
import java.nio.ByteBuffer;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
{
@@ -90,50 +101,23 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
Terminal terminal = originTerminal.getTerminal();
if( terminal != null )
{
boolean redraw = originTerminal.pollTerminalChanged();
if( originTerminal.buffer == null )
{
originTerminal.createBuffer( MonitorRenderer.VBO );
redraw = true;
}
VertexBuffer vbo = originTerminal.buffer;
// Draw a terminal
double xScale = xSize / (terminal.getWidth() * FixedWidthFontRenderer.FONT_WIDTH);
double yScale = ySize / (terminal.getHeight() * FixedWidthFontRenderer.FONT_HEIGHT);
int width = terminal.getWidth(), height = terminal.getHeight();
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
double xScale = xSize / pixelWidth;
double yScale = ySize / pixelHeight;
transform.push();
transform.scale( (float) xScale, (float) -yScale, 1.0f );
float xMargin = (float) (MARGIN / xScale);
float yMargin = (float) (MARGIN / yScale);
Matrix4f matrix = transform.getLast().getMatrix();
if( redraw )
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder builder = tessellator.getBuffer();
builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() );
FixedWidthFontRenderer.drawTerminalWithoutCursor(
IDENTITY, builder, 0, 0,
terminal, !originTerminal.isColour(), yMargin, yMargin, xMargin, xMargin
);
builder.finishDrawing();
vbo.upload( builder );
}
// Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate
// render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick
// for now.
IVertexBuilder buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
FixedWidthFontRenderer.TYPE.setupRenderState();
vbo.bindBuffer();
FixedWidthFontRenderer.TYPE.getVertexFormat().setupBufferState( 0L );
vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() );
VertexBuffer.unbindBuffer();
FixedWidthFontRenderer.TYPE.getVertexFormat().clearBufferState();
renderTerminal( matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) );
// 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.
@@ -158,4 +142,88 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
transform.pop();
}
private static void renderTerminal( Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
{
Terminal terminal = monitor.getTerminal();
MonitorRenderer renderType = MonitorRenderer.current();
boolean redraw = monitor.pollTerminalChanged();
if( monitor.createBuffer( renderType ) ) redraw = true;
switch( renderType )
{
case VBO:
{
VertexBuffer vbo = monitor.buffer;
if( redraw )
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder builder = tessellator.getBuffer();
builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() );
FixedWidthFontRenderer.drawTerminalWithoutCursor(
IDENTITY, builder, 0, 0,
terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin
);
builder.finishDrawing();
vbo.upload( builder );
}
vbo.bindBuffer();
FixedWidthFontRenderer.TYPE.getVertexFormat().setupBufferState( 0L );
vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() );
VertexBuffer.unbindBuffer();
FixedWidthFontRenderer.TYPE.getVertexFormat().clearBufferState();
break;
}
case TBO:
{
if( !MonitorTextureBufferShader.use() ) return;
int width = terminal.getWidth(), height = terminal.getHeight();
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
if( redraw )
{
ByteBuffer buffer = GLAllocation.createDirectByteBuffer( width * height * 3 );
for( int y = 0; y < height; y++ )
{
TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y );
for( int x = 0; x < width; x++ )
{
buffer.put( (byte) (text.charAt( x ) & 0xFF) );
buffer.put( (byte) getColour( textColour.charAt( x ), Colour.WHITE ) );
buffer.put( (byte) getColour( background.charAt( x ), Colour.BLACK ) );
}
}
buffer.flip();
GlStateManager.bindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer );
GlStateManager.bufferData( GL31.GL_TEXTURE_BUFFER, buffer, GL20.GL_STATIC_DRAW );
GlStateManager.bindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );
}
// Nobody knows what they're doing!
GlStateManager.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX );
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture );
GlStateManager.activeTexture( GL13.GL_TEXTURE0 );
MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION );
buffer.pos( -xMargin, -yMargin, 0 ).endVertex();
buffer.pos( -xMargin, pixelHeight + yMargin, 0 ).endVertex();
buffer.pos( pixelWidth + xMargin, -yMargin, 0 ).endVertex();
buffer.pos( pixelWidth + xMargin, pixelHeight + yMargin, 0 ).endVertex();
tessellator.draw();
GlStateManager.useProgram( 0 );
break;
}
}
}
}

View File

@@ -14,6 +14,7 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.core.apis.http.AddressRule;
import dan200.computercraft.core.apis.http.websocket.Websocket;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
@@ -75,7 +76,10 @@ public final class Config
private static final ConfigValue<Boolean> turtlesCanPush;
private static final ConfigValue<List<? extends String>> turtleDisabledActions;
private static final ForgeConfigSpec spec;
private static final ConfigValue<MonitorRenderer> monitorRenderer;
private static final ForgeConfigSpec commonSpec;
private static final ForgeConfigSpec clientSpec;
private Config() {}
@@ -261,12 +265,20 @@ public final class Config
builder.pop();
}
spec = builder.build();
commonSpec = builder.build();
Builder clientBuilder = new Builder();
monitorRenderer = clientBuilder
.comment( "The renderer to use for monitors. Generally this should be kept at \"best\" - if " +
"monitors have performance issues, you may wish to experiment with alternative renderers." )
.defineEnum( "monitor_renderer", MonitorRenderer.BEST );
clientSpec = clientBuilder.build();
}
public static void load()
{
ModLoadingContext.get().registerConfig( ModConfig.Type.COMMON, spec );
ModLoadingContext.get().registerConfig( ModConfig.Type.COMMON, commonSpec );
ModLoadingContext.get().registerConfig( ModConfig.Type.CLIENT, clientSpec );
}
public static void sync()
@@ -316,6 +328,9 @@ public final class Config
ComputerCraft.turtleDisabledActions.clear();
for( String value : turtleDisabledActions.get() ) ComputerCraft.turtleDisabledActions.add( getAction( value ) );
// Client
ComputerCraft.monitorRenderer = monitorRenderer.get();
}
@SubscribeEvent

View File

@@ -120,6 +120,11 @@ public class TileCommandComputer extends TileComputer
@Override
public boolean isUsable( PlayerEntity player, boolean ignoreRange )
{
return isUsable( player ) && super.isUsable( player, ignoreRange );
}
public static boolean isUsable( PlayerEntity player )
{
MinecraftServer server = player.getServer();
if( server == null || !server.isCommandBlockEnabled() )
@@ -127,14 +132,12 @@ public class TileCommandComputer extends TileComputer
player.sendStatusMessage( new TranslationTextComponent( "advMode.notEnabled" ), true );
return false;
}
else if( !player.canUseCommandBlock() )
else if( ComputerCraft.commandRequireCreative ? !player.canUseCommandBlock() : !server.getPlayerList().canSendCommands( player.getGameProfile() ) )
{
player.sendStatusMessage( new TranslationTextComponent( "advMode.notAllowed" ), true );
return false;
}
else
{
return super.isUsable( player, ignoreRange );
}
return true;
}
}

View File

@@ -35,4 +35,3 @@ public enum ComputerState implements IStringSerializable
return name;
}
}

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.shared.computer.inventory;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
@@ -14,8 +15,6 @@ import dan200.computercraft.shared.network.container.ViewComputerContainerData;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TranslationTextComponent;
import javax.annotation.Nonnull;
@@ -48,18 +47,9 @@ public class ContainerViewComputer extends ContainerComputerBase implements ICon
}
// If we're a command computer then ensure we're in creative
if( computer.getFamily() == ComputerFamily.COMMAND )
if( computer.getFamily() == ComputerFamily.COMMAND && !TileCommandComputer.isUsable( player ) )
{
MinecraftServer server = player.getServer();
if( server == null || !server.isCommandBlockEnabled() )
{
return false;
}
else if( !player.canUseCommandBlock() )
{
player.sendStatusMessage( new TranslationTextComponent( "advMode.notAllowed" ), false );
return false;
}
return false;
}
return true;

View File

@@ -5,12 +5,18 @@
*/
package dan200.computercraft.shared.peripheral.monitor;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
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;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL31;
import java.util.HashSet;
import java.util.Iterator;
@@ -25,6 +31,8 @@ public final class ClientMonitor extends ClientTerminal
public long lastRenderFrame = -1;
public BlockPos lastRenderPos = null;
public int tboBuffer;
public int tboTexture;
public VertexBuffer buffer;
public ClientMonitor( boolean colour, TileMonitor origin )
@@ -50,6 +58,26 @@ public final class ClientMonitor extends ClientTerminal
{
switch( renderer )
{
case TBO:
{
if( tboBuffer != 0 ) return false;
deleteBuffers();
tboBuffer = GlStateManager.genBuffers();
GlStateManager.bindBuffer( GL31.GL_TEXTURE_BUFFER, tboBuffer );
GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW );
tboTexture = GlStateManager.genTexture();
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture );
GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8, tboBuffer );
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 );
GlStateManager.bindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );
addMonitor();
return true;
}
case VBO:
if( buffer != null ) return false;
@@ -73,6 +101,19 @@ public final class ClientMonitor extends ClientTerminal
private void deleteBuffers()
{
if( tboBuffer != 0 )
{
RenderSystem.glDeleteBuffers( tboBuffer );
tboBuffer = 0;
}
if( tboTexture != 0 )
{
GlStateManager.deleteTexture( tboTexture );
tboTexture = 0;
}
if( buffer != null )
{
buffer.close();
@@ -83,7 +124,7 @@ public final class ClientMonitor extends ClientTerminal
@OnlyIn( Dist.CLIENT )
public void destroy()
{
if( buffer != null )
if( tboBuffer != 0 || buffer != null )
{
synchronized( allMonitors )
{

View File

@@ -8,9 +8,9 @@ package dan200.computercraft.shared.peripheral.monitor;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import org.lwjgl.opengl.GL;
import javax.annotation.Nonnull;
import java.util.Locale;
/**
* The render type to use for monitors.
@@ -25,6 +25,13 @@ public enum MonitorRenderer
*/
BEST,
/**
* Render using texture buffer objects.
*
* @see org.lwjgl.opengl.GL31#glTexBuffer(int, int, int)
*/
TBO,
/**
* Render using VBOs.
*
@@ -32,37 +39,6 @@ public enum MonitorRenderer
*/
VBO;
private static final MonitorRenderer[] VALUES = values();
public static final String[] NAMES;
private final String displayName = "gui.computercraft:config.peripheral.monitor_renderer." + name().toLowerCase( Locale.ROOT );
static
{
NAMES = new String[VALUES.length];
for( int i = 0; i < VALUES.length; i++ ) NAMES[i] = VALUES[i].displayName();
}
public String displayName()
{
return displayName;
}
@Nonnull
public static MonitorRenderer ofString( String name )
{
for( MonitorRenderer backend : VALUES )
{
if( backend.displayName.equalsIgnoreCase( name ) || backend.name().equalsIgnoreCase( name ) )
{
return backend;
}
}
ComputerCraft.log.warn( "Unknown monitor renderer {}. Falling back to default.", name );
return BEST;
}
/**
* Get the current renderer to use.
*
@@ -72,11 +48,39 @@ public enum MonitorRenderer
public static MonitorRenderer current()
{
MonitorRenderer current = ComputerCraft.monitorRenderer;
return current == MonitorRenderer.BEST ? best() : current;
switch( current )
{
case BEST:
return best();
case TBO:
checkCapabilities();
if( !textureBuffer )
{
ComputerCraft.log.warn( "Texture buffers are not supported on your graphics card. Falling back to default." );
ComputerCraft.monitorRenderer = BEST;
return best();
}
return TBO;
default:
return current;
}
}
private static MonitorRenderer best()
{
return VBO;
checkCapabilities();
return textureBuffer ? TBO : VBO;
}
private static boolean initialised = false;
private static boolean textureBuffer = false;
private static void checkCapabilities()
{
if( initialised ) return;
textureBuffer = GL.getCapabilities().OpenGL31;
initialised = true;
}
}

View File

@@ -154,4 +154,3 @@ public abstract class SpeakerPeripheral implements IPeripheral
return true;
}
}

View File

@@ -78,4 +78,3 @@ public class TileSpeaker extends TileGeneric implements ITickableTileEntity, IPe
}
}
}