11package com .sunekaer .toolkit .commands .level ;
22
3+ import com .mojang .brigadier .arguments .BoolArgumentType ;
34import com .mojang .brigadier .arguments .IntegerArgumentType ;
45import com .mojang .brigadier .arguments .StringArgumentType ;
56import com .mojang .brigadier .builder .ArgumentBuilder ;
67import com .mojang .brigadier .exceptions .CommandSyntaxException ;
78import com .sunekaer .toolkit .ToolkitPlatform ;
89import com .sunekaer .toolkit .jobs .ServerTickJobRunner ;
910import com .sunekaer .toolkit .utils .ChunkRangeIterator ;
11+ import net .minecraft .commands .CommandBuildContext ;
1012import net .minecraft .commands .CommandSourceStack ;
1113import net .minecraft .commands .Commands ;
1214import net .minecraft .commands .SharedSuggestionProvider ;
15+ import net .minecraft .commands .arguments .blocks .BlockPredicateArgument ;
1316import net .minecraft .core .BlockPos ;
14- import net .minecraft .core .Registry ;
1517import net .minecraft .core .registries .BuiltInRegistries ;
16- import net .minecraft .core .registries .Registries ;
1718import net .minecraft .network .chat .Component ;
18- import net .minecraft .resources .ResourceLocation ;
1919import net .minecraft .server .level .ServerLevel ;
20- import net .minecraft .tags .TagKey ;
2120import net .minecraft .world .level .ChunkPos ;
2221import net .minecraft .world .level .block .Block ;
2322import net .minecraft .world .level .block .Blocks ;
2423import net .minecraft .world .level .block .state .BlockState ;
24+ import net .minecraft .world .level .block .state .pattern .BlockInWorld ;
2525
2626import java .util .*;
2727import java .util .concurrent .ExecutorService ;
@@ -33,43 +33,73 @@ public class ClearCommand {
3333 private static final AtomicBoolean COMPLETED = new AtomicBoolean (true );
3434 public static final ExecutorService EXECUTOR = Executors .newSingleThreadExecutor ();
3535
36- public static ArgumentBuilder <CommandSourceStack , ?> register () {
36+ public static ArgumentBuilder <CommandSourceStack , ?> register (CommandBuildContext commandBuildContext ) {
3737 return (Commands .literal ("clear" )
3838 .requires (cs -> cs .hasPermission (2 ))
39- .executes (context -> remove (context .getSource (), 1 , RemovalPredicate .NAMES [0 ]))
40- .then (Commands .argument ("range" , IntegerArgumentType .integer ()).executes (ctx -> remove (ctx .getSource (), IntegerArgumentType .getInteger (ctx , "range" ), RemovalPredicate .NAMES [0 ]))
41- .then (Commands .argument ("filter" , StringArgumentType .string ()).suggests ((commandContext , suggestionsBuilder ) -> SharedSuggestionProvider .suggest (RemovalPredicate .NAMES , suggestionsBuilder )).executes (ctx -> remove (ctx .getSource (), IntegerArgumentType .getInteger (ctx , "range" ), StringArgumentType .getString (ctx , "filter" ))))));
39+ .executes (context -> remove (context .getSource (), 1 , RemovalPredicate .NAMES [0 ], false ))
40+ .then (Commands .argument ("range" , IntegerArgumentType .integer ())
41+ .executes (ctx -> remove (ctx .getSource (), IntegerArgumentType .getInteger (ctx , "range" ), RemovalPredicate .NAMES [0 ], false ))
42+ .then (Commands .argument ("filter" , StringArgumentType .string ())
43+ .suggests ((commandContext , suggestionsBuilder ) -> SharedSuggestionProvider .suggest (RemovalPredicate .NAMES , suggestionsBuilder ))
44+ .executes (ctx -> remove (ctx .getSource (), IntegerArgumentType .getInteger (ctx , "range" ), StringArgumentType .getString (ctx , "filter" ), false ))
45+ .then (Commands .argument ("removes_bedrock" , BoolArgumentType .bool ())
46+ .executes (ctx -> remove (ctx .getSource (), IntegerArgumentType .getInteger (ctx , "range" ), StringArgumentType .getString (ctx , "filter" ), BoolArgumentType .getBool (ctx , "removes_bedrock" )))
47+ )
48+ )
49+ .then (Commands .literal ("custom_filter" )
50+ .then (Commands .argument ("block" , BlockPredicateArgument .blockPredicate (commandBuildContext ))
51+ .executes (ctx -> remove (ctx .getSource (), IntegerArgumentType .getInteger (ctx , "range" ), BlockPredicateArgument .getBlockPredicate (ctx , "block" )))
52+ )
53+ )
54+ )
55+ );
4256 }
4357
44- private static int remove (CommandSourceStack source , int size , String filter ) throws CommandSyntaxException {
58+ private static int remove (CommandSourceStack source , int size , String filter , boolean removesBedrock ) throws CommandSyntaxException {
59+ _remove (new RemoveContext (
60+ source ,
61+ size ,
62+ RemovalPredicate .getFromName (filter ).orElse (RemovalPredicate .JUST_ORES ).stateCheck ,
63+ removesBedrock
64+ ));
65+
66+ return 1 ;
67+ }
68+
69+ private static int remove (CommandSourceStack source , int size , Predicate <BlockInWorld > blockCheck ) throws CommandSyntaxException {
70+ _remove (new RemoveContext (
71+ source ,
72+ size ,
73+ blockCheck ,
74+ false
75+ ));
76+
77+ return 1 ;
78+ }
79+
80+ private static void _remove (RemoveContext context ) throws CommandSyntaxException {
81+ var source = context .commandStack ;
82+
4583 // Block running
4684 if (!COMPLETED .get ()) {
4785 source .sendFailure (Component .literal ("Already running, give it a second." ));
48- return 1 ;
86+ return ;
4987 }
5088
5189 COMPLETED .set (false );
5290 var player = source .getPlayerOrException ();
5391
5492 // Resolve the predicate check, we're lazy, so we'll get the enum regardless but if the filter looks like a
5593 // tag then lets try a tag instead
56- var removalCheck = RemovalPredicate .getFromName (filter ).orElse (RemovalPredicate .JUST_ORES );
57- Predicate <BlockState > customCheck = null ;
58- if (filter .startsWith ("#" )) {
59- customCheck = state -> state .is (TagKey .create (Registries .BLOCK , ResourceLocation .withDefaultNamespace (filter .replace ("#" , "" ))));
60- } else if (filter .contains (":" )) {
61- customCheck = state -> BuiltInRegistries .BLOCK .getKey (state .getBlock ()).toString ().equalsIgnoreCase (filter );
62- }
94+ var removalCheck = context .filter ;
6395
6496 ServerLevel level = source .getLevel ();
6597 source .sendSuccess (() -> Component .translatable ("commands.toolkit.remove.lagwarring" ), true );
6698
6799 // We're removing 1 to make it so 1 = 0, 2 - 1, etc, this means we'll have correct radius 0 = 1x1, 1 = 3x3, 2 = 5x5
68- var range = size - 1 ;
100+ var range = context . size - 1 ;
69101 var chunkPos = player .chunkPosition ();
70102
71- // Compute the max height for the wall and queue the chunk removal
72- Predicate <BlockState > finalCustomCheck = customCheck ;
73103 COMPLETED .set (false );
74104
75105 for (int x = chunkPos .x - range ; x <= chunkPos .x + range ; x ++) {
@@ -79,7 +109,7 @@ private static int remove(CommandSourceStack source, int size, String filter) th
79109 final boolean shouldComplete = x == chunkPos .x + range && z == chunkPos .z + range ;
80110
81111 ServerTickJobRunner .get ().add (() -> {
82- removeChunk (level , currentChunkPos , finalCustomCheck != null ? finalCustomCheck : removalCheck . stateCheck );
112+ removeChunk (level , currentChunkPos , removalCheck , context . removesBedrock );
83113
84114 // If this is the last chunk, then we're done
85115 if (shouldComplete ) {
@@ -88,8 +118,6 @@ private static int remove(CommandSourceStack source, int size, String filter) th
88118 });
89119 }
90120 }
91-
92- return 1 ;
93121 }
94122
95123 /**
@@ -99,29 +127,29 @@ private static int remove(CommandSourceStack source, int size, String filter) th
99127 * @param chunkPos the chunk to remove
100128 * @param blockCheck the predicate that defines what blocks are removed
101129 */
102- private static void removeChunk (ServerLevel level , ChunkPos chunkPos , Predicate <BlockState > blockCheck ) {
130+ private static void removeChunk (ServerLevel level , ChunkPos chunkPos , Predicate <BlockInWorld > blockCheck , boolean removeBedrock ) {
103131 BlockState airState = Blocks .AIR .defaultBlockState ();
104132
105133 ChunkRangeIterator iterator = new ChunkRangeIterator (level , chunkPos , 1 , true );
106134 List <BlockPos > updatedBlocks = new ArrayList <>();
107135
108- int maxHeight = level .dimension () == ServerLevel .NETHER ? 127 : level .getMaxBuildHeight ();
109-
136+ int maxHeight = level .dimension () == ServerLevel .NETHER ? 127 : level .getMaxY ();
110137 while (iterator .hasNext ()) {
111138 BlockPos pos = iterator .next ();
112139 final BlockState state = level .getBlockState (pos );
113140
114141 // Don't remove bedrock and skip air, it's a waste of computation
115- if (state .isAir () || state .getBlock () == Blocks .BEDROCK ) {
116- if (!state .isAir () && pos .getY () > level .getMinBuildHeight () && pos .getY () < maxHeight ) {
142+ if (state .isAir () || (! removeBedrock && state .getBlock () == Blocks .BEDROCK ) ) {
143+ if (!state .isAir () && pos .getY () > level .getMinY () && pos .getY () < maxHeight ) {
117144 level .setBlock (pos , airState , Block .UPDATE_CLIENTS );
118145 updatedBlocks .add (pos );
119146 }
120147
121148 continue ;
122149 }
123150
124- if (blockCheck .test (state )) {
151+ var blockInWorld = new BlockInWorld (level , pos , true );
152+ if (!blockCheck .test (blockInWorld )) {
125153 continue ;
126154 }
127155
@@ -135,20 +163,27 @@ private static void removeChunk(ServerLevel level, ChunkPos chunkPos, Predicate<
135163 }
136164
137165 private enum RemovalPredicate {
138- JUST_ORES (state -> state .is (ToolkitPlatform .getOresTag ())),
139- ORES_AND_MODDED (state -> state .is (ToolkitPlatform .getOresTag ()) && BuiltInRegistries .BLOCK .getKey (state .getBlock ()).getNamespace ().equals ("minecraft" ));
166+ JUST_ORES (state -> ! state . getState () .is (ToolkitPlatform .getOresTag ())),
167+ ORES_AND_MODDED (state -> ! state .getState (). is (ToolkitPlatform .getOresTag ()) || ! BuiltInRegistries .BLOCK .getKey (state . getState () .getBlock ()).getNamespace ().equals ("minecraft" ));
140168
141169 public static final List <RemovalPredicate > VALUES = Arrays .asList (values ());
142170 public static final String [] NAMES = VALUES .stream ().map (e -> e .toString ().toLowerCase ()).toArray (String []::new );
143171
144- final Predicate <BlockState > stateCheck ;
145- RemovalPredicate (Predicate <BlockState > stateCheck ) {
172+ final Predicate <BlockInWorld > stateCheck ;
173+ RemovalPredicate (Predicate <BlockInWorld > stateCheck ) {
146174 this .stateCheck = stateCheck ;
147175 }
148176
149177 public static Optional <RemovalPredicate > getFromName (String name ) {
150178 return VALUES .stream ().filter (e -> e .toString ().toLowerCase ().equals (name )).findFirst ();
151179 }
152180 }
181+
182+ private record RemoveContext (
183+ CommandSourceStack commandStack ,
184+ int size ,
185+ Predicate <BlockInWorld > filter ,
186+ boolean removesBedrock
187+ ) {}
153188}
154189
0 commit comments