1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-26 00:46:54 +00:00

Prevent computer dump command sending too much information

This commit is contained in:
SquidDev 2018-01-20 11:07:09 +00:00
parent 01d9919a3e
commit 3298efe652
3 changed files with 167 additions and 78 deletions

View File

@ -10,11 +10,13 @@ import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -48,8 +50,35 @@ public final class CommandComputerCraft extends CommandDelegate
{
TextTable table = new TextTable( "Instance", "Id", "On", "Position" );
int max = 50;
for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() )
List<ServerComputer> computers = new ArrayList<>( ComputerCraft.serverComputerRegistry.getComputers() );
// Unless we're on a server, limit the number of rows we can send.
if( !(context.getSender() instanceof MinecraftServer) )
{
World world = context.getSender().getEntityWorld();
BlockPos pos = context.getSender().getPosition();
computers.sort( ( a, b ) -> {
if( a.getWorld() == b.getWorld() && a.getWorld() == world )
{
return Double.compare( a.getPosition().distanceSq( pos ), b.getPosition().distanceSq( pos ) );
}
else if( a.getWorld() == world )
{
return -1;
}
else if( b.getWorld() == world )
{
return 1;
}
else
{
return Integer.compare( a.getInstanceID(), b.getInstanceID() );
}
} );
}
for( ServerComputer computer : computers )
{
table.addRow(
linkComputer( computer ),
@ -57,8 +86,6 @@ public final class CommandComputerCraft extends CommandDelegate
bool( computer.isOn() ),
linkPosition( context, computer )
);
if( max-- < 0 ) break;
}
table.displayTo( context.getSender() );
@ -80,7 +107,7 @@ public final class CommandComputerCraft extends CommandDelegate
IPeripheral peripheral = computer.getPeripheral( i );
if( peripheral != null )
{
table.addRow( header( "Peripheral " + Computer.s_sideNames[ i ] ), text( peripheral.getType() ) );
table.addRow( header( "Peripheral " + Computer.s_sideNames[i] ), text( peripheral.getType() ) );
}
}
@ -198,32 +225,36 @@ public final class CommandComputerCraft extends CommandDelegate
}
} );
root.register(new SubCommandBase(
root.register( new SubCommandBase(
"view", "<id>", "View the terminal of a computer.", UserLevel.OP,
"Open the terminal of a computer, allowing remote control of a computer. This does not provide access to " +
"turtle's inventories. You can either specify the computer's instance id (e.g. 123) or computer id (e.g #123)."
) {
)
{
@Override
public void execute(@Nonnull CommandContext context, @Nonnull List<String> arguments) throws CommandException {
if (arguments.size() != 1) throw new CommandException(context.getFullUsage());
public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) throws CommandException
{
if( arguments.size() != 1 ) throw new CommandException( context.getFullUsage() );
ICommandSender sender = context.getSender();
if (!(sender instanceof EntityPlayerMP)) {
throw new CommandException("Cannot open terminal for non-player");
if( !(sender instanceof EntityPlayerMP) )
{
throw new CommandException( "Cannot open terminal for non-player" );
}
ServerComputer computer = ComputerSelector.getComputer(arguments.get(0));
ServerComputer computer = ComputerSelector.getComputer( arguments.get( 0 ) );
ComputerCraft.openComputerGUI( (EntityPlayerMP) sender, computer );
}
@Nonnull
@Override
public List<String> getCompletion(@Nonnull CommandContext context, @Nonnull List<String> arguments) {
public List<String> getCompletion( @Nonnull CommandContext context, @Nonnull List<String> arguments )
{
return arguments.size() == 1
? ComputerSelector.completeComputer( arguments.get( 0 ) )
: Collections.emptyList();
}
});
} );
return root;

View File

@ -3,14 +3,59 @@ package dan200.computercraft.shared.command;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.command.CommandException;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Predicate;
public final class ComputerSelector
{
private static ServerComputer getComputer( Predicate<ServerComputer> predicate, String kind ) throws CommandException
{
// We copy it to prevent concurrent modifications.
List<ServerComputer> computers = Lists.newArrayList( ComputerCraft.serverComputerRegistry.getComputers() );
List<ServerComputer> candidates = Lists.newArrayList();
for( ServerComputer searchComputer : computers )
{
if( predicate.test( searchComputer ) ) candidates.add( searchComputer );
}
if( candidates.size() == 0 )
{
throw new CommandException( "No such computer for " + kind );
}
else if( candidates.size() == 1 )
{
return candidates.get( 0 );
}
else
{
StringBuilder builder = new StringBuilder( "Multiple computers with " )
.append( kind ).append( " (instances " );
boolean first = true;
for( ServerComputer computer : candidates )
{
if( first )
{
first = false;
}
else
{
builder.append( ", " );
}
builder.append( computer.getInstanceID() );
}
builder.append( ")" );
throw new CommandException( builder.toString() );
}
}
public static ServerComputer getComputer( String selector ) throws CommandException
{
if( selector.length() > 0 && selector.charAt( 0 ) == '#' )
@ -27,49 +72,17 @@ public final class ComputerSelector
throw new CommandException( "'" + selector + "' is not a valid number" );
}
// We copy it to prevent concurrent modifications.
List<ServerComputer> computers = Lists.newArrayList( ComputerCraft.serverComputerRegistry.getComputers() );
List<ServerComputer> candidates = Lists.newArrayList();
for( ServerComputer searchComputer : computers )
{
if( searchComputer.getID() == id )
{
candidates.add( searchComputer );
}
}
if( candidates.size() == 0 )
{
throw new CommandException( "No such computer for id " + id );
}
else if( candidates.size() == 1 )
{
return candidates.get( 0 );
}
else
{
StringBuilder builder = new StringBuilder( "Multiple computers with id " )
.append( id ).append( " (instances " );
boolean first = true;
for( ServerComputer computer : candidates )
{
if( first )
{
first = false;
}
else
{
builder.append( ", " );
}
builder.append( computer.getInstanceID() );
}
builder.append( ")" );
throw new CommandException( builder.toString() );
}
return getComputer( x -> x.getID() == id, "id " + id );
}
else if( selector.length() > 0 && selector.charAt( 0 ) == '@' )
{
String label = selector.substring( 1 );
return getComputer( x -> Objects.equals( label, x.getLabel() ), "label '" + label + "'" );
}
else if( selector.length() > 0 && selector.charAt( 0 ) == '~' )
{
String familyName = selector.substring( 1 );
return getComputer( x -> x.getFamily().name().equalsIgnoreCase( familyName ), "family '" + familyName + "'" );
}
else
{
@ -97,7 +110,7 @@ public final class ComputerSelector
public static List<String> completeComputer( String selector )
{
Set<String> options = Sets.newHashSet();
TreeSet<String> options = Sets.newTreeSet();
// We copy it to prevent concurrent modifications.
List<ServerComputer> computers = Lists.newArrayList( ComputerCraft.serverComputerRegistry.getComputers() );
@ -112,6 +125,26 @@ public final class ComputerSelector
if( id.startsWith( selector ) ) options.add( "#" + id );
}
}
else if( selector.length() > 0 && selector.charAt( 0 ) == '@' )
{
String label = selector.substring( 1 );
for( ServerComputer computer : computers )
{
String thisLabel = computer.getLabel();
if( thisLabel != null && thisLabel.startsWith( label ) ) options.add( "@" + thisLabel );
}
}
else if( selector.length() > 0 && selector.charAt( 0 ) == '~' )
{
String familyName = selector.substring( 1 ).toLowerCase( Locale.ENGLISH );
for( ComputerFamily family : ComputerFamily.values() )
{
if( family.name().toLowerCase( Locale.ENGLISH ).startsWith( familyName ) )
{
options.add( "~" + family.name() );
}
}
}
else
{
for( ServerComputer computer : computers )
@ -121,6 +154,20 @@ public final class ComputerSelector
}
}
return Lists.newArrayList( options );
if( options.size() > 100 )
{
ArrayList<String> result = Lists.newArrayListWithCapacity( 100 );
for( String element : options )
{
if( result.size() > 100 ) break;
result.add( element );
}
return result;
}
else
{
return Lists.newArrayList( options );
}
}
}

