mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-30 21:23:00 +00:00 
			
		
		
		
	Various improvements to the tracking system
- Trackers are created per-user, meaning multiple people can run /computercraft track at once. - Allow sorting the tracking information by arbitrary fields. - Add support for tracking arbitrary fields (though none are currently implemented).
This commit is contained in:
		| @@ -11,6 +11,7 @@ import dan200.computercraft.core.computer.Computer; | ||||
| import dan200.computercraft.core.computer.IComputerEnvironment; | ||||
| import dan200.computercraft.core.filesystem.FileSystem; | ||||
| import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.core.tracking.TrackingField; | ||||
|  | ||||
| public interface IAPIEnvironment | ||||
| { | ||||
| @@ -42,4 +43,6 @@ public interface IAPIEnvironment | ||||
|  | ||||
|     String getLabel(); | ||||
|     void setLabel( String label ); | ||||
|  | ||||
|     void addTrackingChange( TrackingField field, long change ); | ||||
| } | ||||
|   | ||||
| @@ -20,6 +20,8 @@ import dan200.computercraft.core.filesystem.FileSystemException; | ||||
| import dan200.computercraft.core.lua.CobaltLuaMachine; | ||||
| import dan200.computercraft.core.lua.ILuaMachine; | ||||
| import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.core.tracking.Tracking; | ||||
| import dan200.computercraft.core.tracking.TrackingField; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| @@ -167,6 +169,12 @@ public class Computer | ||||
|             m_computer.setLabel( label ); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void addTrackingChange( TrackingField field, long change ) | ||||
|         { | ||||
|             Tracking.addValue( m_computer, field, change ); | ||||
|         } | ||||
|  | ||||
|         public void onPeripheralChanged( int side, IPeripheral peripheral ) | ||||
|         { | ||||
|             synchronized( m_computer.m_peripherals ) | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| package dan200.computercraft.core.computer; | ||||
|  | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.core.tracking.Tracking; | ||||
|  | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| @@ -233,7 +234,7 @@ public class ComputerThread | ||||
|             { | ||||
|                 long stop = System.nanoTime(); | ||||
|                 Computer computer = task.getOwner(); | ||||
|                 if( computer != null ) ComputerTimeTracker.addTiming( computer, stop - start ); | ||||
|                 if( computer != null ) Tracking.addTiming( computer, stop - start ); | ||||
|                  | ||||
|                 // Re-add it back onto the queue or remove it | ||||
|                 synchronized( s_taskLock ) | ||||
|   | ||||
| @@ -1,116 +0,0 @@ | ||||
| package dan200.computercraft.core.computer; | ||||
|  | ||||
| import com.google.common.collect.MapMaker; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| import java.lang.ref.WeakReference; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * Tracks timing information about computers, including how long they ran for | ||||
|  * and the number of events they handled. | ||||
|  * | ||||
|  * Note that this <em>will</em> track computers which have been deleted (hence | ||||
|  * the presence of {@link #timingLookup} and {@link #timings} | ||||
|  */ | ||||
| public class ComputerTimeTracker | ||||
| { | ||||
|     public static class Timings | ||||
|     { | ||||
|         private final WeakReference<Computer> computer; | ||||
|         private final int computerId; | ||||
|  | ||||
|         private int tasks; | ||||
|  | ||||
|         private long totalTime; | ||||
|         private long maxTime; | ||||
|  | ||||
|         public Timings( @Nonnull Computer computer ) | ||||
|         { | ||||
|             this.computer = new WeakReference<>( computer ); | ||||
|             this.computerId = computer.getID(); | ||||
|         } | ||||
|  | ||||
|         @Nullable | ||||
|         public Computer getComputer() | ||||
|         { | ||||
|             return computer.get(); | ||||
|         } | ||||
|  | ||||
|         public int getComputerId() | ||||
|         { | ||||
|             return computerId; | ||||
|         } | ||||
|  | ||||
|         public int getTasks() | ||||
|         { | ||||
|             return tasks; | ||||
|         } | ||||
|  | ||||
|         public long getTotalTime() | ||||
|         { | ||||
|             return totalTime; | ||||
|         } | ||||
|  | ||||
|         public long getMaxTime() | ||||
|         { | ||||
|             return maxTime; | ||||
|         } | ||||
|  | ||||
|         public double getAverage() | ||||
|         { | ||||
|             return totalTime / (double) tasks; | ||||
|         } | ||||
|  | ||||
|         void update( long time ) | ||||
|         { | ||||
|             tasks++; | ||||
|             totalTime += time; | ||||
|             if( time > maxTime ) maxTime = time; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static boolean tracking; | ||||
|     private static final List<Timings> timings = new ArrayList<>(); | ||||
|     private static final Map<Computer, Timings> timingLookup = new MapMaker().weakKeys().makeMap(); | ||||
|  | ||||
|     public synchronized static void start() | ||||
|     { | ||||
|         tracking = true; | ||||
|  | ||||
|         timings.clear(); | ||||
|         timingLookup.clear(); | ||||
|     } | ||||
|  | ||||
|     public synchronized static boolean stop() | ||||
|     { | ||||
|         if( !tracking ) return false; | ||||
|  | ||||
|         tracking = false; | ||||
|         timingLookup.clear(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public static synchronized List<Timings> getTimings() | ||||
|     { | ||||
|         return new ArrayList<>( timings ); | ||||
|     } | ||||
|  | ||||
|     public static synchronized void addTiming( Computer computer, long time ) | ||||
|     { | ||||
|         if( !tracking ) return; | ||||
|  | ||||
|         Timings timings = ComputerTimeTracker.timingLookup.get( computer ); | ||||
|         if( timings == null ) | ||||
|         { | ||||
|             timings = new Timings( computer ); | ||||
|             timingLookup.put( computer, timings ); | ||||
|             ComputerTimeTracker.timings.add( timings ); | ||||
|         } | ||||
|  | ||||
|         timings.update( time ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,96 @@ | ||||
| package dan200.computercraft.core.tracking; | ||||
|  | ||||
| import dan200.computercraft.core.computer.Computer; | ||||
| import gnu.trove.map.hash.TObjectLongHashMap; | ||||
|  | ||||
| import javax.annotation.Nullable; | ||||
| import java.lang.ref.WeakReference; | ||||
|  | ||||
| public class ComputerTracker | ||||
| { | ||||
|     private final WeakReference<Computer> computer; | ||||
|     private final int computerId; | ||||
|  | ||||
|     private long tasks; | ||||
|     private long totalTime; | ||||
|     private long maxTime; | ||||
|  | ||||
|     private final TObjectLongHashMap<TrackingField> fields; | ||||
|  | ||||
|     public ComputerTracker( Computer computer ) | ||||
|     { | ||||
|         this.computer = new WeakReference<>( computer ); | ||||
|         this.computerId = computer.getID(); | ||||
|         this.fields = new TObjectLongHashMap<>(); | ||||
|     } | ||||
|  | ||||
|     ComputerTracker( ComputerTracker timings ) | ||||
|     { | ||||
|         this.computer = timings.computer; | ||||
|         this.computerId = timings.computerId; | ||||
|  | ||||
|         this.tasks = timings.tasks; | ||||
|         this.totalTime = timings.totalTime; | ||||
|         this.maxTime = timings.maxTime; | ||||
|         this.fields = new TObjectLongHashMap<>( timings.fields ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Nullable | ||||
|     public Computer getComputer() | ||||
|     { | ||||
|         return computer.get(); | ||||
|     } | ||||
|  | ||||
|     public int getComputerId() | ||||
|     { | ||||
|         return computerId; | ||||
|     } | ||||
|  | ||||
|     public long getTasks() | ||||
|     { | ||||
|         return tasks; | ||||
|     } | ||||
|  | ||||
|     public long getTotalTime() | ||||
|     { | ||||
|         return totalTime; | ||||
|     } | ||||
|  | ||||
|     public long getMaxTime() | ||||
|     { | ||||
|         return maxTime; | ||||
|     } | ||||
|  | ||||
|     public long getAverage() | ||||
|     { | ||||
|         return totalTime / tasks; | ||||
|     } | ||||
|  | ||||
|     void addTiming( long time ) | ||||
|     { | ||||
|         tasks++; | ||||
|         totalTime += time; | ||||
|         if( time > maxTime ) maxTime = time; | ||||
|     } | ||||
|  | ||||
|     void addValue( TrackingField field, long change ) | ||||
|     { | ||||
|         fields.adjustOrPutValue( field, change, change ); | ||||
|     } | ||||
|  | ||||
|     public long get( TrackingField field ) | ||||
|     { | ||||
|         if( field == TrackingField.TASKS ) return tasks; | ||||
|         if( field == TrackingField.MAX_TIME ) return maxTime; | ||||
|         if( field == TrackingField.TOTAL_TIME ) return totalTime; | ||||
|         if( field == TrackingField.AVERAGE_TIME ) return totalTime / tasks; | ||||
|  | ||||
|         return fields.get( field ); | ||||
|     } | ||||
|  | ||||
|     public String getFormatted( TrackingField field ) | ||||
|     { | ||||
|         return field.format( get( field ) ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| package dan200.computercraft.core.tracking; | ||||
|  | ||||
| import dan200.computercraft.core.computer.Computer; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
|  | ||||
| public class Tracking | ||||
| { | ||||
|     static final AtomicInteger tracking = new AtomicInteger( 0 ); | ||||
|     private static final HashMap<UUID, TrackingContext> contexts = new HashMap<>(); | ||||
|  | ||||
|     public static TrackingContext getContext( UUID uuid ) | ||||
|     { | ||||
|         synchronized( contexts ) | ||||
|         { | ||||
|             TrackingContext context = contexts.get( uuid ); | ||||
|             if( context == null ) contexts.put( uuid, context = new TrackingContext() ); | ||||
|             return context; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void addTiming( Computer computer, long time ) | ||||
|     { | ||||
|         if( tracking.get() == 0 ) return; | ||||
|  | ||||
|         synchronized( contexts ) | ||||
|         { | ||||
|             for( TrackingContext context : contexts.values() ) context.addTiming( computer, time ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void addValue( Computer computer, TrackingField field, long change ) | ||||
|     { | ||||
|         if( tracking.get() == 0 ) return; | ||||
|  | ||||
|         synchronized( contexts ) | ||||
|         { | ||||
|             for( TrackingContext context : contexts.values() ) context.addValue( computer, field, change ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void reset() | ||||
|     { | ||||
|         synchronized( contexts ) | ||||
|         { | ||||
|             contexts.clear(); | ||||
|             tracking.set( 0 ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,85 @@ | ||||
| package dan200.computercraft.core.tracking; | ||||
|  | ||||
| import com.google.common.collect.MapMaker; | ||||
| import dan200.computercraft.core.computer.Computer; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * Tracks timing information about computers, including how long they ran for | ||||
|  * and the number of events they handled. | ||||
|  * | ||||
|  * Note that this <em>will</em> track computers which have been deleted (hence | ||||
|  * the presence of {@link #timingLookup} and {@link #timings} | ||||
|  */ | ||||
| public class TrackingContext | ||||
| { | ||||
|     private boolean tracking = false; | ||||
|  | ||||
|     private final List<ComputerTracker> timings = new ArrayList<>(); | ||||
|     private final Map<Computer, ComputerTracker> timingLookup = new MapMaker().weakKeys().makeMap(); | ||||
|  | ||||
|     public synchronized void start() | ||||
|     { | ||||
|         if( !tracking ) Tracking.tracking.incrementAndGet(); | ||||
|         tracking = true; | ||||
|  | ||||
|         timings.clear(); | ||||
|         timingLookup.clear(); | ||||
|     } | ||||
|  | ||||
|     public synchronized boolean stop() | ||||
|     { | ||||
|         if( !tracking ) return false; | ||||
|  | ||||
|         Tracking.tracking.decrementAndGet(); | ||||
|         tracking = false; | ||||
|         timingLookup.clear(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public synchronized List<ComputerTracker> getTimings() | ||||
|     { | ||||
|         ArrayList<ComputerTracker> timings = new ArrayList<>( this.timings.size() ); | ||||
|         for( ComputerTracker timing : this.timings ) timings.add( new ComputerTracker( timing ) ); | ||||
|         return timings; | ||||
|     } | ||||
|  | ||||
|     public void addTiming( Computer computer, long time ) | ||||
|     { | ||||
|         if( !tracking ) return; | ||||
|  | ||||
|         synchronized( this ) | ||||
|         { | ||||
|             ComputerTracker computerTimings = timingLookup.get( computer ); | ||||
|             if( computerTimings == null ) | ||||
|             { | ||||
|                 computerTimings = new ComputerTracker( computer ); | ||||
|                 timingLookup.put( computer, computerTimings ); | ||||
|                 timings.add( computerTimings ); | ||||
|             } | ||||
|  | ||||
|             computerTimings.addTiming( time ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public synchronized void addValue( Computer computer, TrackingField field, long change ) | ||||
|     { | ||||
|         if( !tracking ) return; | ||||
|  | ||||
|         synchronized( this ) | ||||
|         { | ||||
|             ComputerTracker computerTimings = timingLookup.get( computer ); | ||||
|             if( computerTimings == null ) | ||||
|             { | ||||
|                 computerTimings = new ComputerTracker( computer ); | ||||
|                 timingLookup.put( computer, computerTimings ); | ||||
|                 timings.add( computerTimings ); | ||||
|             } | ||||
|  | ||||
|             computerTimings.addValue( field, change ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,54 @@ | ||||
| package dan200.computercraft.core.tracking; | ||||
|  | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.function.LongFunction; | ||||
|  | ||||
| public class TrackingField | ||||
| { | ||||
|     private static final Map<String, TrackingField> fields = new HashMap<>(); | ||||
|  | ||||
|     public static final TrackingField TASKS = TrackingField.of( "tasks", "Tasks", x -> String.format( "%4d", x ) ); | ||||
|     public static final TrackingField TOTAL_TIME = TrackingField.of( "total", "Total time", x -> String.format( "%7.1fms", x / 1e6 ) ); | ||||
|     public static final TrackingField AVERAGE_TIME = TrackingField.of( "average", "Average time", x -> String.format( "%4.1fms", x / 1e6 ) ); | ||||
|     public static final TrackingField MAX_TIME = TrackingField.of( "max", "Max time", x -> String.format( "%5.1fms", x / 1e6 ) ); | ||||
|  | ||||
|     private final String id; | ||||
|     private final String displayName; | ||||
|     private final LongFunction<String> format; | ||||
|  | ||||
|     public String id() | ||||
|     { | ||||
|         return id; | ||||
|     } | ||||
|  | ||||
|     public String displayName() | ||||
|     { | ||||
|         return displayName; | ||||
|     } | ||||
|  | ||||
|     private TrackingField( String id, String displayName, LongFunction<String> format ) | ||||
|     { | ||||
|         this.id = id; | ||||
|         this.displayName = displayName; | ||||
|         this.format = format; | ||||
|     } | ||||
|  | ||||
|     public String format( long value ) | ||||
|     { | ||||
|         return format.apply( value ); | ||||
|     } | ||||
|  | ||||
|     public static TrackingField of( String id, String displayName, LongFunction<String> format ) | ||||
|     { | ||||
|         TrackingField field = new TrackingField( id, displayName, format ); | ||||
|         fields.put( id, field ); | ||||
|         return field; | ||||
|     } | ||||
|  | ||||
|     public static Map<String, TrackingField> fields() | ||||
|     { | ||||
|         return Collections.unmodifiableMap( fields ); | ||||
|     } | ||||
| } | ||||
| @@ -4,9 +4,13 @@ import com.google.common.collect.Sets; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.api.peripheral.IPeripheral; | ||||
| import dan200.computercraft.core.computer.Computer; | ||||
| import dan200.computercraft.core.computer.ComputerTimeTracker; | ||||
| import dan200.computercraft.core.tracking.ComputerTracker; | ||||
| import dan200.computercraft.core.tracking.Tracking; | ||||
| import dan200.computercraft.core.tracking.TrackingContext; | ||||
| import dan200.computercraft.core.tracking.TrackingField; | ||||
| import dan200.computercraft.shared.command.framework.*; | ||||
| import dan200.computercraft.shared.computer.core.ServerComputer; | ||||
| import net.minecraft.command.CommandBase; | ||||
| import net.minecraft.command.CommandException; | ||||
| import net.minecraft.command.ICommandSender; | ||||
| import net.minecraft.entity.Entity; | ||||
| @@ -25,6 +29,8 @@ import static dan200.computercraft.shared.command.framework.ChatHelpers.*; | ||||
|  | ||||
| public final class CommandComputerCraft extends CommandDelegate | ||||
| { | ||||
|     public static final UUID SYSTEM_UUID = new UUID( 0, 0 ); | ||||
|  | ||||
|     public CommandComputerCraft() | ||||
|     { | ||||
|         super( create() ); | ||||
| @@ -311,7 +317,7 @@ public final class CommandComputerCraft extends CommandDelegate | ||||
|             @Override | ||||
|             public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) | ||||
|             { | ||||
|                 ComputerTimeTracker.start(); | ||||
|                 getTimingContext( context ).start(); | ||||
|  | ||||
|                 String stopCommand = "/" + context.parent().getFullPath() + " stop"; | ||||
|                 context.getSender().sendMessage( list( | ||||
| @@ -330,20 +336,51 @@ public final class CommandComputerCraft extends CommandDelegate | ||||
|             @Override | ||||
|             public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) throws CommandException | ||||
|             { | ||||
|                 if( !ComputerTimeTracker.stop() ) throw new CommandException( "Tracking not enabled" ); | ||||
|                 displayTimings( context ); | ||||
|                 TrackingContext timings = getTimingContext( context ); | ||||
|                 if( !timings.stop() ) throw new CommandException( "Tracking not enabled" ); | ||||
|                 displayTimings( context, timings.getTimings(), TrackingField.AVERAGE_TIME ); | ||||
|             } | ||||
|         } ); | ||||
|  | ||||
|         track.register( new SubCommandBase( | ||||
|             "dump", "Dump the latest track results", UserLevel.OWNER_OP, | ||||
|             "dump", "[kind]", "Dump the latest track results", UserLevel.OWNER_OP, | ||||
|             "Dump the latest results of computer tracking." | ||||
|         ) | ||||
|         { | ||||
|             @Override | ||||
|             public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) throws CommandException | ||||
|             { | ||||
|                 displayTimings( context ); | ||||
|                 TrackingField field = TrackingField.AVERAGE_TIME; | ||||
|                 if( arguments.size() >= 1 ) | ||||
|                 { | ||||
|                     field = TrackingField.fields().get( arguments.get( 0 ) ); | ||||
|                     if( field == null ) throw new CommandException( "Unknown field '" + arguments.get( 0 ) + "'" ); | ||||
|                 } | ||||
|  | ||||
|                 displayTimings( context, getTimingContext( context ).getTimings(), field ); | ||||
|             } | ||||
|  | ||||
|             @Nonnull | ||||
|             @Override | ||||
|             public List<String> getCompletion( @Nonnull CommandContext context, @Nonnull List<String> arguments ) | ||||
|             { | ||||
|                 if( arguments.size() == 1 ) | ||||
|                 { | ||||
|                     String match = arguments.get( 0 ); | ||||
|  | ||||
|                     List<String> out = new ArrayList<>(); | ||||
|                     for( String key : TrackingField.fields().keySet() ) | ||||
|                     { | ||||
|                         if( CommandBase.doesStringStartWith( match, key ) ) out.add( key ); | ||||
|                     } | ||||
|  | ||||
|                     out.sort( Comparator.naturalOrder() ); | ||||
|                     return out; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     return super.getCompletion( context, arguments ); | ||||
|                 } | ||||
|             } | ||||
|         } ); | ||||
|  | ||||
| @@ -390,13 +427,22 @@ public final class CommandComputerCraft extends CommandDelegate | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void displayTimings( CommandContext context ) throws CommandException | ||||
|     private static TrackingContext getTimingContext( CommandContext context ) | ||||
|     { | ||||
|         List<ComputerTimeTracker.Timings> timings = ComputerTimeTracker.getTimings(); | ||||
|         if( timings.isEmpty() ) throw new CommandException( "No timings available" ); | ||||
|         Entity entity = context.getSender().getCommandSenderEntity(); | ||||
|         if( entity instanceof EntityPlayerMP ) | ||||
|         { | ||||
|             return Tracking.getContext( entity.getUniqueID() ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return Tracking.getContext( SYSTEM_UUID ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         timings.sort( Comparator.comparing( ComputerTimeTracker.Timings::getAverage ).reversed() ); | ||||
|         TextTable table = new TextTable( "Computer", "Tasks", "Total", "Average", "Maximum" ); | ||||
|     private static void displayTimings( CommandContext context, List<ComputerTracker> timings, TrackingField field ) throws CommandException | ||||
|     { | ||||
|         if( timings.isEmpty() ) throw new CommandException( "No timings available" ); | ||||
|  | ||||
|         Map<Computer, ServerComputer> lookup = new HashMap<>(); | ||||
|         int maxId = 0, maxInstance = 0; | ||||
| @@ -411,7 +457,17 @@ public final class CommandComputerCraft extends CommandDelegate | ||||
|         ICommandSender sender = context.getSender(); | ||||
|         boolean isPlayer = sender instanceof EntityPlayerMP && !(sender instanceof FakePlayer); | ||||
|  | ||||
|         for( ComputerTimeTracker.Timings entry : timings ) | ||||
|         timings.sort( Comparator.<ComputerTracker, Long>comparing( x -> x.get( field ) ).reversed() ); | ||||
|  | ||||
|         boolean defaultLayout = field == TrackingField.TASKS || field == TrackingField.TOTAL_TIME | ||||
|             || field == TrackingField.AVERAGE_TIME || field == TrackingField.MAX_TIME; | ||||
|  | ||||
|  | ||||
|         TextTable table = defaultLayout | ||||
|             ? new TextTable( "Computer", "Tasks", "Total", "Average", "Maximum" ) | ||||
|             : new TextTable( "Computer", field.displayName() ); | ||||
|  | ||||
|         for( ComputerTracker entry : timings ) | ||||
|         { | ||||
|             Computer computer = entry.getComputer(); | ||||
|             ServerComputer serverComputer = computer == null ? null : lookup.get( computer ); | ||||
| @@ -437,14 +493,21 @@ public final class CommandComputerCraft extends CommandDelegate | ||||
|                     ) ); | ||||
|             } | ||||
|  | ||||
|             if( defaultLayout ) | ||||
|             { | ||||
|                 table.addRow( | ||||
|                     computerComponent, | ||||
|                 formatted( "%4d", entry.getTasks() ), | ||||
|                 text( String.format( "%7.1f", entry.getTotalTime() / 1e6 ) + "ms" ), | ||||
|                 text( String.format( "%4.1f", entry.getAverage() / 1e6 ) + "ms" ), | ||||
|                 text( String.format( "%5.1f", entry.getMaxTime() / 1e6 ) + "ms" ) | ||||
|                     text( entry.getFormatted( TrackingField.TASKS ) ), | ||||
|                     text( entry.getFormatted( TrackingField.TOTAL_TIME ) ), | ||||
|                     text( entry.getFormatted( TrackingField.AVERAGE_TIME ) ), | ||||
|                     text( entry.getFormatted( TrackingField.MAX_TIME ) ) | ||||
|                 ); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 table.addRow( computerComponent, text( entry.getFormatted( field ) ) ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         table.displayTo( context.getSender() ); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 SquidDev
					SquidDev