44import net .minecraft .command .*;
55import net .minecraft .server .function .Tracer ;
66import net .minecraft .util .profiler .Profiler ;
7+ import org .jetbrains .annotations .NotNull ;
78import org .slf4j .Logger ;
9+ import org .spongepowered .asm .mixin .Final ;
810import org .spongepowered .asm .mixin .Mixin ;
911import org .spongepowered .asm .mixin .Shadow ;
1012import org .spongepowered .asm .mixin .Unique ;
1113import org .spongepowered .asm .mixin .injection .At ;
1214import org .spongepowered .asm .mixin .injection .Inject ;
1315import org .spongepowered .asm .mixin .injection .callback .CallbackInfo ;
1416import top .mcfpp .mod .breakpoint .DatapackBreakpoint ;
17+ import top .mcfpp .mod .breakpoint .command .BreakPointCommand ;
1518
19+ import java .lang .reflect .Field ;
1620import java .util .Deque ;
1721import java .util .List ;
22+ import java .util .Objects ;
1823
1924import static top .mcfpp .mod .breakpoint .command .BreakPointCommand .*;
2025
@@ -24,25 +29,25 @@ abstract public class CommandExecutionContextMixin<T> {
2429 @ Unique
2530 private final Deque <CommandQueueEntry <T >> storedCommandQueue = Queues .newArrayDeque ();
2631
27- @ Shadow private static int MAX_COMMAND_QUEUE_LENGTH ;
28- @ Shadow private static Logger LOGGER ;
29- @ Shadow private int maxCommandChainLength ;
30- @ Shadow private int forkLimit ;
31- @ Shadow private Profiler profiler ;
32+ @ Shadow @ Final private static int MAX_COMMAND_QUEUE_LENGTH ;
33+ @ Shadow @ Final private static Logger LOGGER ;
34+ @ Shadow @ Final private int maxCommandChainLength ;
35+ @ Shadow @ Final private int forkLimit ;
36+ @ Shadow @ Final private Profiler profiler ;
3237 @ Shadow private Tracer tracer ;
3338 @ Shadow private int commandsRemaining ;
3439 @ Shadow private boolean queueOverflowed ;
35- @ Shadow private Deque <CommandQueueEntry <T >> commandQueue ;
36- @ Shadow private List <CommandQueueEntry <T >> pendingCommands ;
40+ @ Shadow @ Final private Deque <CommandQueueEntry <T >> commandQueue ;
41+ @ Shadow @ Final private List <CommandQueueEntry <T >> pendingCommands ;
3742 @ Shadow private int currentDepth ;
38- @ Shadow abstract void queuePendingCommands ();
43+ @ Shadow protected abstract void queuePendingCommands ();
3944
4045 @ Shadow public abstract void enqueueCommand (CommandQueueEntry <T > entry );
4146
4247 @ Inject (method = "run()V" , at = @ At ("HEAD" ), cancellable = true )
4348 private void onRun (CallbackInfo ci ){
4449
45- final var THIS = (CommandExecutionContext <? >) (Object ) this ;
50+ final var THIS = (CommandExecutionContext <T >) (Object ) this ;
4651
4752 this .queuePendingCommands ();
4853
@@ -53,26 +58,26 @@ private void onRun(CallbackInfo ci){
5358 }
5459
5560 CommandQueueEntry <T > commandQueueEntry = this .commandQueue .pollFirst ();
61+
5662 if (commandQueueEntry == null ) {
5763 ci .cancel ();
5864 return ;
5965 }
6066
61- if (INSTANCE .isDebugging () && commandQueueEntry .frame ().depth () != 0 && INSTANCE .getMoveSteps () == 0 ) {
62- //在函数中执行的,把所有命令暂存
63- if (INSTANCE .getStoredCommandExecutionContext ().peekFirst () != THIS ) {
64- INSTANCE .getStoredCommandExecutionContext ().addFirst (THIS );
67+ LOGGER .info ("Method run()V is injected!" );
68+
69+ if (isDebugging && commandQueueEntry .frame ().depth () != 0 && moveSteps == 0 ) {
70+ //在函数中执行的,把命令暂存
71+ commandQueue .addFirst (commandQueueEntry );
72+ if (storedCommandExecutionContext .peekFirst () != THIS ) {
73+ storedCommandExecutionContext .addFirst (THIS );
6574 }
6675 ci .cancel ();
6776 return ;
6877 }
6978
70- if (commandQueueEntry .action () instanceof FixedCommandAction <?>){
71- INSTANCE .setMoveSteps (INSTANCE .getMoveSteps () - 1 );
72- }
73-
7479 this .currentDepth = commandQueueEntry .frame ().depth ();
75- commandQueueEntry .execute (( CommandExecutionContext )( Object ) this );
80+ commandQueueEntry .execute (THIS );
7681 if (this .queueOverflowed ) {
7782 LOGGER .error ("Command execution stopped due to command queue overflow (max {})" , 10000000 );
7883 break ;
@@ -87,4 +92,67 @@ private void onRun(CallbackInfo ci){
8792 ci .cancel ();
8893 }
8994
95+ @ Unique
96+ private void onStep (){
97+
98+ final var THIS = (CommandExecutionContext <T >) (Object ) this ;
99+
100+ this .queuePendingCommands ();
101+
102+ while (true ) {
103+ if (this .commandsRemaining <= 0 ) {
104+ LOGGER .info ("Command execution stopped due to limit (executed {} commands)" , this .maxCommandChainLength );
105+ break ;
106+ }
107+
108+ CommandQueueEntry <T > commandQueueEntry = this .commandQueue .pollFirst ();
109+
110+ if (commandQueueEntry == null ) {
111+ return ;
112+ }
113+
114+ LOGGER .info ("Method run()V is injected!" );
115+
116+ if (isDebugging && commandQueueEntry .frame ().depth () != 0 && moveSteps == 0 ) {
117+ //在函数中执行的,把所有命令暂存
118+ commandQueue .addFirst (commandQueueEntry );
119+ if (storedCommandExecutionContext .peekFirst () != THIS ) {
120+ storedCommandExecutionContext .addFirst (THIS );
121+ }
122+ return ;
123+ }
124+
125+ this .currentDepth = commandQueueEntry .frame ().depth ();
126+ commandQueueEntry .execute (THIS );
127+ if (this .queueOverflowed ) {
128+ LOGGER .error ("Command execution stopped due to command queue overflow (max {})" , 10000000 );
129+ break ;
130+ }
131+
132+ this .queuePendingCommands ();
133+ }
134+
135+ this .currentDepth = 0 ;
136+ }
137+
138+ @ Unique
139+ private boolean isFixCommandAction (@ NotNull CommandAction <T > action ){
140+ if (!(action instanceof SourcedCommandAction )) return false ;
141+ try {
142+ Class <?> actionClass = action .getClass ();
143+ Field [] fields = actionClass .getDeclaredFields ();
144+
145+ for (Field field : fields ) {
146+ field .setAccessible (true );
147+ Object fieldValue = field .get (action );
148+ if (fieldValue instanceof FixedCommandAction ) {
149+ return true ;
150+ }
151+ }
152+ } catch (IllegalAccessException e ) {
153+ e .printStackTrace ();
154+ }
155+ return false ;
156+ }
157+
90158}
0 commit comments