Skip to content

Commit

Permalink
Better bulk block add using wildcards (fr1kin#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
fr1kin committed Aug 5, 2021
1 parent ddd237c commit 3161eb5
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 28 deletions.
18 changes: 17 additions & 1 deletion src/main/java/dev/fiki/forgehax/api/BlockHelper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.fiki.forgehax.api;

import com.google.common.collect.Lists;
import dev.fiki.forgehax.api.extension.GeneralEx;
import dev.fiki.forgehax.api.extension.LocalPlayerEx;
import dev.fiki.forgehax.api.math.VectorUtil;
import lombok.AllArgsConstructor;
Expand All @@ -22,13 +23,15 @@
import net.minecraft.util.math.vector.Vector3d;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static dev.fiki.forgehax.main.Common.getLocalPlayer;
import static dev.fiki.forgehax.main.Common.getWorld;

public class BlockHelper {

@Deprecated
public static UniqueBlock newUniqueBlock(Block block, int metadata, BlockPos pos) {
throw new UnsupportedOperationException();
Expand All @@ -43,6 +46,19 @@ public static UniqueBlock newUniqueBlock(BlockPos pos) {
return new UniqueBlock(getWorld().getBlockState(pos).getBlock(), pos);
}

public static Set<Block> getBlocksMatching(Iterable<Block> blocks, String match) {
final Pattern pattern = Pattern.compile(GeneralEx.globToRegex(match), Pattern.CASE_INSENSITIVE);
return StreamSupport.stream(blocks.spliterator(), false)
.filter(block -> block != Blocks.AIR)
.filter(block -> block.getRegistryName() != null)
.filter(block -> pattern.matcher(getBlockRegistryName(block)).matches())
.collect(Collectors.toSet());
}

public static String getBlockRegistryName(Block block) {
return block.getRegistryName().toString();
}

public static BlockTraceInfo newBlockTrace(BlockPos pos, Direction side) {
return new BlockTraceInfo(pos, side);
}
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/dev/fiki/forgehax/api/cmd/AbstractSettingMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ protected String printableValue(V o) {
return String.valueOf(o);
}

@Override
public boolean removeKeys(Collection<? extends K> collection) {
int beforeSize = size();
collection.forEach(wrapping::remove);
if (beforeSize != size()) {
callUpdateListeners();
return true;
}
return false;
}

@Override
public int size() {
return wrapping.size();
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/dev/fiki/forgehax/api/cmd/ISettingMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import dev.fiki.forgehax.api.serialization.IJsonSerializable;

import java.util.Collection;
import java.util.Map;

public interface ISettingMap<K, V, M extends Map<K, V>> extends IParentCommand, IJsonSerializable, Map<K, V> {

boolean removeKeys(Collection<? extends K> collection);
}
45 changes: 45 additions & 0 deletions src/main/java/dev/fiki/forgehax/api/extension/GeneralEx.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,49 @@ public static float clamp(float value, float min, float max) {
public static double scale(double x, double from_min, double from_max, double to_min, double to_max) {
return to_min + (to_max - to_min) * ((x - from_min) / (from_max - from_min));
}

public static String globToRegex(String glob) {
StringBuilder builder = new StringBuilder("^");

boolean literal = false;
for (int i = 0; i < glob.length(); i++) {
char at = glob.charAt(i);
switch (at) {
case '*':
case '?':
// this is an expression, end literal if started
if (literal) {
builder.append("\\E");
literal = false;
}
// nasty
switch (at) {
case '*':
// do not allow repeated wildcards
if (i - 1 < 0 || glob.charAt(i - 1) != '*') {
// * = match any multiple characters
builder.append(".*");
}
break;
case '?':
// ? = match any single character
builder.append('.');
}
break;
default:
if (!literal) {
builder.append("\\Q");
literal = true;
}
builder.append(at);
}
}

// end literal if started
if (literal) {
builder.append("\\E");
}

return builder.append("$").toString();
}
}
13 changes: 3 additions & 10 deletions src/main/java/dev/fiki/forgehax/main/commands/BlocksCommand.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package dev.fiki.forgehax.main.commands;

import dev.fiki.forgehax.api.BlockHelper;
import dev.fiki.forgehax.api.cmd.argument.Arguments;
import dev.fiki.forgehax.api.mod.CommandMod;
import dev.fiki.forgehax.api.modloader.RegisterMod;
import net.minecraft.block.Block;
import net.minecraft.util.ResourceLocation;

import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static dev.fiki.forgehax.main.Common.getBlockRegistry;

Expand All @@ -17,7 +14,6 @@
*/
@RegisterMod
public class BlocksCommand extends CommandMod {

{
newSimpleCommand()
.name("blocks")
Expand All @@ -28,11 +24,8 @@ public class BlocksCommand extends CommandMod {
.executor(args -> {
String find = args.getFirst().getStringValue();

args.inform(StreamSupport.stream(getBlockRegistry().spliterator(), false)
.map(Block::getRegistryName)
.filter(Objects::nonNull)
.map(ResourceLocation::toString)
.filter(block -> block.toLowerCase().contains(find))
args.inform(BlockHelper.getBlocksMatching(getBlockRegistry(), find).stream()
.map(BlockHelper::getBlockRegistryName)
.limit(25)
.collect(Collectors.joining(", ")));
})
Expand Down
57 changes: 41 additions & 16 deletions src/main/java/dev/fiki/forgehax/main/mods/world/Markers.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.collect.Maps;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.fiki.forgehax.api.BlockHelper;
import dev.fiki.forgehax.api.asm.MapField;
import dev.fiki.forgehax.api.cmd.argument.Arguments;
import dev.fiki.forgehax.api.cmd.listener.Listeners;
Expand All @@ -26,14 +27,12 @@
import dev.fiki.forgehax.main.Common;
import lombok.RequiredArgsConstructor;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.client.renderer.ViewFrustum;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexBuffer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d;
Expand All @@ -42,7 +41,6 @@
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static dev.fiki.forgehax.main.Common.*;

Expand Down Expand Up @@ -85,8 +83,10 @@ public class Markers extends ToggleMod implements Common {

{
blocks.newSimpleCommand()
.name("bulk-add")
.description("Add all matching a given string.")
.name("match-add")
.alias("madd")
.alias("bulk-add")
.description("Add all matching a given string. Use ? to match exactly 1 character, and * to match 0 or more")
.argument(Arguments.newStringArgument()
.label("search blocks")
.maxArgumentsConsumed(1)
Expand All @@ -98,25 +98,50 @@ public class Markers extends ToggleMod implements Common {
.build())
.executor(args -> {
final String searchString = args.<String>getFirst().getValue();
final String lower = searchString.toLowerCase();
final Color color = args.<Color>getSecond().getValue();

Set<Block> blocks = StreamSupport.stream(getBlockRegistry().spliterator(), false)
.filter(block -> Blocks.AIR != block)
.filter(block -> block.getRegistryName() != null)
.filter(block -> block.getRegistryName().toString().toLowerCase().contains(lower))
.collect(Collectors.toSet());
final Set<Block> blocks = BlockHelper.getBlocksMatching(getBlockRegistry(), searchString);

if (blocks.isEmpty()) {
args.warn("Found no blocks matching name %s", searchString);
args.warn("Found no blocks matching %s.", searchString);
if (!searchString.contains(":")) {
args.warn("Did you mean \"minecraft:%s\"?", searchString);
}
} else {
args.inform("Adding blocks %s with color %s",
blocks.stream()
.map(Block::getRegistryName)
.map(ResourceLocation::toString)
.map(BlockHelper::getBlockRegistryName)
.collect(Collectors.joining(", ")),
args.getSecond().getStringValue());
blocks.forEach(block -> this.blocks.put(block, color));
this.blocks.putAll(blocks.stream()
.collect(Collectors.toMap(block -> block, block -> color)));
}
})
.build();

blocks.newSimpleCommand()
.name("match-remove")
.alias("mremove")
.alias("mdelete")
.alias("bulk-remove")
.description("Remove all matching a given string. Use ? to match exactly 1 character, and * to match 0 or more")
.argument(Arguments.newStringArgument()
.label("search blocks")
.maxArgumentsConsumed(1)
.build())
.executor(args -> {
final String searchString = args.<String>getFirst().getValue();
final Set<Block> blocks = BlockHelper.getBlocksMatching(this.blocks.keySet(), searchString);

if (blocks.isEmpty()) {
args.warn("Found no blocks matching %s", searchString);
if (!searchString.contains(":")) {
args.warn("Did you mean \"minecraft:%s\"?", searchString);
}
} else {
args.inform("Removing blocks %s", blocks.stream()
.map(BlockHelper::getBlockRegistryName)
.collect(Collectors.joining(", ")));
this.blocks.removeKeys(blocks);
}
})
.build();
Expand Down
62 changes: 62 additions & 0 deletions src/main/java/dev/fiki/forgehax/main/mods/world/XrayMod.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.fiki.forgehax.main.mods.world;

import com.google.common.collect.Sets;
import dev.fiki.forgehax.api.BlockHelper;
import dev.fiki.forgehax.api.cmd.argument.Arguments;
import dev.fiki.forgehax.api.cmd.flag.EnumFlag;
import dev.fiki.forgehax.api.cmd.listener.Listeners;
Expand All @@ -13,9 +14,13 @@
import dev.fiki.forgehax.api.modloader.RegisterMod;
import dev.fiki.forgehax.asm.events.render.CullCavesEvent;
import dev.fiki.forgehax.asm.hooks.XrayHooks;
import dev.fiki.forgehax.main.Common;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;

import java.util.Set;
import java.util.stream.Collectors;

import static dev.fiki.forgehax.main.Common.isInWorld;
import static dev.fiki.forgehax.main.Common.reloadChunkSmooth;

Expand Down Expand Up @@ -60,6 +65,63 @@ public class XrayMod extends ToggleMod {
}))
.build();

{
blocks.newSimpleCommand()
.name("match-add")
.alias("madd")
.alias("bulk-add")
.description("Add all matching a given string. Use ? to match exactly 1 character, and * to match 0 or more")
.argument(Arguments.newStringArgument()
.label("search blocks")
.maxArgumentsConsumed(1)
.build())
.executor(args -> {
final String searchString = args.<String>getFirst().getValue();
final Set<Block> blocks = BlockHelper.getBlocksMatching(Common.getBlockRegistry(), searchString);

if (blocks.isEmpty()) {
args.warn("Found no blocks matching %s.", searchString);
if (!searchString.contains(":")) {
args.warn("Did you mean \"minecraft:%s\"?", searchString);
}
} else {
args.inform("Adding blocks %s", blocks.stream()
.map(BlockHelper::getBlockRegistryName)
.collect(Collectors.joining(", ")));
this.blocks.addAll(blocks);
}
})
.build();

blocks.newSimpleCommand()
.name("match-remove")
.alias("mremove")
.alias("mdelete")
.alias("bulk-remove")
.description("Remove all matching a given string. Use ? to match exactly 1 character, and * to match 0 or more")
.argument(Arguments.newStringArgument()
.label("search blocks")
.maxArgumentsConsumed(1)
.build())
.executor(args -> {
final String searchString = args.<String>getFirst().getValue();
final Set<Block> blocks = BlockHelper.getBlocksMatching(this.blocks, searchString);

if (blocks.isEmpty()) {
args.warn("Found no blocks matching %s", searchString);
if (!searchString.contains(":")) {
args.warn("Did you mean \"minecraft:%s\"?", searchString);
}
} else {
args.inform("Removing blocks %s", blocks.stream()
.map(BlockHelper::getBlockRegistryName)
.collect(Collectors.joining(", ")));
this.blocks.removeAll(blocks);
}
})
.build();
}

private void reloadWorldChunks() {
if (isEnabled() && isInWorld()) {
reloadChunkSmooth();
Expand Down
Loading

0 comments on commit 3161eb5

Please sign in to comment.