Skip to content

Commit

Permalink
add anti-footgun entity selector limits
Browse files Browse the repository at this point in the history
hi yes I still have commit access lmao enjoy (also idea automatically sorted all the mixins lol)
  • Loading branch information
LemmaEOF committed Feb 8, 2024
1 parent 2b2d10c commit 5f83f9a
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 35 deletions.
5 changes: 5 additions & 0 deletions src/main/java/net/modfest/fireblanket/FireblanketMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class FireblanketMixin implements IMixinConfigPlugin {
private static final boolean DO_CHUNK_CACHE = System.getProperty("fireblanket.loadRadius") != null;
public static final boolean ALLOW_LAMBDAMAP_SAVING = Boolean.getBoolean("fireblanket.allowLambdaMapSaving");
private static final boolean DO_CHUNKSECTION_OPTO = Boolean.getBoolean("fireblanket.flattenChunkPalettes");
public static final boolean ALLOW_FOOTGUNS = Boolean.getBoolean("fireblanket.allowFootguns");

@Override
public void onLoad(String mixinPackage) {
Expand Down Expand Up @@ -111,6 +112,10 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (mixinClassName.contains("ai") || mixinClassName.contains("sounds")) {
return GAMEPLAY_CHANGES;
}

if (mixinClassName.contains("footgun")) {
return !ALLOW_FOOTGUNS;
}

if (mixinClassName.contains("SplitterHandler") && FabricLoader.getInstance().isModLoaded("krypton")) {
// Conflicts with Krypton, which also lifts the limit
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.modfest.fireblanket.mixin.footgun;

import net.minecraft.command.EntitySelectorOptions;
import net.minecraft.command.EntitySelectorReader;
import net.minecraft.text.Text;
import net.modfest.fireblanket.mixinsupport.ForceableArgument;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.Map;
import java.util.function.Predicate;

@Mixin(EntitySelectorOptions.class)
public abstract class MixinEntitySelectorOptions {
@Shadow private static void putOption(String id, EntitySelectorOptions.SelectorHandler handler, Predicate<EntitySelectorReader> condition, Text description) {
throw new IllegalStateException("Unimplemented mixin");
}

@SuppressWarnings("rawtypes")
@Shadow @Final private static Map OPTIONS;

@Inject(method = "register", at = @At("TAIL"))
private static void injectForce(CallbackInfo info) {
if (!OPTIONS.containsKey("force")) {
putOption("force", reader -> {
reader.setLocalWorldOnly();
((ForceableArgument) reader).setForced(reader.getReader().readBoolean());
}, reader -> !((ForceableArgument) reader).isForced(), Text.translatable("argument.entity.options.force.description"));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package net.modfest.fireblanket.mixin.footgun;

import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import net.minecraft.command.EntitySelector;
import net.minecraft.command.EntitySelectorReader;
import net.minecraft.predicate.NumberRange;
import net.minecraft.text.Text;
import net.modfest.fireblanket.mixinsupport.ForceableArgument;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

/**
* Prevents foot-gunning by using an unlimited @e selector without forcing to assure you know what you're doing
*/
@Mixin(EntitySelectorReader.class)
public class MixinEntitySelectorReader implements ForceableArgument {
@Shadow private boolean includesNonPlayers;
@Shadow private int limit;
@Shadow private NumberRange.DoubleRange distance;
private boolean forced = false;

private static final DynamicCommandExceptionType LIMIT_UNFORCED = new DynamicCommandExceptionType(
count -> Text.stringifiedTranslatable("argument.entity.selector.limit.unforced", count)
);

@Override
public void setForced(boolean forced) {
this.forced = forced;
}

@Override
public boolean isForced() {
return forced;
}

@Inject(method = "read", at = @At("RETURN"))
private void preventFootgun(CallbackInfoReturnable<EntitySelector> info) throws CommandSyntaxException {
if (this.includesNonPlayers
&& (this.limit > 50 || this.distance == NumberRange.DoubleRange.ANY)
&& !forced) {
throw LIMIT_UNFORCED.create(this.limit);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package net.modfest.fireblanket.mixinsupport;

public interface ForceableArgument {
void setForced(boolean force);
boolean isForced();
}
4 changes: 4 additions & 0 deletions src/main/resources/assets/fireblanket/lang/en_us.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"argument.entity.selector.limit.unforced": "Targeting too many entities with no distance filter; add `force=true` to the selector to bypass",
"argument.entity.options.force.description": "Force-allow more than 50 entities targeted with no distance filter"
}
72 changes: 37 additions & 35 deletions src/main/resources/fireblanket.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,75 +5,77 @@
"plugin": "net.modfest.fireblanket.FireblanketMixin",
"mixins": [
"accessor.BlockEntityTypeAccessor",
"accessor.ClientConnectionAccessor",
"accessor.EntityTypeAccessor",
"opto.MixinEntitySelector",
"opto.MixinRecipeManager",
"serde.MixinServerPlayerEntity",
"accessor.ServerChunkManagerAccessor",
"accessor.ServerLoginNetworkHandlerAccessor",
"adventure_fix.MixinEggItem",
"adventure_fix.MixinFlowerPotBlock",
"ai.MixinTemptGoal",
"be_sync.MixinBlockEntity",
"be_sync.MixinChunkHolder",
"block.MixinCommandBlock",
"block_format.MixinChunkSection",
"entity_ticking.MixinDebugStickItem",
"entity_ticking.MixinLivingEntity",
"entity_ticking.MixinItemGroups",
"entity_ticking.MixinEntity",
"entity_ticking.MixinItemGroups",
"entity_ticking.MixinLivingEntity",
"entity_ticking.MixinMinecraftServer",
"entity_ticking.MixinThreadedAnvilChunkStorage",
"entity_ticking.create.MixinSuperGlueEntity",
"sounds.MixinSpyglassItem",
"be_sync.MixinBlockEntity",
"be_sync.MixinChunkHolder",
"mods.pehkui.MixinScaleUtils",
"mods.pswg.MixinComplexCollisionManager",
"mods.mythicmetals.MixinCarmotShield",
"mods.create.MixinMechanicalBearingBlockEntity",
"mods.create.AccessorSmartBlockEntity",
"footgun.MixinEntitySelectorOptions",
"footgun.MixinEntitySelectorReader",
"fsc.MixinClientConnection",
"fsc.MixinSizePrepender",
"fsc.MixinSplitterHandler",
"io_uring.MixinServerNetworkIo",
"mods.create.AccessorSmartBlockEntity",
"mods.create.MixinMechanicalBearingBlockEntity",
"mods.mythicmetals.MixinCarmotShield",
"mods.pehkui.MixinScaleUtils",
"mods.pswg.MixinComplexCollisionManager",
"mods.terracotta_knights.MixinItemPickupGoal",
"opto.MixinEntitySelector",
"opto.MixinRecipeManager",
"packet_chunk_cache.MixinChunkDataS2CPacket",
"packet_chunk_cache.MixinWorldChunk",
"region_chunk_cache.MixinServerChunkManager",
"accessor.ClientConnectionAccessor",
"io_uring.MixinServerNetworkIo",
"accessor.ServerLoginNetworkHandlerAccessor",
"accessor.ServerChunkManagerAccessor",
"serde.MixinNbtCompound",
"adventure_fix.MixinEggItem",
"ai.MixinTemptGoal",
"mods.terracotta_knights.MixinItemPickupGoal",
"serde.MixinServerPlayerEntity",
"sounds.MixinSpyglassItem",
"zstd.MixinChunkStreamVersion",
"zstd.MixinRegionFile",
"zstd.MixinPersistentStateManager",
"zstd.MixinPersistentState",
"zstd.MixinLevelStorageSession",
"adventure_fix.MixinFlowerPotBlock",
"block.MixinCommandBlock"
"zstd.MixinPersistentState",
"zstd.MixinPersistentStateManager",
"zstd.MixinRegionFile"
],
"injectors": {
"defaultRequire": 1
},
"client": [
"accessor.ClientLoginNetworkHandlerAccessor",
"client.MixinClientPlayNetworkHandler",
"client.MixinRenderSystem",
"client.MixinSignBlockEntityRenderer",
"client.MixinClientPlayNetworkHandler",
"client.be_masking.MixinBlockEntityRenderDispatcher",
"client.be_masking.MixinRebuildTask",
"client.be_masking.sodium.MixinChunkRenderRebuildTask",
"client.bufferbuilder_opto.MixinBufferBuilder",
"client.bufferbuilder_opto.MixinVertexFormat",
"client.entity_masking.MixinEntityRenderer",
"client.vbo_opto.MixinShaderProgram",
"client.vbo_opto.MixinVertexBuffer",
"accessor.ClientLoginNetworkHandlerAccessor",
"client.entity_ticking.MixinArmorStandEntity",
"client.entity_ticking.MixinLivingEntity",
"client.entity_ticking.MixinLivingEntity",
"client.hooks.MixinWorldRenderer",
"client.lambdamap.MixinMapRegionFile",
"client.render_regions.MixinBlockEntityRenderDispatcher",
"client.render_regions.MixinEntityRenderDispatcher",
"client.render_regions.MixinRegionSubjects",
"client.lambdamap.MixinMapRegionFile",
"client.hooks.MixinWorldRenderer",
"client.timing.MixinObservables",
"client.timing.MixinBlockEntityRenderDispatcher",
"client.timing.MixinClientWorld",
"client.timing.MixinEntityRenderer",
"client.timing.MixinObservables",
"client.timing.MixinWorld",
"client.timing.MixinBlockEntityRenderDispatcher",
"client.timing.MixinEntityRenderer"
"client.vbo_opto.MixinShaderProgram",
"client.vbo_opto.MixinVertexBuffer"
]
}

0 comments on commit 5f83f9a

Please sign in to comment.