mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-16 21:27:10 +00:00
Started work on upgrading to 1.16.1. Not in a compilable state yet
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.shared.common.BlockGeneric;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.util.NamedBlockEntityType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.state.property.EnumProperty;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockMonitor extends BlockGeneric
|
||||
{
|
||||
public static final DirectionProperty ORIENTATION = DirectionProperty.of( "orientation",
|
||||
Direction.UP, Direction.DOWN, Direction.NORTH );
|
||||
|
||||
public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING;
|
||||
|
||||
static final EnumProperty<MonitorEdgeState> STATE = EnumProperty.of( "state", MonitorEdgeState.class );
|
||||
|
||||
public BlockMonitor( Settings settings, NamedBlockEntityType<? extends TileGeneric> type )
|
||||
{
|
||||
super( settings, type );
|
||||
setDefaultState( getStateManager().getDefaultState()
|
||||
.with( ORIENTATION, Direction.NORTH )
|
||||
.with( FACING, Direction.NORTH )
|
||||
.with( STATE, MonitorEdgeState.NONE ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderLayer getRenderLayer()
|
||||
{
|
||||
return RenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties( StateManager.Builder<Block, BlockState> builder )
|
||||
{
|
||||
builder.add( ORIENTATION, FACING, STATE );
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockState getPlacementState( ItemPlacementContext context )
|
||||
{
|
||||
float pitch = context.getPlayer() == null ? 0 : context.getPlayer().pitch;
|
||||
Direction orientation;
|
||||
if( pitch > 66.5f )
|
||||
{
|
||||
// If the player is looking down, place it facing upwards
|
||||
orientation = Direction.UP;
|
||||
}
|
||||
else if( pitch < -66.5f )
|
||||
{
|
||||
// If they're looking up, place it down.
|
||||
orientation = Direction.DOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
orientation = Direction.NORTH;
|
||||
}
|
||||
|
||||
return getDefaultState()
|
||||
.with( FACING, context.getPlayerFacing().getOpposite() )
|
||||
.with( ORIENTATION, orientation );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaced( World world, BlockPos pos, BlockState blockState, @Nullable LivingEntity livingEntity, ItemStack itemStack )
|
||||
{
|
||||
super.onPlaced( world, pos, blockState, livingEntity, itemStack );
|
||||
|
||||
BlockEntity entity = world.getBlockEntity( pos );
|
||||
if( entity instanceof TileMonitor && !world.isClient )
|
||||
{
|
||||
TileMonitor monitor = (TileMonitor) entity;
|
||||
monitor.contractNeighbours();
|
||||
monitor.contract();
|
||||
monitor.expand();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import dan200.computercraft.shared.common.ClientTerminal;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class ClientMonitor extends ClientTerminal
|
||||
{
|
||||
private static final Set<ClientMonitor> allMonitors = new HashSet<>();
|
||||
|
||||
private final TileMonitor origin;
|
||||
|
||||
public long lastRenderFrame = -1;
|
||||
public BlockPos lastRenderPos = null;
|
||||
public int[] renderDisplayLists = null;
|
||||
|
||||
public ClientMonitor( boolean colour, TileMonitor origin )
|
||||
{
|
||||
super( colour );
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public TileMonitor getOrigin()
|
||||
{
|
||||
return origin;
|
||||
}
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
public void createLists()
|
||||
{
|
||||
if( renderDisplayLists == null )
|
||||
{
|
||||
renderDisplayLists = new int[3];
|
||||
|
||||
for( int i = 0; i < renderDisplayLists.length; i++ )
|
||||
{
|
||||
renderDisplayLists[i] = GlStateManager.genLists( 1 );
|
||||
}
|
||||
|
||||
synchronized( allMonitors )
|
||||
{
|
||||
allMonitors.add( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
public void destroy()
|
||||
{
|
||||
if( renderDisplayLists != null )
|
||||
{
|
||||
synchronized( allMonitors )
|
||||
{
|
||||
allMonitors.remove( this );
|
||||
}
|
||||
|
||||
for( int list : renderDisplayLists )
|
||||
{
|
||||
GlStateManager.deleteLists( list, 1 );
|
||||
}
|
||||
|
||||
renderDisplayLists = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
public static void destroyAll()
|
||||
{
|
||||
synchronized( allMonitors )
|
||||
{
|
||||
for( Iterator<ClientMonitor> iterator = allMonitors.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
ClientMonitor monitor = iterator.next();
|
||||
if( monitor.renderDisplayLists != null )
|
||||
{
|
||||
for( int list : monitor.renderDisplayLists )
|
||||
{
|
||||
GlStateManager.deleteLists( list, 1 );
|
||||
}
|
||||
monitor.renderDisplayLists = null;
|
||||
}
|
||||
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.*;
|
||||
|
||||
public enum MonitorEdgeState implements StringIdentifiable
|
||||
{
|
||||
NONE( "none", 0 ),
|
||||
|
||||
L( "l", LEFT ),
|
||||
R( "r", RIGHT ),
|
||||
LR( "lr", LEFT | RIGHT ),
|
||||
U( "u", UP ),
|
||||
D( "d", DOWN ),
|
||||
|
||||
UD( "ud", UP | DOWN ),
|
||||
RD( "rd", RIGHT | DOWN ),
|
||||
LD( "ld", LEFT | DOWN ),
|
||||
RU( "ru", RIGHT | UP ),
|
||||
LU( "lu", LEFT | UP ),
|
||||
|
||||
LRD( "lrd", LEFT | RIGHT | DOWN ),
|
||||
RUD( "rud", RIGHT | UP | DOWN ),
|
||||
LUD( "lud", LEFT | UP | DOWN ),
|
||||
LRU( "lru", LEFT | RIGHT | UP ),
|
||||
LRUD( "lrud", LEFT | RIGHT | UP | DOWN );
|
||||
|
||||
private final String name;
|
||||
private final int flags;
|
||||
|
||||
MonitorEdgeState( String name, int flags )
|
||||
{
|
||||
this.name = name;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
private static final MonitorEdgeState[] BY_FLAG = new MonitorEdgeState[16];
|
||||
|
||||
static
|
||||
{
|
||||
for( MonitorEdgeState state : values() )
|
||||
{
|
||||
BY_FLAG[state.flags] = state;
|
||||
}
|
||||
}
|
||||
|
||||
public static MonitorEdgeState fromConnections( boolean up, boolean down, boolean left, boolean right )
|
||||
{
|
||||
return BY_FLAG[(up ? UP : 0) | (down ? DOWN : 0) | (left ? LEFT : 0) | (right ? RIGHT : 0)];
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String asString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
static final class Flags
|
||||
{
|
||||
static final int UP = 1 << 0;
|
||||
static final int DOWN = 1 << 1;
|
||||
static final int LEFT = 1 << 2;
|
||||
static final int RIGHT = 1 << 3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.apis.TermAPI;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.core.apis.ArgumentHelper.*;
|
||||
|
||||
public class MonitorPeripheral implements IPeripheral
|
||||
{
|
||||
private final TileMonitor m_monitor;
|
||||
|
||||
public MonitorPeripheral( TileMonitor monitor )
|
||||
{
|
||||
m_monitor = monitor;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getType()
|
||||
{
|
||||
return "monitor";
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return new String[] {
|
||||
"write",
|
||||
"scroll",
|
||||
"setCursorPos",
|
||||
"setCursorBlink",
|
||||
"getCursorPos",
|
||||
"getSize",
|
||||
"clear",
|
||||
"clearLine",
|
||||
"setTextScale",
|
||||
"setTextColour",
|
||||
"setTextColor",
|
||||
"setBackgroundColour",
|
||||
"setBackgroundColor",
|
||||
"isColour",
|
||||
"isColor",
|
||||
"getTextColour",
|
||||
"getTextColor",
|
||||
"getBackgroundColour",
|
||||
"getBackgroundColor",
|
||||
"blit",
|
||||
"setPaletteColour",
|
||||
"setPaletteColor",
|
||||
"getPaletteColour",
|
||||
"getPaletteColor",
|
||||
"getTextScale",
|
||||
"getCursorBlink",
|
||||
};
|
||||
}
|
||||
|
||||
@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 detached" );
|
||||
|
||||
Terminal terminal = monitor.getTerminal();
|
||||
if( terminal == null ) throw new LuaException( "Monitor has been detached" );
|
||||
|
||||
switch( method )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
// write
|
||||
String text = args.length > 0 && args[0] != null ? args[0].toString() : "";
|
||||
terminal.write( text );
|
||||
terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() );
|
||||
return null;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// scroll
|
||||
int value = getInt( args, 0 );
|
||||
terminal.scroll( value );
|
||||
return null;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// setCursorPos
|
||||
int x = getInt( args, 0 ) - 1;
|
||||
int y = getInt( args, 1 ) - 1;
|
||||
terminal.setCursorPos( x, y );
|
||||
return null;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// setCursorBlink
|
||||
boolean blink = getBoolean( args, 0 );
|
||||
terminal.setCursorBlink( blink );
|
||||
return null;
|
||||
}
|
||||
case 4: // getCursorPos
|
||||
return new Object[] { terminal.getCursorX() + 1, terminal.getCursorY() + 1 };
|
||||
case 5: // getSize
|
||||
return new Object[] { terminal.getWidth(), terminal.getHeight() };
|
||||
case 6: // clear
|
||||
terminal.clear();
|
||||
return null;
|
||||
case 7: // clearLine
|
||||
terminal.clearLine();
|
||||
return null;
|
||||
case 8:
|
||||
{
|
||||
// setTextScale
|
||||
int scale = (int) (getReal( args, 0 ) * 2.0);
|
||||
if( scale < 1 || scale > 10 )
|
||||
{
|
||||
throw new LuaException( "Expected number in range 0.5-5" );
|
||||
}
|
||||
monitor.setTextScale( scale );
|
||||
return null;
|
||||
}
|
||||
case 9:
|
||||
case 10:
|
||||
{
|
||||
// setTextColour/setTextColor
|
||||
int colour = TermAPI.parseColour( args );
|
||||
terminal.setTextColour( colour );
|
||||
return null;
|
||||
}
|
||||
case 11:
|
||||
case 12:
|
||||
{
|
||||
// setBackgroundColour/setBackgroundColor
|
||||
int colour = TermAPI.parseColour( args );
|
||||
terminal.setBackgroundColour( colour );
|
||||
return null;
|
||||
}
|
||||
case 13:
|
||||
case 14: // isColour/isColor
|
||||
return new Object[] { monitor.isColour() };
|
||||
case 15:
|
||||
case 16: // getTextColour/getTextColor
|
||||
return TermAPI.encodeColour( terminal.getTextColour() );
|
||||
case 17:
|
||||
case 18: // getBackgroundColour/getBackgroundColor
|
||||
return TermAPI.encodeColour( terminal.getBackgroundColour() );
|
||||
case 19:
|
||||
{
|
||||
// blit
|
||||
String text = getString( args, 0 );
|
||||
String textColour = getString( args, 1 );
|
||||
String backgroundColour = getString( args, 2 );
|
||||
if( textColour.length() != text.length() || backgroundColour.length() != text.length() )
|
||||
{
|
||||
throw new LuaException( "Arguments must be the same length" );
|
||||
}
|
||||
|
||||
terminal.blit( text, textColour, backgroundColour );
|
||||
terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() );
|
||||
return null;
|
||||
}
|
||||
case 20:
|
||||
case 21:
|
||||
{
|
||||
// setPaletteColour/setPaletteColor
|
||||
int colour = 15 - TermAPI.parseColour( args );
|
||||
if( args.length == 2 )
|
||||
{
|
||||
int hex = getInt( args, 1 );
|
||||
double[] rgb = Palette.decodeRGB8( hex );
|
||||
TermAPI.setColour( terminal, colour, rgb[0], rgb[1], rgb[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
double r = getReal( args, 1 );
|
||||
double g = getReal( args, 2 );
|
||||
double b = getReal( args, 3 );
|
||||
TermAPI.setColour( terminal, colour, r, g, b );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
case 22:
|
||||
case 23:
|
||||
{
|
||||
// getPaletteColour/getPaletteColor
|
||||
Palette palette = terminal.getPalette();
|
||||
|
||||
int colour = 15 - TermAPI.parseColour( args );
|
||||
|
||||
if( palette != null )
|
||||
{
|
||||
return ArrayUtils.toObject( palette.getColour( colour ) );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
case 24: // getTextScale
|
||||
return new Object[] { monitor.getTextScale() / 2.0 };
|
||||
case 25:
|
||||
// getCursorBlink
|
||||
return new Object[] { terminal.getCursorBlink() };
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attach( @Nonnull IComputerAccess computer )
|
||||
{
|
||||
m_monitor.addComputer( computer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach( @Nonnull IComputerAccess computer )
|
||||
{
|
||||
m_monitor.removeComputer( computer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( IPeripheral other )
|
||||
{
|
||||
return other instanceof MonitorPeripheral && m_monitor == ((MonitorPeripheral) other).m_monitor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.common.ServerTerminal;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ServerMonitor extends ServerTerminal
|
||||
{
|
||||
private final TileMonitor origin;
|
||||
private int textScale = 2;
|
||||
private final AtomicBoolean resized = new AtomicBoolean( false );
|
||||
private final AtomicBoolean changed = new AtomicBoolean( false );
|
||||
|
||||
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.set( true );
|
||||
markChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void markTerminalChanged()
|
||||
{
|
||||
super.markTerminalChanged();
|
||||
markChanged();
|
||||
}
|
||||
|
||||
private void markChanged()
|
||||
{
|
||||
if( !changed.getAndSet( true ) ) TickScheduler.schedule( origin );
|
||||
}
|
||||
|
||||
protected void clearChanged()
|
||||
{
|
||||
changed.set( false );
|
||||
}
|
||||
|
||||
public int getTextScale()
|
||||
{
|
||||
return textScale;
|
||||
}
|
||||
|
||||
public synchronized void setTextScale( int textScale )
|
||||
{
|
||||
if( this.textScale == textScale ) return;
|
||||
this.textScale = textScale;
|
||||
rebuild();
|
||||
}
|
||||
|
||||
public boolean pollResized()
|
||||
{
|
||||
return resized.getAndSet( false );
|
||||
}
|
||||
|
||||
public boolean pollTerminalChanged()
|
||||
{
|
||||
update();
|
||||
return hasTerminalChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.common.ServerTerminal;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.util.NamedBlockEntityType;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
{
|
||||
public static final NamedBlockEntityType<TileMonitor> FACTORY_NORMAL = NamedBlockEntityType.create(
|
||||
new Identifier( ComputerCraft.MOD_ID, "monitor_normal" ),
|
||||
f -> new TileMonitor( f, false )
|
||||
);
|
||||
|
||||
public static final NamedBlockEntityType<TileMonitor> FACTORY_ADVANCED = NamedBlockEntityType.create(
|
||||
new Identifier( ComputerCraft.MOD_ID, "monitor_advanced" ),
|
||||
f -> new TileMonitor( f, true )
|
||||
);
|
||||
|
||||
public static final double RENDER_BORDER = 2.0 / 16.0;
|
||||
public static final double RENDER_MARGIN = 0.5 / 16.0;
|
||||
public static final double RENDER_PIXEL_SCALE = 1.0 / 64.0;
|
||||
|
||||
private static final int MAX_WIDTH = 8;
|
||||
private static final int MAX_HEIGHT = 6;
|
||||
|
||||
private static final String NBT_X = "XIndex";
|
||||
private static final String NBT_Y = "YIndex";
|
||||
private static final String NBT_WIDTH = "Width";
|
||||
private static final String NBT_HEIGHT = "Height";
|
||||
|
||||
private final boolean advanced;
|
||||
|
||||
private ServerMonitor m_serverMonitor;
|
||||
private ClientMonitor m_clientMonitor;
|
||||
private MonitorPeripheral m_peripheral;
|
||||
private final Set<IComputerAccess> m_computers = new HashSet<>();
|
||||
|
||||
private boolean m_destroyed = false;
|
||||
private boolean visiting = false;
|
||||
|
||||
private int m_width = 1;
|
||||
private int m_height = 1;
|
||||
private int m_xIndex = 0;
|
||||
private int m_yIndex = 0;
|
||||
|
||||
public TileMonitor( BlockEntityType<? extends TileMonitor> type, boolean advanced )
|
||||
{
|
||||
super( type );
|
||||
this.advanced = advanced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelRemoval()
|
||||
{
|
||||
super.cancelRemoval();
|
||||
TickScheduler.schedule( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
// TODO: Call this before using the block
|
||||
if( m_destroyed ) return;
|
||||
m_destroyed = true;
|
||||
if( !getWorld().isClient ) contractNeighbours();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markRemoved()
|
||||
{
|
||||
super.markRemoved();
|
||||
if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public void onChunkUnloaded()
|
||||
{
|
||||
super.onChunkUnloaded();
|
||||
if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy();
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean onActivate( PlayerEntity player, Hand hand, BlockHitResult hit )
|
||||
{
|
||||
if( !player.isSneaking() && getFront() == hit.getSide() )
|
||||
{
|
||||
if( !getWorld().isClient )
|
||||
{
|
||||
monitorTouched(
|
||||
(float) (hit.getPos().x - hit.getBlockPos().getX()),
|
||||
(float) (hit.getPos().y - hit.getBlockPos().getY()),
|
||||
(float) (hit.getPos().z - hit.getBlockPos().getZ())
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompoundTag toTag( CompoundTag tag )
|
||||
{
|
||||
tag.putInt( NBT_X, m_xIndex );
|
||||
tag.putInt( NBT_Y, m_yIndex );
|
||||
tag.putInt( NBT_WIDTH, m_width );
|
||||
tag.putInt( NBT_HEIGHT, m_height );
|
||||
return super.toTag( tag );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag( CompoundTag tag )
|
||||
{
|
||||
super.fromTag( tag );
|
||||
m_xIndex = tag.getInt( NBT_X );
|
||||
m_yIndex = tag.getInt( NBT_Y );
|
||||
m_width = tag.getInt( NBT_WIDTH );
|
||||
m_height = tag.getInt( NBT_HEIGHT );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockTick()
|
||||
{
|
||||
if( m_xIndex != 0 || m_yIndex != 0 || m_serverMonitor == null ) return;
|
||||
|
||||
m_serverMonitor.clearChanged();
|
||||
|
||||
if( m_serverMonitor.pollResized() )
|
||||
{
|
||||
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;
|
||||
|
||||
for( IComputerAccess computer : monitor.m_computers )
|
||||
{
|
||||
computer.queueEvent( "monitor_resize", new Object[] {
|
||||
computer.getAttachmentName()
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_serverMonitor.pollTerminalChanged() ) updateBlock();
|
||||
}
|
||||
|
||||
// IPeripheralTile implementation
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
createServerMonitor(); // Ensure the monitor is created before doing anything else.
|
||||
if( m_peripheral == null ) m_peripheral = new MonitorPeripheral( this );
|
||||
return m_peripheral;
|
||||
}
|
||||
|
||||
public ServerMonitor getCachedServerMonitor()
|
||||
{
|
||||
return m_serverMonitor;
|
||||
}
|
||||
|
||||
private ServerMonitor getServerMonitor()
|
||||
{
|
||||
if( m_serverMonitor != null ) return m_serverMonitor;
|
||||
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin == null ) return null;
|
||||
|
||||
return m_serverMonitor = origin.m_serverMonitor;
|
||||
}
|
||||
|
||||
private ServerMonitor createServerMonitor()
|
||||
{
|
||||
if( m_serverMonitor != null ) return m_serverMonitor;
|
||||
|
||||
if( m_xIndex == 0 && m_yIndex == 0 )
|
||||
{
|
||||
// If we're the origin, set up the new monitor
|
||||
m_serverMonitor = new ServerMonitor( advanced, this );
|
||||
m_serverMonitor.rebuild();
|
||||
|
||||
// And propagate it to child monitors
|
||||
for( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
for( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
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();
|
||||
BlockEntity te = world.getBlockEntity( 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();
|
||||
BlockEntity te = world.getBlockEntity( pos.offset( getRight(), -m_xIndex ).offset( getDown(), -m_yIndex ) );
|
||||
if( !(te instanceof TileMonitor) ) return null;
|
||||
|
||||
return m_clientMonitor = ((TileMonitor) te).m_clientMonitor;
|
||||
}
|
||||
|
||||
// Networking stuff
|
||||
|
||||
@Override
|
||||
protected void writeDescription( @Nonnull CompoundTag nbt )
|
||||
{
|
||||
super.writeDescription( nbt );
|
||||
|
||||
nbt.putInt( NBT_X, m_xIndex );
|
||||
nbt.putInt( NBT_Y, m_yIndex );
|
||||
nbt.putInt( NBT_WIDTH, m_width );
|
||||
nbt.putInt( NBT_HEIGHT, m_height );
|
||||
|
||||
if( m_xIndex == 0 && m_yIndex == 0 && m_serverMonitor != null )
|
||||
{
|
||||
m_serverMonitor.writeDescription( nbt );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void readDescription( @Nonnull CompoundTag nbt )
|
||||
{
|
||||
super.readDescription( nbt );
|
||||
|
||||
int oldXIndex = m_xIndex;
|
||||
int oldYIndex = m_yIndex;
|
||||
int oldWidth = m_width;
|
||||
int oldHeight = m_height;
|
||||
|
||||
m_xIndex = nbt.getInt( NBT_X );
|
||||
m_yIndex = nbt.getInt( NBT_Y );
|
||||
m_width = nbt.getInt( NBT_WIDTH );
|
||||
m_height = nbt.getInt( NBT_HEIGHT );
|
||||
|
||||
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( advanced, this );
|
||||
m_clientMonitor.readDescription( nbt );
|
||||
}
|
||||
|
||||
if( oldXIndex != m_xIndex || oldYIndex != m_yIndex ||
|
||||
oldWidth != m_width || oldHeight != m_height )
|
||||
{
|
||||
// One of our properties has changed, so ensure we redraw the block
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBlockState()
|
||||
{
|
||||
getWorld().setBlockState( getPos(), getCachedState()
|
||||
.with( BlockMonitor.STATE, MonitorEdgeState.fromConnections(
|
||||
m_yIndex < m_height - 1, m_yIndex > 0,
|
||||
m_xIndex > 0, m_xIndex < m_width - 1 ) ), 2 );
|
||||
}
|
||||
|
||||
// region Sizing and placement stuff
|
||||
public Direction getDirection()
|
||||
{
|
||||
return getCachedState().get( BlockMonitor.FACING );
|
||||
}
|
||||
|
||||
public Direction getOrientation()
|
||||
{
|
||||
return getCachedState().get( BlockMonitor.ORIENTATION );
|
||||
}
|
||||
|
||||
public Direction getFront()
|
||||
{
|
||||
Direction orientation = getOrientation();
|
||||
return orientation == Direction.NORTH ? getDirection() : orientation;
|
||||
}
|
||||
|
||||
public Direction getRight()
|
||||
{
|
||||
return getDirection().rotateYCounterclockwise();
|
||||
}
|
||||
|
||||
public Direction getDown()
|
||||
{
|
||||
Direction orientation = getOrientation();
|
||||
if( orientation == Direction.NORTH ) return Direction.UP;
|
||||
return orientation == Direction.DOWN ? getDirection() : getDirection().getOpposite();
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
public int getXIndex()
|
||||
{
|
||||
return m_xIndex;
|
||||
}
|
||||
|
||||
public int getYIndex()
|
||||
{
|
||||
return m_yIndex;
|
||||
}
|
||||
|
||||
private TileMonitor getSimilarMonitorAt( BlockPos pos )
|
||||
{
|
||||
if( pos.equals( getPos() ) ) return this;
|
||||
|
||||
int y = pos.getY();
|
||||
World world = getWorld();
|
||||
if( world == null || !world.isBlockLoaded( pos ) ) return null;
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( !(tile instanceof TileMonitor) ) return null;
|
||||
|
||||
TileMonitor monitor = (TileMonitor) tile;
|
||||
return !monitor.visiting && !monitor.m_destroyed && advanced == monitor.advanced
|
||||
&& getDirection() == monitor.getDirection() && getOrientation() == monitor.getOrientation()
|
||||
? monitor : null;
|
||||
}
|
||||
|
||||
private TileMonitor getNeighbour( int x, int y )
|
||||
{
|
||||
BlockPos pos = getPos();
|
||||
Direction right = getRight();
|
||||
Direction down = getDown();
|
||||
int xOffset = -m_xIndex + x;
|
||||
int yOffset = -m_yIndex + y;
|
||||
return getSimilarMonitorAt( pos.offset( right, xOffset ).offset( down, yOffset ) );
|
||||
}
|
||||
|
||||
private TileMonitor getOrigin()
|
||||
{
|
||||
return getNeighbour( 0, 0 );
|
||||
}
|
||||
|
||||
private void resize( int width, int height )
|
||||
{
|
||||
// If we're not already the origin then we'll need to generate a new terminal.
|
||||
if( m_xIndex != 0 || m_yIndex != 0 ) m_serverMonitor = null;
|
||||
|
||||
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 y = 0; y < height; y++ )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor != null && monitor.m_peripheral != null )
|
||||
{
|
||||
needsTerminal = true;
|
||||
break terminalCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Either delete the current monitor or sync a new one.
|
||||
if( needsTerminal )
|
||||
{
|
||||
if( m_serverMonitor == null ) m_serverMonitor = new ServerMonitor( 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.updateBlockState();
|
||||
monitor.updateBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mergeLeft()
|
||||
{
|
||||
TileMonitor left = getNeighbour( -1, 0 );
|
||||
if( left == null || left.m_yIndex != 0 || left.m_height != m_height ) return false;
|
||||
|
||||
int width = left.m_width + m_width;
|
||||
if( width > MAX_WIDTH ) return false;
|
||||
|
||||
TileMonitor origin = left.getOrigin();
|
||||
if( origin != null ) origin.resize( width, m_height );
|
||||
left.expand();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean mergeRight()
|
||||
{
|
||||
TileMonitor right = getNeighbour( m_width, 0 );
|
||||
if( right == null || right.m_yIndex != 0 || right.m_height != m_height ) return false;
|
||||
|
||||
int width = m_width + right.m_width;
|
||||
if( width > MAX_WIDTH ) return false;
|
||||
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin != null ) origin.resize( width, m_height );
|
||||
expand();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean mergeUp()
|
||||
{
|
||||
TileMonitor above = getNeighbour( 0, m_height );
|
||||
if( above == null || above.m_xIndex != 0 || above.m_width != m_width ) return false;
|
||||
|
||||
int height = above.m_height + m_height;
|
||||
if( height > MAX_HEIGHT ) return false;
|
||||
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin != null ) origin.resize( m_width, height );
|
||||
expand();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean mergeDown()
|
||||
{
|
||||
TileMonitor below = getNeighbour( 0, -1 );
|
||||
if( below == null || below.m_xIndex != 0 || below.m_width != m_width ) return false;
|
||||
|
||||
int height = m_height + below.m_height;
|
||||
if( height > MAX_HEIGHT ) return false;
|
||||
|
||||
TileMonitor origin = below.getOrigin();
|
||||
if( origin != null ) origin.resize( m_width, height );
|
||||
below.expand();
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "StatementWithEmptyBody" )
|
||||
void expand()
|
||||
{
|
||||
while( mergeLeft() || mergeRight() || mergeUp() || mergeDown() ) ;
|
||||
}
|
||||
|
||||
void contractNeighbours()
|
||||
{
|
||||
visiting = true;
|
||||
if( m_xIndex > 0 )
|
||||
{
|
||||
TileMonitor left = getNeighbour( m_xIndex - 1, m_yIndex );
|
||||
if( left != null ) left.contract();
|
||||
}
|
||||
if( m_xIndex + 1 < m_width )
|
||||
{
|
||||
TileMonitor right = getNeighbour( m_xIndex + 1, m_yIndex );
|
||||
if( right != null ) right.contract();
|
||||
}
|
||||
if( m_yIndex > 0 )
|
||||
{
|
||||
TileMonitor below = getNeighbour( m_xIndex, m_yIndex - 1 );
|
||||
if( below != null ) below.contract();
|
||||
}
|
||||
if( m_yIndex + 1 < m_height )
|
||||
{
|
||||
TileMonitor above = getNeighbour( m_xIndex, m_yIndex + 1 );
|
||||
if( above != null ) above.contract();
|
||||
}
|
||||
visiting = false;
|
||||
}
|
||||
|
||||
void contract()
|
||||
{
|
||||
int height = m_height;
|
||||
int width = m_width;
|
||||
|
||||
TileMonitor origin = getOrigin();
|
||||
if( origin == null )
|
||||
{
|
||||
TileMonitor right = width > 1 ? getNeighbour( 1, 0 ) : null;
|
||||
TileMonitor below = height > 1 ? getNeighbour( 0, 1 ) : null;
|
||||
|
||||
if( right != null ) right.resize( width - 1, 1 );
|
||||
if( below != null ) below.resize( width, height - 1 );
|
||||
if( right != null ) right.expand();
|
||||
if( below != null ) below.expand();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for( int y = 0; y < height; y++ )
|
||||
{
|
||||
for( int x = 0; x < width; x++ )
|
||||
{
|
||||
TileMonitor monitor = origin.getNeighbour( x, y );
|
||||
if( monitor != null ) continue;
|
||||
|
||||
// Decompose
|
||||
TileMonitor above = null;
|
||||
TileMonitor left = null;
|
||||
TileMonitor right = null;
|
||||
TileMonitor below = null;
|
||||
|
||||
if( y > 0 )
|
||||
{
|
||||
above = origin;
|
||||
above.resize( width, y );
|
||||
}
|
||||
if( x > 0 )
|
||||
{
|
||||
left = origin.getNeighbour( 0, y );
|
||||
left.resize( x, 1 );
|
||||
}
|
||||
if( x + 1 < width )
|
||||
{
|
||||
right = origin.getNeighbour( x + 1, y );
|
||||
right.resize( width - (x + 1), 1 );
|
||||
}
|
||||
if( y + 1 < height )
|
||||
{
|
||||
below = origin.getNeighbour( 0, y + 1 );
|
||||
below.resize( width, height - (y + 1) );
|
||||
}
|
||||
|
||||
// Re-expand
|
||||
if( above != null ) above.expand();
|
||||
if( left != null ) left.expand();
|
||||
if( right != null ) right.expand();
|
||||
if( below != null ) below.expand();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void monitorTouched( float xPos, float yPos, float zPos )
|
||||
{
|
||||
XYPair pair = XYPair
|
||||
.of( xPos, yPos, zPos, getDirection(), getOrientation() )
|
||||
.add( m_xIndex, m_height - m_yIndex - 1 );
|
||||
|
||||
if( pair.x > m_width - RENDER_BORDER || pair.y > m_height - RENDER_BORDER || pair.x < RENDER_BORDER || pair.y < RENDER_BORDER )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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++ )
|
||||
{
|
||||
for( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor == null ) continue;
|
||||
|
||||
for( IComputerAccess computer : monitor.m_computers )
|
||||
{
|
||||
computer.queueEvent( "monitor_touch", new Object[] {
|
||||
computer.getAttachmentName(), xCharPos, yCharPos
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
void addComputer( IComputerAccess computer )
|
||||
{
|
||||
m_computers.add( computer );
|
||||
}
|
||||
|
||||
void removeComputer( IComputerAccess computer )
|
||||
{
|
||||
m_computers.remove( computer );
|
||||
}
|
||||
|
||||
/*
|
||||
@Nonnull
|
||||
@Override
|
||||
public AxisAlignedBB getRenderBoundingBox()
|
||||
{
|
||||
TileMonitor start = getNeighbour( 0, 0 );
|
||||
TileMonitor end = getNeighbour( width - 1, height - 1 );
|
||||
if( start != null && end != null )
|
||||
{
|
||||
BlockPos startPos = start.getPos();
|
||||
BlockPos endPos = end.getPos();
|
||||
int minX = Math.min( startPos.getX(), endPos.getX() );
|
||||
int minY = Math.min( startPos.getY(), endPos.getY() );
|
||||
int minZ = Math.min( startPos.getZ(), endPos.getZ() );
|
||||
int maxX = Math.max( startPos.getX(), endPos.getX() ) + 1;
|
||||
int maxY = Math.max( startPos.getY(), endPos.getY() ) + 1;
|
||||
int maxZ = Math.max( startPos.getZ(), endPos.getZ() ) + 1;
|
||||
return new AxisAlignedBB( minX, minY, minZ, maxX, maxY, maxZ );
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockPos pos = getPos();
|
||||
return new AxisAlignedBB( pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
public class XYPair
|
||||
{
|
||||
public final float x;
|
||||
public final float y;
|
||||
|
||||
public XYPair( float x, float y )
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public XYPair add( float x, float y )
|
||||
{
|
||||
return new XYPair( this.x + x, this.y + y );
|
||||
}
|
||||
|
||||
public static XYPair of( float xPos, float yPos, float zPos, Direction facing, Direction orientation )
|
||||
{
|
||||
switch( orientation )
|
||||
{
|
||||
case NORTH:
|
||||
switch( facing )
|
||||
{
|
||||
case NORTH:
|
||||
return new XYPair( 1 - xPos, 1 - yPos );
|
||||
case SOUTH:
|
||||
return new XYPair( xPos, 1 - yPos );
|
||||
case WEST:
|
||||
return new XYPair( zPos, 1 - yPos );
|
||||
case EAST:
|
||||
return new XYPair( 1 - zPos, 1 - yPos );
|
||||
}
|
||||
break;
|
||||
case DOWN:
|
||||
switch( facing )
|
||||
{
|
||||
case NORTH:
|
||||
return new XYPair( 1 - xPos, zPos );
|
||||
case SOUTH:
|
||||
return new XYPair( xPos, 1 - zPos );
|
||||
case WEST:
|
||||
return new XYPair( zPos, xPos );
|
||||
case EAST:
|
||||
return new XYPair( 1 - zPos, 1 - xPos );
|
||||
}
|
||||
break;
|
||||
case UP:
|
||||
switch( facing )
|
||||
{
|
||||
case NORTH:
|
||||
return new XYPair( 1 - xPos, 1 - zPos );
|
||||
case SOUTH:
|
||||
return new XYPair( xPos, zPos );
|
||||
case WEST:
|
||||
return new XYPair( zPos, 1 - xPos );
|
||||
case EAST:
|
||||
return new XYPair( 1 - zPos, xPos );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return new XYPair( xPos, zPos );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user