mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-12 11:10:29 +00:00
Overhaul monitor's terminal code
This restructures monitor in order to make it thread-safe: namely removing any world interaction from the computer thread. Instead of each monitor having their own terminal, resize flag, etc... we use a monitor "multiblock" object. This is constructed on the origin monitor and propagated to other monitors when required. We attempt to construct the multiblock object (and so the corresponding terminal) as lazily as posible. Consequently, we only create the terminal when fetching the peripheral (not when attaching, as that is done on the computer thread). If a monitor is resized (say due to placing/breaking a monitor) then we will invalidate all references to the multiblock object, construct a new one if required, and propagate it to all component monitors. This commit also fixes several instances of glLists not being deleted after use. It is not a comprehensive fix, but that is outside the scope of this commit.
This commit is contained in:
parent
4c14431a3d
commit
662fb96beb
@ -10,7 +10,7 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.common.ClientTerminal;
|
||||
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;
|
||||
@ -43,24 +43,22 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
private void renderMonitorAt( TileMonitor monitor, double posX, double posY, double posZ, float f, int i )
|
||||
{
|
||||
// Render from the origin monitor
|
||||
TileMonitor origin = monitor.getOrigin();
|
||||
if( origin == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
ClientMonitor originTerminal = monitor.getClientMonitor();
|
||||
|
||||
if( originTerminal == null ) return;
|
||||
TileMonitor origin = originTerminal.getOrigin();
|
||||
|
||||
// Ensure each monitor is rendered only once
|
||||
long renderFrame = ComputerCraft.getRenderFrame();
|
||||
if( origin.m_lastRenderFrame == renderFrame )
|
||||
if( originTerminal.lastRenderFrame == renderFrame )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
origin.m_lastRenderFrame = renderFrame;
|
||||
originTerminal.lastRenderFrame = renderFrame;
|
||||
}
|
||||
|
||||
boolean redraw = origin.pollChanged();
|
||||
BlockPos monitorPos = monitor.getPos();
|
||||
BlockPos originPos = origin.getPos();
|
||||
posX += originPos.getX() - monitorPos.getX();
|
||||
@ -94,9 +92,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
BufferBuilder renderer = tessellator.getBuffer();
|
||||
|
||||
// Get terminal
|
||||
ClientTerminal clientTerminal = (ClientTerminal)origin.getTerminal();
|
||||
Terminal terminal = (clientTerminal != null) ? clientTerminal.getTerminal() : null;
|
||||
redraw = redraw || (clientTerminal != null && clientTerminal.hasTerminalChanged());
|
||||
boolean redraw = originTerminal.hasTerminalChanged();
|
||||
|
||||
// Draw the contents
|
||||
GlStateManager.depthMask( false );
|
||||
@ -104,24 +100,25 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
mc.entityRenderer.disableLightmap();
|
||||
try
|
||||
{
|
||||
Terminal terminal = originTerminal.getTerminal();
|
||||
if( terminal != null )
|
||||
{
|
||||
Palette palette = terminal.getPalette();
|
||||
|
||||
// Allocate display lists
|
||||
if( origin.m_renderDisplayList < 0 )
|
||||
if( originTerminal.renderDisplayList < 0 )
|
||||
{
|
||||
origin.m_renderDisplayList = GlStateManager.glGenLists( 3 );
|
||||
originTerminal.renderDisplayList = GlStateManager.glGenLists( 3 );
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
// Draw a terminal
|
||||
boolean greyscale = !clientTerminal.isColour();
|
||||
boolean greyscale = !originTerminal.isColour();
|
||||
int width = terminal.getWidth();
|
||||
int height = terminal.getHeight();
|
||||
int cursorX = terminal.getCursorX();
|
||||
int cursorY = terminal.getCursorY();
|
||||
FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer)ComputerCraft.getFixedWidthFontRenderer();
|
||||
FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
try
|
||||
@ -135,7 +132,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
if( redraw )
|
||||
{
|
||||
// Build background display list
|
||||
GlStateManager.glNewList( origin.m_renderDisplayList, GL11.GL_COMPILE );
|
||||
GlStateManager.glNewList( originTerminal.renderDisplayList, GL11.GL_COMPILE );
|
||||
try
|
||||
{
|
||||
double marginXSize = TileMonitor.RENDER_MARGIN / xScale;
|
||||
@ -149,7 +146,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
GlStateManager.scale( 1.0, marginSquash, 1.0 );
|
||||
GlStateManager.translate( 0.0, -marginYSize / marginSquash, 0.0 );
|
||||
fontRenderer.drawStringBackgroundPart( 0, 0, terminal.getBackgroundColourLine( 0 ), marginXSize, marginXSize, greyscale, palette );
|
||||
GlStateManager.translate( 0.0, ( marginYSize + height * FixedWidthFontRenderer.FONT_HEIGHT ) / marginSquash, 0.0 );
|
||||
GlStateManager.translate( 0.0, (marginYSize + height * FixedWidthFontRenderer.FONT_HEIGHT) / marginSquash, 0.0 );
|
||||
fontRenderer.drawStringBackgroundPart( 0, 0, terminal.getBackgroundColourLine( height - 1 ), marginXSize, marginXSize, greyscale, palette );
|
||||
}
|
||||
finally
|
||||
@ -174,7 +171,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
GlStateManager.glEndList();
|
||||
}
|
||||
}
|
||||
GlStateManager.callList( origin.m_renderDisplayList );
|
||||
GlStateManager.callList( originTerminal.renderDisplayList );
|
||||
GlStateManager.resetColor();
|
||||
|
||||
// Draw text
|
||||
@ -182,7 +179,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
if( redraw )
|
||||
{
|
||||
// Build text display list
|
||||
GlStateManager.glNewList( origin.m_renderDisplayList + 1, GL11.GL_COMPILE );
|
||||
GlStateManager.glNewList( originTerminal.renderDisplayList + 1, GL11.GL_COMPILE );
|
||||
try
|
||||
{
|
||||
// Lines
|
||||
@ -202,7 +199,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
GlStateManager.glEndList();
|
||||
}
|
||||
}
|
||||
GlStateManager.callList( origin.m_renderDisplayList + 1 );
|
||||
GlStateManager.callList( originTerminal.renderDisplayList + 1 );
|
||||
GlStateManager.resetColor();
|
||||
|
||||
// Draw cursor
|
||||
@ -210,7 +207,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
if( redraw )
|
||||
{
|
||||
// Build cursor display list
|
||||
GlStateManager.glNewList( origin.m_renderDisplayList + 2, GL11.GL_COMPILE );
|
||||
GlStateManager.glNewList( originTerminal.renderDisplayList + 2, GL11.GL_COMPILE );
|
||||
try
|
||||
{
|
||||
// Cursor
|
||||
@ -236,7 +233,7 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon
|
||||
}
|
||||
if( ComputerCraft.getGlobalCursorBlink() )
|
||||
{
|
||||
GlStateManager.callList( origin.m_renderDisplayList + 2 );
|
||||
GlStateManager.callList( originTerminal.renderDisplayList + 2 );
|
||||
GlStateManager.resetColor();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.common.ClientTerminal;
|
||||
import gnu.trove.set.hash.TIntHashSet;
|
||||
|
||||
public class ClientMonitor extends ClientTerminal
|
||||
{
|
||||
private static final TIntHashSet displayLists = new TIntHashSet();
|
||||
|
||||
private final TileMonitor origin;
|
||||
|
||||
public long lastRenderFrame = -1;
|
||||
public int renderDisplayList = -1;
|
||||
|
||||
public ClientMonitor( boolean colour, TileMonitor origin )
|
||||
{
|
||||
super( colour );
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public TileMonitor getOrigin()
|
||||
{
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void destroy()
|
||||
{
|
||||
if( renderDisplayList != -1 )
|
||||
{
|
||||
ComputerCraft.deleteDisplayLists( renderDisplayList, 3 );
|
||||
}
|
||||
}
|
||||
}
|
@ -73,6 +73,12 @@ public class MonitorPeripheral implements IPeripheral
|
||||
@Override
|
||||
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object args[] ) throws LuaException
|
||||
{
|
||||
ServerMonitor monitor = m_monitor.getCachedServerMonitor();
|
||||
if( monitor == null ) throw new LuaException( "Monitor has been detatched" );
|
||||
|
||||
Terminal terminal = monitor.getTerminal();
|
||||
if( terminal == null ) throw new LuaException( "Monitor has been detatched" );
|
||||
|
||||
switch( method )
|
||||
{
|
||||
case 0:
|
||||
@ -84,7 +90,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
} else {
|
||||
text = "";
|
||||
}
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.write( text );
|
||||
terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() );
|
||||
return null;
|
||||
@ -93,7 +98,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
// scroll
|
||||
int value = getInt( args, 0 );
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.scroll( value );
|
||||
return null;
|
||||
}
|
||||
@ -102,7 +106,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
// setCursorPos
|
||||
int x = getInt( args, 0 ) - 1;
|
||||
int y = getInt( args, 1 ) - 1;
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.setCursorPos( x, y );
|
||||
return null;
|
||||
}
|
||||
@ -110,14 +113,12 @@ public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
// setCursorBlink
|
||||
boolean blink = getBoolean( args, 0 );
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.setCursorBlink( blink );
|
||||
return null;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
// getCursorPos
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
return new Object[] {
|
||||
terminal.getCursorX() + 1,
|
||||
terminal.getCursorY() + 1
|
||||
@ -126,7 +127,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
case 5:
|
||||
{
|
||||
// getSize
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
return new Object[] {
|
||||
terminal.getWidth(),
|
||||
terminal.getHeight()
|
||||
@ -135,14 +135,12 @@ public class MonitorPeripheral implements IPeripheral
|
||||
case 6:
|
||||
{
|
||||
// clear
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.clear();
|
||||
return null;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
// clearLine
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.clearLine();
|
||||
return null;
|
||||
}
|
||||
@ -154,7 +152,7 @@ public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
throw new LuaException( "Expected number in range 0.5-5" );
|
||||
}
|
||||
m_monitor.setTextScale( scale );
|
||||
monitor.setTextScale( scale );
|
||||
return null;
|
||||
}
|
||||
case 9:
|
||||
@ -162,7 +160,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
// setTextColour/setTextColor
|
||||
int colour = TermAPI.parseColour( args );
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.setTextColour( colour );
|
||||
return null;
|
||||
}
|
||||
@ -171,7 +168,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
// setBackgroundColour/setBackgroundColor
|
||||
int colour = TermAPI.parseColour( args );
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.setBackgroundColour( colour );
|
||||
return null;
|
||||
}
|
||||
@ -180,21 +176,19 @@ public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
// isColour/isColor
|
||||
return new Object[] {
|
||||
m_monitor.getTerminal().isColour()
|
||||
monitor.isColour()
|
||||
};
|
||||
}
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
// getTextColour/getTextColor
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
return TermAPI.encodeColour( terminal.getTextColour() );
|
||||
}
|
||||
case 17:
|
||||
case 18:
|
||||
{
|
||||
// getBackgroundColour/getBackgroundColor
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
return TermAPI.encodeColour( terminal.getBackgroundColour() );
|
||||
}
|
||||
case 19:
|
||||
@ -208,7 +202,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
throw new LuaException( "Arguments must be the same length" );
|
||||
}
|
||||
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
terminal.blit( text, textColour, backgroundColour );
|
||||
terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() );
|
||||
return null;
|
||||
@ -217,8 +210,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
case 21:
|
||||
{
|
||||
// setPaletteColour/setPaletteColor
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
|
||||
int colour = 15 - TermAPI.parseColour( args );
|
||||
if( args.length == 2 )
|
||||
{
|
||||
@ -239,7 +230,6 @@ public class MonitorPeripheral implements IPeripheral
|
||||
case 23:
|
||||
{
|
||||
// getPaletteColour/getPaletteColor
|
||||
Terminal terminal = m_monitor.getTerminal().getTerminal();
|
||||
Palette palette = terminal.getPalette();
|
||||
|
||||
int colour = 15 - TermAPI.parseColour( args );
|
||||
@ -253,7 +243,7 @@ public class MonitorPeripheral implements IPeripheral
|
||||
case 24:
|
||||
{
|
||||
// getTextScale
|
||||
return new Object[] { m_monitor.getTextScale() };
|
||||
return new Object[] { monitor.getTextScale() };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -0,0 +1,64 @@
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.common.ServerTerminal;
|
||||
|
||||
public class ServerMonitor extends ServerTerminal
|
||||
{
|
||||
private final TileMonitor origin;
|
||||
private int textScale = 2;
|
||||
private boolean resized;
|
||||
|
||||
public ServerMonitor( boolean colour, TileMonitor origin )
|
||||
{
|
||||
super( colour );
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public synchronized void rebuild()
|
||||
{
|
||||
Terminal oldTerm = getTerminal();
|
||||
int oldWidth = oldTerm == null ? -1 : oldTerm.getWidth();
|
||||
int oldHeight = oldTerm == null ? -1 : oldTerm.getHeight();
|
||||
|
||||
double textScale = this.textScale * 0.5;
|
||||
int termWidth = (int) Math.max(
|
||||
Math.round( (origin.getWidth() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 6.0 * TileMonitor.RENDER_PIXEL_SCALE) ),
|
||||
1.0
|
||||
);
|
||||
int termHeight = (int) Math.max(
|
||||
Math.round( (origin.getHeight() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 9.0 * TileMonitor.RENDER_PIXEL_SCALE) ),
|
||||
1.0
|
||||
);
|
||||
|
||||
resize( termWidth, termHeight );
|
||||
if( oldWidth != termWidth || oldHeight != termHeight )
|
||||
{
|
||||
getTerminal().clear();
|
||||
resized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextScale()
|
||||
{
|
||||
return textScale;
|
||||
}
|
||||
|
||||
public synchronized void setTextScale( int textScale )
|
||||
{
|
||||
if( this.textScale == textScale ) return;
|
||||
this.textScale = textScale;
|
||||
rebuild();
|
||||
}
|
||||
|
||||
public synchronized boolean pollResized()
|
||||
{
|
||||
if( resized )
|
||||
{
|
||||
resized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -10,19 +10,17 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.common.ClientTerminal;
|
||||
import dan200.computercraft.shared.common.ITerminal;
|
||||
import dan200.computercraft.shared.common.ITerminalTile;
|
||||
import dan200.computercraft.shared.common.ServerTerminal;
|
||||
import dan200.computercraft.shared.peripheral.PeripheralType;
|
||||
import dan200.computercraft.shared.peripheral.common.BlockPeripheral;
|
||||
import dan200.computercraft.shared.peripheral.common.TilePeripheralBase;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -30,7 +28,6 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TileMonitor extends TilePeripheralBase
|
||||
implements ITerminalTile
|
||||
{
|
||||
// Statics
|
||||
|
||||
@ -42,26 +39,22 @@ public class TileMonitor extends TilePeripheralBase
|
||||
private static final int MAX_HEIGHT = 6;
|
||||
|
||||
// Members
|
||||
|
||||
private ServerTerminal m_serverTerminal;
|
||||
private ClientTerminal m_clientTerminal;
|
||||
private ServerMonitor m_serverMonitor;
|
||||
private ClientMonitor m_clientMonitor;
|
||||
private boolean hasPeripheral;
|
||||
private final Set<IComputerAccess> m_computers;
|
||||
|
||||
public long m_lastRenderFrame = -1; // For rendering use only
|
||||
public int m_renderDisplayList = -1; // For rendering use only
|
||||
|
||||
private boolean m_destroyed;
|
||||
private boolean m_ignoreMe;
|
||||
private boolean m_changed;
|
||||
|
||||
private int m_textScale;
|
||||
private int m_width;
|
||||
private int m_height;
|
||||
private int m_xIndex;
|
||||
private int m_yIndex;
|
||||
|
||||
private int m_dir;
|
||||
private boolean m_sizeChangedQueued;
|
||||
|
||||
private boolean m_advanced;
|
||||
|
||||
public TileMonitor()
|
||||
{
|
||||
@ -69,17 +62,23 @@ public class TileMonitor extends TilePeripheralBase
|
||||
|
||||
m_destroyed = false;
|
||||
m_ignoreMe = false;
|
||||
m_textScale = 2;
|
||||
|
||||
m_width = 1;
|
||||
m_height = 1;
|
||||
m_xIndex = 0;
|
||||
m_yIndex = 0;
|
||||
m_changed = false;
|
||||
|
||||
m_dir = 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad()
|
||||
{
|
||||
super.onLoad();
|
||||
m_advanced = getBlockState().getValue( BlockPeripheral.Properties.VARIANT )
|
||||
.getPeripheralType() == PeripheralType.AdvancedMonitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
@ -91,11 +90,20 @@ public class TileMonitor extends TilePeripheralBase
|
||||
contractNeighbours();
|
||||
}
|
||||
}
|
||||
if( m_renderDisplayList >= 0 )
|
||||
{
|
||||
ComputerCraft.deleteDisplayLists( m_renderDisplayList, 3 );
|
||||
m_renderDisplayList = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate()
|
||||
{
|
||||
super.invalidate();
|
||||
if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload()
|
||||
{
|
||||
super.onChunkUnload();
|
||||
if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -143,41 +151,38 @@ public class TileMonitor extends TilePeripheralBase
|
||||
|
||||
if( !getWorld().isRemote )
|
||||
{
|
||||
if( m_sizeChangedQueued )
|
||||
if( m_xIndex == 0 && m_yIndex == 0 && m_serverMonitor != null )
|
||||
{
|
||||
for( IComputerAccess computer : m_computers )
|
||||
if( m_serverMonitor.pollResized() )
|
||||
{
|
||||
computer.queueEvent( "monitor_resize", new Object[] {
|
||||
computer.getAttachmentName()
|
||||
} );
|
||||
}
|
||||
m_sizeChangedQueued = false;
|
||||
}
|
||||
for( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
for( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor == null ) continue;
|
||||
|
||||
if( m_serverTerminal != null )
|
||||
{
|
||||
m_serverTerminal.update();
|
||||
if( m_serverTerminal.hasTerminalChanged() )
|
||||
{
|
||||
updateBlock();
|
||||
for( IComputerAccess computer : monitor.m_computers )
|
||||
{
|
||||
computer.queueEvent( "monitor_resize", new Object[] {
|
||||
computer.getAttachmentName()
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_clientTerminal != null )
|
||||
{
|
||||
m_clientTerminal.update();
|
||||
m_serverMonitor.update();
|
||||
if( m_serverMonitor.hasTerminalChanged() ) updateBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean pollChanged()
|
||||
{
|
||||
if( m_changed )
|
||||
else
|
||||
{
|
||||
m_changed = false;
|
||||
return true;
|
||||
if( m_xIndex == 0 && m_yIndex == 0 && m_clientMonitor != null )
|
||||
{
|
||||
m_clientMonitor.update();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// IPeripheralTile implementation
|
||||
@ -185,24 +190,71 @@ public class TileMonitor extends TilePeripheralBase
|
||||
@Override
|
||||
public IPeripheral getPeripheral( EnumFacing side )
|
||||
{
|
||||
hasPeripheral = true;
|
||||
createServerMonitor(); // Ensure the monitor is created before doing anything else.
|
||||
return new MonitorPeripheral( this );
|
||||
}
|
||||
|
||||
public void setTextScale( int scale )
|
||||
public ServerMonitor getCachedServerMonitor()
|
||||
{
|
||||
return m_serverMonitor;
|
||||
}
|
||||
|
||||
private ServerMonitor getServerMonitor()
|
||||
{
|
||||
if( m_serverMonitor != null ) return m_serverMonitor;
|
||||
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin != null )
|
||||
if( origin == null ) return null;
|
||||
|
||||
return m_serverMonitor = origin.m_serverMonitor;
|
||||
}
|
||||
|
||||
private ServerMonitor createServerMonitor()
|
||||
{
|
||||
if( m_serverMonitor != null )
|
||||
{
|
||||
synchronized( origin )
|
||||
return m_serverMonitor;
|
||||
}
|
||||
else if( m_xIndex == 0 && m_yIndex == 0 )
|
||||
{
|
||||
// If we're the origin, set up the new monitor
|
||||
m_serverMonitor = new ServerMonitor( m_advanced, this );
|
||||
m_serverMonitor.rebuild();
|
||||
|
||||
// And propagate it to child monitors
|
||||
for( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
if( origin.m_textScale != scale )
|
||||
for( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
origin.m_textScale = scale;
|
||||
origin.rebuildTerminal();
|
||||
origin.updateBlock();
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor != null ) monitor.m_serverMonitor = m_serverMonitor;
|
||||
}
|
||||
}
|
||||
|
||||
return m_serverMonitor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise fetch the origin and attempt to get its monitor
|
||||
// Note this may load chunks, but we don't really have a choice here.
|
||||
BlockPos pos = getPos();
|
||||
TileEntity te = world.getTileEntity( pos.offset( getRight(), -m_xIndex ).offset( getDown(), -m_yIndex ) );
|
||||
if( !(te instanceof TileMonitor) ) return null;
|
||||
|
||||
return m_serverMonitor = ((TileMonitor) te).createServerMonitor();
|
||||
}
|
||||
}
|
||||
|
||||
public ClientMonitor getClientMonitor()
|
||||
{
|
||||
if( m_clientMonitor != null ) return m_clientMonitor;
|
||||
|
||||
BlockPos pos = getPos();
|
||||
TileEntity te = world.getTileEntity( pos.offset( getRight(), -m_xIndex ).offset( getDown(), -m_yIndex ) );
|
||||
if( !(te instanceof TileMonitor) ) return null;
|
||||
|
||||
return m_clientMonitor = ((TileMonitor) te).m_clientMonitor;
|
||||
}
|
||||
|
||||
// Networking stuff
|
||||
@ -215,9 +267,12 @@ public class TileMonitor extends TilePeripheralBase
|
||||
nbttagcompound.setInteger( "yIndex", m_yIndex );
|
||||
nbttagcompound.setInteger( "width", m_width );
|
||||
nbttagcompound.setInteger( "height", m_height );
|
||||
nbttagcompound.setInteger( "textScale", m_textScale );
|
||||
nbttagcompound.setInteger( "monitorDir", m_dir );
|
||||
((ServerTerminal)getLocalTerminal()).writeDescription( nbttagcompound );
|
||||
|
||||
if( m_xIndex == 0 && m_yIndex == 0 && m_serverMonitor != null )
|
||||
{
|
||||
m_serverMonitor.writeDescription( nbttagcompound );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -229,110 +284,40 @@ public class TileMonitor extends TilePeripheralBase
|
||||
int oldYIndex = m_yIndex;
|
||||
int oldWidth = m_width;
|
||||
int oldHeight = m_height;
|
||||
int oldTextScale = m_textScale;
|
||||
int oldDir = m_dir;
|
||||
|
||||
m_xIndex = nbttagcompound.getInteger( "xIndex" );
|
||||
m_yIndex = nbttagcompound.getInteger( "yIndex" );
|
||||
m_width = nbttagcompound.getInteger( "width" );
|
||||
m_height = nbttagcompound.getInteger( "height" );
|
||||
m_textScale = nbttagcompound.getInteger( "textScale" );
|
||||
m_dir = nbttagcompound.getInteger( "monitorDir" );
|
||||
((ClientTerminal)getLocalTerminal()).readDescription( nbttagcompound );
|
||||
m_changed = true;
|
||||
|
||||
if( oldXIndex != m_xIndex || oldYIndex != m_yIndex )
|
||||
{
|
||||
// If our index has changed then it's possible the origin monitor has changed. Thus
|
||||
// we'll clear our cache. If we're the origin then we'll need to remove the glList as well.
|
||||
if( oldXIndex == 0 && oldYIndex == 0 && m_clientMonitor != null ) m_clientMonitor.destroy();
|
||||
m_clientMonitor = null;
|
||||
}
|
||||
|
||||
if( m_xIndex == 0 && m_yIndex == 0 )
|
||||
{
|
||||
// If we're the origin terminal then read the description
|
||||
if( m_clientMonitor == null ) m_clientMonitor = new ClientMonitor( m_advanced, this );
|
||||
m_clientMonitor.readDescription( nbttagcompound );
|
||||
}
|
||||
|
||||
if( oldXIndex != m_xIndex || oldYIndex != m_yIndex ||
|
||||
oldWidth != m_width || oldHeight != m_height ||
|
||||
oldTextScale != m_textScale || oldDir != m_dir )
|
||||
oldDir != m_dir )
|
||||
{
|
||||
// One of our properties has changed, so ensure we redraw the block
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
|
||||
// ITerminalTile implementation
|
||||
|
||||
@Override
|
||||
public ITerminal getTerminal()
|
||||
{
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin != null )
|
||||
{
|
||||
return origin.getLocalTerminal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ITerminal getLocalTerminal()
|
||||
{
|
||||
if( !getWorld().isRemote )
|
||||
{
|
||||
if( m_serverTerminal == null )
|
||||
{
|
||||
m_serverTerminal = new ServerTerminal(
|
||||
getPeripheralType() == PeripheralType.AdvancedMonitor
|
||||
);
|
||||
}
|
||||
return m_serverTerminal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_clientTerminal == null )
|
||||
{
|
||||
m_clientTerminal = new ClientTerminal(
|
||||
getPeripheralType() == PeripheralType.AdvancedMonitor
|
||||
);
|
||||
}
|
||||
return m_clientTerminal;
|
||||
}
|
||||
}
|
||||
|
||||
// Sizing and placement stuff
|
||||
|
||||
public double getTextScale()
|
||||
{
|
||||
TileMonitor origin = getOrigin();
|
||||
return (origin == null ? m_textScale : origin.m_textScale) * 0.5;
|
||||
}
|
||||
|
||||
private void rebuildTerminal()
|
||||
{
|
||||
Terminal oldTerm = getTerminal().getTerminal();
|
||||
int oldWidth = (oldTerm != null) ? oldTerm.getWidth() : -1;
|
||||
int oldHeight = (oldTerm != null) ? oldTerm.getHeight() : -1;
|
||||
|
||||
double textScale = getTextScale();
|
||||
int termWidth = (int)Math.max(
|
||||
Math.round( (m_width - 2.0 * ( TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN )) / (textScale * 6.0 * TileMonitor.RENDER_PIXEL_SCALE) ),
|
||||
1.0
|
||||
);
|
||||
int termHeight = (int)Math.max(
|
||||
Math.round( (m_height - 2.0 * ( TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN )) / (textScale * 9.0 * TileMonitor.RENDER_PIXEL_SCALE) ),
|
||||
1.0
|
||||
);
|
||||
((ServerTerminal)getLocalTerminal()).resize( termWidth, termHeight );
|
||||
|
||||
if( oldWidth != termWidth || oldHeight != termHeight )
|
||||
{
|
||||
getLocalTerminal().getTerminal().clear();
|
||||
for( int y=0; y<m_height; ++y )
|
||||
{
|
||||
for( int x=0; x<m_width; ++x )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor != null )
|
||||
{
|
||||
monitor.queueSizeChangedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyTerminal()
|
||||
{
|
||||
((ServerTerminal)getLocalTerminal()).delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumFacing getDirection()
|
||||
{
|
||||
@ -354,7 +339,6 @@ public class TileMonitor extends TilePeripheralBase
|
||||
public void setDir( int dir )
|
||||
{
|
||||
m_dir = dir;
|
||||
m_changed = true;
|
||||
markDirty();
|
||||
}
|
||||
|
||||
@ -431,10 +415,9 @@ public class TileMonitor extends TilePeripheralBase
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
if( tile != null && tile instanceof TileMonitor )
|
||||
{
|
||||
TileMonitor monitor = (TileMonitor)tile;
|
||||
if( monitor.getDir() == getDir() &&
|
||||
monitor.getLocalTerminal().isColour() == getLocalTerminal().isColour() &&
|
||||
!monitor.m_destroyed && !monitor.m_ignoreMe )
|
||||
TileMonitor monitor = (TileMonitor) tile;
|
||||
if( monitor.getDir() == getDir() && monitor.m_advanced == m_advanced &&
|
||||
!monitor.m_destroyed && !monitor.m_ignoreMe )
|
||||
{
|
||||
return monitor;
|
||||
}
|
||||
@ -464,34 +447,59 @@ public class TileMonitor extends TilePeripheralBase
|
||||
|
||||
private void resize( int width, int height )
|
||||
{
|
||||
// Update the positions and indexes of the other monitors
|
||||
BlockPos pos = getPos();
|
||||
EnumFacing right = getRight();
|
||||
EnumFacing down = getDown();
|
||||
for( int y=0; y<height; ++y )
|
||||
m_xIndex = 0;
|
||||
m_yIndex = 0;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
// Determine if we actually need a monitor. In order to do this, simply check if
|
||||
// any component monitor been wrapped as a peripheral. Whilst this flag may be
|
||||
// out of date,
|
||||
boolean needsTerminal = false;
|
||||
terminalCheck:
|
||||
for( int x = 0; x < width; x++ )
|
||||
{
|
||||
for( int x=0; x<width; ++x )
|
||||
for( int y = 0; y < height; y++ )
|
||||
{
|
||||
TileMonitor monitor = getSimilarMonitorAt(
|
||||
pos.offset( right, x ).offset( down, y )
|
||||
);
|
||||
if( monitor != null )
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor != null && monitor.hasPeripheral )
|
||||
{
|
||||
monitor.m_xIndex = x;
|
||||
monitor.m_yIndex = y;
|
||||
monitor.m_width = width;
|
||||
monitor.m_height = height;
|
||||
monitor.updateBlock();
|
||||
if( x != 0 || y != 0 )
|
||||
{
|
||||
monitor.destroyTerminal();
|
||||
}
|
||||
needsTerminal = true;
|
||||
break terminalCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild this terminal (will invoke resize events)
|
||||
rebuildTerminal();
|
||||
// Either delete the current monitor or sync a new one.
|
||||
if( needsTerminal )
|
||||
{
|
||||
if( m_serverMonitor == null ) m_serverMonitor = new ServerMonitor( m_advanced, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_serverMonitor = null;
|
||||
}
|
||||
|
||||
// Update the terminal's width and height and rebuild it. This ensures the monitor
|
||||
// is consistent when syncing it to other monitors.
|
||||
if( m_serverMonitor != null ) m_serverMonitor.rebuild();
|
||||
|
||||
// Update the other monitors, setting coordinates, dimensions and the server terminal
|
||||
for( int x = 0; x < width; x++ )
|
||||
{
|
||||
for( int y = 0; y < height; y++ )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor == null ) continue;
|
||||
|
||||
monitor.m_xIndex = x;
|
||||
monitor.m_yIndex = y;
|
||||
monitor.m_width = width;
|
||||
monitor.m_height = height;
|
||||
monitor.m_serverMonitor = m_serverMonitor;
|
||||
monitor.updateBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mergeLeft()
|
||||
@ -699,51 +707,36 @@ public class TileMonitor extends TilePeripheralBase
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Terminal originTerminal = getTerminal().getTerminal();
|
||||
if( originTerminal == null )
|
||||
|
||||
ServerTerminal serverTerminal = getServerMonitor();
|
||||
if( serverTerminal == null || !serverTerminal.isColour() ) return;
|
||||
|
||||
Terminal originTerminal = serverTerminal.getTerminal();
|
||||
if( originTerminal == null ) return;
|
||||
|
||||
double xCharWidth = (m_width - ((RENDER_BORDER + RENDER_MARGIN) * 2.0)) / originTerminal.getWidth();
|
||||
double yCharHeight = (m_height - ((RENDER_BORDER + RENDER_MARGIN) * 2.0)) / originTerminal.getHeight();
|
||||
|
||||
int xCharPos = (int) Math.min( originTerminal.getWidth(), Math.max( ((pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth) + 1.0, 1.0 ) );
|
||||
int yCharPos = (int) Math.min( originTerminal.getHeight(), Math.max( ((pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight) + 1.0, 1.0 ) );
|
||||
|
||||
for( int y = 0; y < m_height; ++y )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( !getTerminal().isColour() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double xCharWidth = (m_width - ((RENDER_BORDER + RENDER_MARGIN) * 2.0)) / (originTerminal.getWidth());
|
||||
double yCharHeight = (m_height - ((RENDER_BORDER + RENDER_MARGIN) * 2.0)) / (originTerminal.getHeight());
|
||||
|
||||
int xCharPos = (int)Math.min(originTerminal.getWidth(), Math.max(((pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth) + 1.0, 1.0));
|
||||
int yCharPos = (int)Math.min(originTerminal.getHeight(), Math.max(((pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight) + 1.0, 1.0));
|
||||
|
||||
for( int y=0; y<m_height; ++y )
|
||||
{
|
||||
for( int x=0; x<m_width; ++x )
|
||||
for( int x = 0; x < m_width; ++x )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor != null )
|
||||
if( monitor == null )continue;
|
||||
|
||||
for( IComputerAccess computer : monitor.m_computers )
|
||||
{
|
||||
monitor.queueTouchEvent(xCharPos, yCharPos);
|
||||
computer.queueEvent( "monitor_touch", new Object[] {
|
||||
computer.getAttachmentName(), xCharPos, yCharPos
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void queueTouchEvent( int xCharPos, int yCharPos )
|
||||
{
|
||||
for( IComputerAccess computer : m_computers )
|
||||
{
|
||||
computer.queueEvent( "monitor_touch", new Object[] {
|
||||
computer.getAttachmentName(), xCharPos, yCharPos
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private void queueSizeChangedEvent()
|
||||
{
|
||||
m_sizeChangedQueued = true;
|
||||
}
|
||||
|
||||
|
||||
private XYPair convertToXY( float xPos, float yPos, float zPos, int side )
|
||||
{
|
||||
switch (side)
|
||||
@ -781,18 +774,7 @@ public class TileMonitor extends TilePeripheralBase
|
||||
{
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_computers.size() == 0 )
|
||||
{
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin != null )
|
||||
{
|
||||
origin.rebuildTerminal();
|
||||
}
|
||||
}
|
||||
if( !m_computers.contains(computer) )
|
||||
{
|
||||
m_computers.add(computer);
|
||||
}
|
||||
m_computers.add( computer );
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,10 +782,7 @@ public class TileMonitor extends TilePeripheralBase
|
||||
{
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_computers.contains(computer) )
|
||||
{
|
||||
m_computers.remove(computer);
|
||||
}
|
||||
m_computers.remove( computer );
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user