View File

@ -18,7 +18,7 @@ import static dan200.computercraft.shared.command.framework.ChatHelpers.text;
public class TextTable
{
private static final String CHARACTERS = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000";
private static final int[] CHAR_WIDTHS = new int[] {
private static final int[] CHAR_WIDTHS = new int[]{
6, 6, 6, 6, 6, 6, 4, 6, 6, 6, 6, 6, 6, 6, 6, 4,
4, 6, 7, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1,
1, 2, 5, 6, 6, 6, 6, 3, 5, 5, 5, 6, 2, 6, 2, 6,
@ -55,7 +55,7 @@ public class TextTable
}
else if( CHARACTERS.indexOf( character ) != -1 )
{
return CHAR_WIDTHS[ character ];
return CHAR_WIDTHS[character];
}
else
{
@ -108,10 +108,10 @@ public class TextTable
public TextTable( @Nonnull String... header )
{
this.header = new ITextComponent[ header.length ];
this.header = new ITextComponent[header.length];
for( int i = 0; i < header.length; i++ )
{
this.header[ i ] = ChatHelpers.header( header[ i ] );
this.header[i] = ChatHelpers.header( header[i] );
}
this.columns = header.length;
}
@ -136,27 +136,32 @@ public class TextTable
final int maxWidth = getMaxWidth( sender );
int[] minWidths = new int[ columns ];
int[] maxWidths = new int[ columns ];
int[] rowWidths = new int[ columns ];
int[] minWidths = new int[columns];
int[] maxWidths = new int[columns];
int[] rowWidths = new int[columns];
if( header != null )
{
for( int i = 0; i < columns; i++ )
{
maxWidths[ i ] = minWidths[ i ] = getWidth( header[ i ], sender );
maxWidths[i] = minWidths[i] = getWidth( header[i], sender );
}
}
for( ITextComponent[] row : rows )
// Limit the number of rows to something sensible.
int limit = isPlayer( sender ) ? 30 : 100;
if( limit > rows.size() ) limit = rows.size();
for( int y = 0; y < limit; y++ )
{
ITextComponent[] row = rows.get( y );
for( int i = 0; i < row.length; i++ )
{
int width = getWidth( row[ i ], sender );
rowWidths[ i ] += width;
if( width > maxWidths[ i ] )
int width = getWidth( row[i], sender );
rowWidths[i] += width;
if( width > maxWidths[i] )
{
maxWidths[ i ] = width;
maxWidths[i] = width;
}
}
}
@ -164,7 +169,7 @@ public class TextTable
// Calculate the average width
for( int i = 0; i < columns; i++ )
{
rowWidths[ i ] = Math.max( rowWidths[ i ], rows.size() );
rowWidths[i] = Math.max( rowWidths[i], rows.size() );
}
int totalWidth = (columns - 1) * getWidth( SEPARATOR, sender );
@ -179,7 +184,7 @@ public class TextTable
for( int i = 0; i < columns; i++ )
{
if( i != 0 ) out.appendSibling( SEPARATOR );
appendFixed( out, sender, header[ i ], maxWidths[ i ] );
appendFixed( out, sender, header[i], maxWidths[i] );
}
out.appendSibling( LINE );
@ -190,17 +195,23 @@ public class TextTable
out.appendSibling( LINE );
}
for( int i = 0; i < rows.size(); i++ )
for( int i = 0; i < limit; i++ )
{
ITextComponent[] row = rows.get( i );
if( i != 0 ) out.appendSibling( LINE );
for( int j = 0; j < columns; j++ )
{
if( j != 0 ) out.appendSibling( SEPARATOR );
appendFixed( out, sender, row[ j ], maxWidths[ j ] );
appendFixed( out, sender, row[j], maxWidths[j] );
}
}
if( limit != rows.size() )
{
out.appendSibling( LINE );
out.appendSibling( coloured( (rows.size() - limit) + " additional rows...", TextFormatting.AQUA ) );
}
sender.sendMessage( out );
}