diff --git a/common/src/main/java/io/github/gaming32/bingo/BingoCommand.java b/common/src/main/java/io/github/gaming32/bingo/BingoCommand.java index a1d5e086..1b6b3047 100644 --- a/common/src/main/java/io/github/gaming32/bingo/BingoCommand.java +++ b/common/src/main/java/io/github/gaming32/bingo/BingoCommand.java @@ -16,6 +16,7 @@ import io.github.gaming32.bingo.data.BingoDifficulty; import io.github.gaming32.bingo.data.BingoRegistries; import io.github.gaming32.bingo.data.BingoTag; +import io.github.gaming32.bingo.data.goal.BingoGoal; import io.github.gaming32.bingo.data.goal.GoalHolder; import io.github.gaming32.bingo.data.goal.GoalManager; import io.github.gaming32.bingo.game.ActiveGoal; @@ -31,6 +32,7 @@ import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.arguments.ColorArgument; import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.commands.arguments.ResourceKeyArgument; import net.minecraft.commands.arguments.ResourceLocationArgument; import net.minecraft.commands.arguments.TeamArgument; import net.minecraft.commands.arguments.TimeArgument; @@ -40,6 +42,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentUtils; import net.minecraft.network.chat.HoverEvent; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerScoreboard; @@ -63,7 +66,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -121,41 +123,40 @@ public class BingoCommand { private static final CommandSwitch CONTINUE_AFTER_WIN = CommandSwitch.storeTrue("--continue-after-win"); private static final CommandSwitch INCLUDE_INACTIVE_TEAMS = CommandSwitch.storeTrue("--include-inactive-teams"); - private static final CommandSwitch SIZE = - CommandSwitch.argument("--size", IntegerArgumentType.integer(BingoBoard.MIN_SIZE, BingoBoard.MAX_SIZE)) - .defaultValue(BingoBoard.DEFAULT_SIZE) - .build(); - private static final CommandSwitch SEED = - CommandSwitch.argument("--seed", LongArgumentType.longArg()) - .defaultValue(RandomSupport::generateUniqueSeed) - .build(); - private static final CommandSwitch AUTO_FORFEIT_TIME = - CommandSwitch.argument("--auto-forfeit-time", TimeArgument.time(0)) - .getter(IntegerArgumentType::getInteger) - .defaultValue(BingoGame.DEFAULT_AUTO_FORFEIT_TICKS) - .build(); - private static final CommandSwitch> DIFFICULTY = - CommandSwitch.resource("--difficulty", BingoRegistries.DIFFICULTY) - .defaultValue(BingoDifficulties.MEDIUM) - .unknownExceptionType(UNKNOWN_DIFFICULTY) - .build(); - private static final CommandSwitch> GAMEMODE = - CommandSwitch.resource("--gamemode", BingoRegistries.GAME_MODE) - .defaultValue(BingoGameMode.STANDARD.key()) - .unknownExceptionType(UNKNOWN_GAMEMODE) - .build(); - - private static final CommandSwitch> REQUIRE_GOAL = - CommandSwitch.argument("--require-goal", ResourceLocationArgument.id()) - .getter(ResourceLocationArgument::getId) - .suggests((context, builder) -> SharedSuggestionProvider.suggestResource( - GoalManager.getGoalIds(), builder - )) - .buildRepeatable(HashSet::new); - private static final CommandSwitch> EXCLUDE_TAG = - CommandSwitch.resource("--exclude-tag", BingoRegistries.TAG) - .unknownExceptionType(UNKNOWN_TAG) - .buildRepeatable(); + private static final CommandSwitch SIZE = CommandSwitch + .argument("--size", IntegerArgumentType.integer(BingoBoard.MIN_SIZE, BingoBoard.MAX_SIZE)) + .build(BingoBoard.DEFAULT_SIZE); + private static final CommandSwitch SEED = CommandSwitch + .argument("--seed", LongArgumentType.longArg()) + .build(RandomSupport::generateUniqueSeed); + private static final CommandSwitch AUTO_FORFEIT_TIME = CommandSwitch + .argument("--auto-forfeit-time", TimeArgument.time(0)) + .getter(IntegerArgumentType::getInteger) + .build(BingoGame.DEFAULT_AUTO_FORFEIT_TICKS); + private static final CommandSwitch> DIFFICULTY = CommandSwitch + .resource("--difficulty", BingoRegistries.DIFFICULTY) + .unknownExceptionType(UNKNOWN_DIFFICULTY) + .build(BingoDifficulties.MEDIUM); + private static final CommandSwitch> GAMEMODE = CommandSwitch + .resource("--gamemode", BingoRegistries.GAME_MODE) + .unknownExceptionType(UNKNOWN_GAMEMODE) + .build(BingoGameMode.STANDARD.key()); + + private static final CommandSwitch> REQUIRE_GOAL = CommandSwitch + ., GoalHolder>specialArgument("--require-goal", ResourceKeyArgument.key(BingoRegistries.GOAL)) + .getter((context, arg) -> { + final var key = ResourceKeyArgument.getRegistryKey(context, arg, BingoRegistries.GOAL, INVALID_GOAL); + final var goal = GoalManager.getGoal(key.location()); + if (goal == null) { + throw UNKNOWN_GOAL.create(key.location()); + } + return goal; + }) + .buildRepeatable(LinkedHashSet::new); + private static final CommandSwitch> EXCLUDE_TAG = CommandSwitch + .resource("--exclude-tag", BingoRegistries.TAG) + .unknownExceptionType(UNKNOWN_TAG) + .buildRepeatable(); public static void register( CommandDispatcher dispatcher, @@ -394,7 +395,7 @@ private static int startGame(CommandContext context, int tea final var difficulty = DIFFICULTY.get(context); final long seed = SEED.get(context); - final var requiredGoalIds = REQUIRE_GOAL.get(context); + final var requiredGoals = REQUIRE_GOAL.get(context); final var excludedTags = EXCLUDE_TAG.get(context); final int size = SIZE.get(context); final var gamemode = GAMEMODE.get(context).value(); @@ -420,16 +421,6 @@ private static int startGame(CommandContext context, int tea throw NO_TEAMS.create(); } - final List requiredGoals = requiredGoalIds.stream() - .map(id -> { - final GoalHolder goal = GoalManager.getGoal(id); - if (goal == null) { - throwInBlock(UNKNOWN_GOAL.create(id)); - } - return goal; - }) - .toList(); - final CommandSyntaxException configError = gamemode.checkAllowedConfig( new BingoGameMode.GameConfig(gamemode, size, teams) ); @@ -571,9 +562,4 @@ private static int randomizeTeams( ); return players.size(); } - - @SuppressWarnings("unchecked") - private static void throwInBlock(Throwable t) throws T { - throw (T)t; - } } diff --git a/common/src/main/java/io/github/gaming32/bingo/client/icons/BlockIconRenderer.java b/common/src/main/java/io/github/gaming32/bingo/client/icons/BlockIconRenderer.java index 4c388cf0..758b449d 100644 --- a/common/src/main/java/io/github/gaming32/bingo/client/icons/BlockIconRenderer.java +++ b/common/src/main/java/io/github/gaming32/bingo/client/icons/BlockIconRenderer.java @@ -45,7 +45,7 @@ public void render(BlockIcon icon, GuiGraphics graphics, int x, int y) { private static void renderInGui(BlockState state, PoseStack poseStack, MultiBufferSource buffer, BakedModel model) { poseStack.pushPose(); - ItemTransform transform = model.getTransforms().gui; + ItemTransform transform = model.getTransforms().gui(); if (transform == ItemTransform.NO_TRANSFORM) { transform = DEFAULT_TRANSFORM; } diff --git a/common/src/main/java/io/github/gaming32/bingo/commandswitch/CommandSwitch.java b/common/src/main/java/io/github/gaming32/bingo/commandswitch/CommandSwitch.java index a768b00c..d9c71aae 100644 --- a/common/src/main/java/io/github/gaming32/bingo/commandswitch/CommandSwitch.java +++ b/common/src/main/java/io/github/gaming32/bingo/commandswitch/CommandSwitch.java @@ -8,9 +8,10 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.CommandNode; +import io.github.gaming32.bingo.util.BingoUtil; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.ResourceKeyArgument; -import net.minecraft.core.DefaultedRegistry; +import net.minecraft.commands.arguments.ResourceOrTagKeyArgument; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; @@ -71,15 +72,10 @@ static ResourceArgumentSwitchBuilder resource(String name, ResourceKey { - private static final Function, ?> ALWAYS_NULL = context -> null; - private final String name; private final ArgumentType type; private String argName; private ArgGetter getter; - @SuppressWarnings("unchecked") - private Function, T> defaultValue = - (Function, T>)ALWAYS_NULL; private SuggestionProvider suggests = null; private ArgumentSwitchBuilder(String name, ArgumentType type) { @@ -102,36 +98,31 @@ public ArgumentSwitchBuilder getter(ArgGetter getter) { return this; } - public ArgumentSwitchBuilder defaultValue(Function, T> function) { - this.defaultValue = function; + public ArgumentSwitchBuilder suggests(SuggestionProvider suggests) { + this.suggests = suggests; return this; } - public ArgumentSwitchBuilder defaultValue(Supplier supplier) { - return defaultValue(context -> supplier.get()); + public CommandSwitch build(Function, T> defaultValue) { + return buildInner(defaultValue); } - public ArgumentSwitchBuilder defaultValue(T value) { - return defaultValue(context -> value); - } - - public ArgumentSwitchBuilder suggests(SuggestionProvider suggests) { - this.suggests = suggests; - return this; + public CommandSwitch build(Supplier defaultSupplier) { + return buildInner(ctx -> defaultSupplier.get()); } - public CommandSwitch build() { - return buildInner(); + public CommandSwitch build(T defaultValue) { + return buildInner(ctx -> defaultValue); } public CommandSwitch buildRepeatable(Function, C> collectionFunction) { - if (defaultValue != ALWAYS_NULL) { - throw new IllegalArgumentException("Cannot specify default value with buildRepeatable()"); - } - return new RepeatableArgumentSwitch<>(buildInner(), collectionFunction); + return new RepeatableArgumentSwitch<>( + buildInner(context -> null), + (context, values) -> collectionFunction.apply(values) + ); } - private ArgumentSwitch buildInner() { + private ArgumentSwitch buildInner(Function, T> defaultValue) { return new ArgumentSwitch<>( name, argName, type, Objects.requireNonNull(getter, "Must specify a getter() for a argument()"), @@ -144,7 +135,6 @@ final class ResourceArgumentSwitchBuilder { private final String name; private final ResourceKey> registry; private String argName; - private ResourceKey defaultValue; private DynamicCommandExceptionType unknownExceptionType; private ResourceArgumentSwitchBuilder(String name, ResourceKey> registry) { @@ -158,53 +148,54 @@ public ResourceArgumentSwitchBuilder argName(String argName) { return this; } - public ResourceArgumentSwitchBuilder defaultValue(ResourceKey defaultValue) { - this.defaultValue = defaultValue; - return this; - } - public ResourceArgumentSwitchBuilder unknownExceptionType(DynamicCommandExceptionType type) { unknownExceptionType = type; return this; } - public CommandSwitch> build() { - return buildInner(); - } - - public CommandSwitch> buildRepeatable() { - if (defaultValue != null) { - throw new IllegalArgumentException("Cannot specify default value with buildRepeatable()"); - } - return new RepeatableArgumentSwitch<>( - buildInner(), - values -> HolderSet.direct(values.stream().distinct().toList()) - ); - } - - private ArgumentSwitch, Holder.Reference> buildInner() { + public CommandSwitch> build(ResourceKey defaultValue) { final var registryKey = this.registry; - final var defaultKey = this.defaultValue; + final var exceptionType = + Objects.requireNonNull(unknownExceptionType, "unknownExceptionType() must be called"); return new ArgumentSwitch<>( name, argName, ResourceKeyArgument.key(registryKey), - ArgGetter.forResource( - registryKey, - Objects.requireNonNull(unknownExceptionType, "unknownExceptionType() must be called") + (context, arg) -> ResourceKeyArgument.resolveKey(context, arg, registry, exceptionType), + context -> context + .getSource() + .registryAccess() + .lookupOrThrow(registryKey) + .getOrThrow(defaultValue), + null + ); + } + + public CommandSwitch> buildRepeatable() { + final var registryKey = this.registry; + final var exceptionType = + Objects.requireNonNull(unknownExceptionType, "unknownExceptionType() must be called"); + return new RepeatableArgumentSwitch<>( + new ArgumentSwitch<>( + name, argName, + ResourceOrTagKeyArgument.resourceOrTagKey(registryKey), + (context, arg) -> + ResourceOrTagKeyArgument.getResourceOrTagKey(context, arg, registryKey, exceptionType), + context -> null, null ), - context -> { + (context, values) -> { final var registry = context.getSource().registryAccess().lookupOrThrow(registryKey); - final ResourceKey key; - if (defaultKey != null) { - key = defaultKey; - } else if (registry instanceof DefaultedRegistry defaulted) { - key = ResourceKey.create(registryKey, defaulted.getDefaultKey()); - } else { - throw new IllegalArgumentException("defaultValue() must be specified for non-defaulted registry"); - } - return registry.getOrThrow(key); - }, - null + return switch (values.size()) { + case 0 -> HolderSet.empty(); + case 1 -> BingoUtil.toHolderSet(registry, values.iterator().next()); + default -> HolderSet.direct( + values.stream() + .map(result -> BingoUtil.toHolderSet(registry, result)) + .flatMap(HolderSet::stream) + .distinct() + .toList() + ); + }; + } ); } } diff --git a/common/src/main/java/io/github/gaming32/bingo/commandswitch/RepeatableArgumentSwitch.java b/common/src/main/java/io/github/gaming32/bingo/commandswitch/RepeatableArgumentSwitch.java index 5e14793a..ffab0537 100644 --- a/common/src/main/java/io/github/gaming32/bingo/commandswitch/RepeatableArgumentSwitch.java +++ b/common/src/main/java/io/github/gaming32/bingo/commandswitch/RepeatableArgumentSwitch.java @@ -5,11 +5,11 @@ import net.minecraft.commands.CommandSourceStack; import java.util.Collection; -import java.util.function.Function; +import java.util.function.BiFunction; record RepeatableArgumentSwitch( ArgumentSwitch inner, - Function, C> collectionFunction + BiFunction, Collection, C> collectionFunction ) implements CommandSwitch { @Override public String name() { @@ -23,6 +23,6 @@ public void addTo(CommandNode node) { @Override public C get(CommandContext context) { - return collectionFunction.apply(context.getSource().bingo$getRepeatableArgument(inner)); + return collectionFunction.apply(context, context.getSource().bingo$getRepeatableArgument(inner)); } } diff --git a/common/src/main/java/io/github/gaming32/bingo/conditions/DistanceFromSpawnCondition.java b/common/src/main/java/io/github/gaming32/bingo/conditions/DistanceFromSpawnCondition.java index 58a5c5cb..33bdd374 100644 --- a/common/src/main/java/io/github/gaming32/bingo/conditions/DistanceFromSpawnCondition.java +++ b/common/src/main/java/io/github/gaming32/bingo/conditions/DistanceFromSpawnCondition.java @@ -2,9 +2,7 @@ import com.mojang.serialization.MapCodec; import net.minecraft.advancements.critereon.DistancePredicate; -import net.minecraft.core.GlobalPos; import net.minecraft.util.context.ContextKey; -import net.minecraft.world.item.CompassItem; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; @@ -29,11 +27,7 @@ public LootItemConditionType getType() { @Override public boolean test(LootContext lootContext) { final Vec3 origin = lootContext.getParameter(LootContextParams.ORIGIN); - final GlobalPos spawnPoint = CompassItem.getSpawnPosition(lootContext.getLevel()); - if (spawnPoint == null || spawnPoint.dimension() != lootContext.getLevel().dimension()) { // Maybe some mod does something interesting? - return false; - } - final Vec3 spawnVec = Vec3.atCenterOf(spawnPoint.pos()); + final Vec3 spawnVec = Vec3.atCenterOf(lootContext.getLevel().getSharedSpawnPos()); return distance.isEmpty() || distance.get().matches( origin.x, origin.y, origin.z, spawnVec.x, spawnVec.y, spawnVec.z diff --git a/common/src/main/java/io/github/gaming32/bingo/conditions/WearingDifferentArmorCondition.java b/common/src/main/java/io/github/gaming32/bingo/conditions/WearingDifferentArmorCondition.java index 55834251..a09cf1fa 100644 --- a/common/src/main/java/io/github/gaming32/bingo/conditions/WearingDifferentArmorCondition.java +++ b/common/src/main/java/io/github/gaming32/bingo/conditions/WearingDifferentArmorCondition.java @@ -5,10 +5,11 @@ import io.github.gaming32.bingo.data.tags.convention.ConventionItemTags; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.ResourceKey; import net.minecraft.util.context.ContextKey; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.equipment.EquipmentAsset; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; @@ -46,12 +47,12 @@ public boolean test(LootContext lootContext) { return false; } int wearingCount = 0; - final var models = HashSet.newHashSet(4); + final var models = HashSet.>newHashSet(4); for (final var stack : livingEntity.getArmorSlots()) { if (!stack.is(ConventionItemTags.ARMORS)) continue; final var equippable = stack.get(DataComponents.EQUIPPABLE); if (equippable == null) continue; - models.add(equippable.model().orElse(null)); + equippable.assetId().ifPresent(models::add); } return equippedArmor.matches(wearingCount) && differentTypes.matches(models.size()); } diff --git a/common/src/main/java/io/github/gaming32/bingo/data/BingoRegistries.java b/common/src/main/java/io/github/gaming32/bingo/data/BingoRegistries.java index f479bfd0..c2d4998d 100644 --- a/common/src/main/java/io/github/gaming32/bingo/data/BingoRegistries.java +++ b/common/src/main/java/io/github/gaming32/bingo/data/BingoRegistries.java @@ -1,5 +1,6 @@ package io.github.gaming32.bingo.data; +import io.github.gaming32.bingo.data.goal.BingoGoal; import io.github.gaming32.bingo.data.icons.GoalIconType; import io.github.gaming32.bingo.data.progresstrackers.ProgressTrackerType; import io.github.gaming32.bingo.data.subs.BingoSubType; @@ -11,6 +12,7 @@ public class BingoRegistries { public static final ResourceKey> DIFFICULTY = createKey("difficulty"); public static final ResourceKey> GAME_MODE = createKey("game_mode"); + public static final ResourceKey> GOAL = createKey("goal"); public static final ResourceKey>> GOAL_ICON_TYPE = createKey("goal_icon_type"); public static final ResourceKey>> PROGRESS_TRACKER_TYPE = createKey("progress_tracker_type"); public static final ResourceKey>> SUB_TYPE = createKey("sub_type"); diff --git a/common/src/main/java/io/github/gaming32/bingo/data/goal/GoalManager.java b/common/src/main/java/io/github/gaming32/bingo/data/goal/GoalManager.java index fcc3e4f4..48e5df71 100644 --- a/common/src/main/java/io/github/gaming32/bingo/data/goal/GoalManager.java +++ b/common/src/main/java/io/github/gaming32/bingo/data/goal/GoalManager.java @@ -3,6 +3,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.github.gaming32.bingo.Bingo; +import io.github.gaming32.bingo.data.BingoRegistries; import io.github.gaming32.bingo.util.ResourceLocations; import net.minecraft.core.HolderLookup; import net.minecraft.resources.ResourceLocation; @@ -24,7 +25,7 @@ public class GoalManager extends SimpleJsonResourceReloadListener { private static Map> goalsByDifficulty = Map.of(); public GoalManager(HolderLookup.Provider registries) { - super(registries, BingoGoal.CODEC, "bingo/goal"); + super(registries, BingoGoal.CODEC, BingoRegistries.GOAL); } public static Set getGoalIds() { diff --git a/common/src/main/java/io/github/gaming32/bingo/game/BingoBoard.java b/common/src/main/java/io/github/gaming32/bingo/game/BingoBoard.java index 8fb7ed29..c7ff2d8c 100644 --- a/common/src/main/java/io/github/gaming32/bingo/game/BingoBoard.java +++ b/common/src/main/java/io/github/gaming32/bingo/game/BingoBoard.java @@ -26,6 +26,7 @@ import java.util.ArrayDeque; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -82,7 +83,7 @@ public static BingoBoard generate( int teamCount, RandomSource rand, Predicate isAllowedGoal, - List requiredGoals, + Collection requiredGoals, HolderSet excludedTags, boolean allowsClientRequired, HolderLookup.Provider registries @@ -121,7 +122,7 @@ public static GoalHolder[] generateGoals( int difficulty, RandomSource rand, Predicate isAllowedGoal, - List requiredGoals, + Collection requiredGoals, HolderSet excludedTags, boolean allowsClientRequired ) { diff --git a/common/src/main/java/io/github/gaming32/bingo/mixin/common/MixinCommandSourceStack.java b/common/src/main/java/io/github/gaming32/bingo/mixin/common/MixinCommandSourceStack.java index ac2a18ec..94a03590 100644 --- a/common/src/main/java/io/github/gaming32/bingo/mixin/common/MixinCommandSourceStack.java +++ b/common/src/main/java/io/github/gaming32/bingo/mixin/common/MixinCommandSourceStack.java @@ -1,164 +1,40 @@ package io.github.gaming32.bingo.mixin.common; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import io.github.gaming32.bingo.commandswitch.CommandSwitch; -import io.github.gaming32.bingo.ext.CommandSourceStackExt; -import io.github.gaming32.bingo.util.BingoUtil; -import net.minecraft.Util; -import net.minecraft.commands.CommandResultCallback; -import net.minecraft.commands.CommandSigningContext; -import net.minecraft.commands.CommandSource; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.github.gaming32.bingo.data.BingoRegistries; +import io.github.gaming32.bingo.data.goal.GoalManager; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityAnchorArgument; -import net.minecraft.network.chat.Component; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.TaskChainer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec2; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.concurrent.CompletableFuture; @Mixin(CommandSourceStack.class) -public class MixinCommandSourceStack implements CommandSourceStackExt { - @Shadow @Final private CommandSource source; - @Shadow @Final private Vec3 worldPosition; - @Shadow @Final private Vec2 rotation; - @Shadow @Final private ServerLevel level; - @Shadow @Final private int permissionLevel; - @Shadow @Final private String textName; - @Shadow @Final private Component displayName; - @Shadow @Final private MinecraftServer server; - @Shadow @Final private @Nullable Entity entity; - @Shadow @Final private boolean silent; - @Shadow @Final private CommandResultCallback resultCallback; - @Shadow @Final private EntityAnchorArgument.Anchor anchor; - @Shadow @Final private CommandSigningContext signingContext; - @Shadow @Final private TaskChainer chatMessageChainer; - - @Unique - private Set> bingo$constants = ImmutableSet.of(); - @Unique - private Map, Object> bingo$arguments = ImmutableMap.of(); - @Unique - private Multimap, Object> bingo$repeatableArguments = ImmutableMultimap.of(); - - private MixinCommandSourceStack() { - } - - @Invoker("") - static CommandSourceStack create( - CommandSource source, - Vec3 worldPosition, - Vec2 rotation, - ServerLevel level, - int permissionLevel, - String textName, - Component displayName, - MinecraftServer server, - @Nullable Entity entity, - boolean silent, - CommandResultCallback resultCallback, - EntityAnchorArgument.Anchor anchor, - CommandSigningContext signingContext, - TaskChainer chatMessageChainer - ) { - throw new AssertionError(); - } - - @Override - public CommandSourceStack bingo$withFlag(CommandSwitch flag) { - final var copy = bingo$copy(); - ((MixinCommandSourceStack)(CommandSourceStackExt)copy).bingo$constants = - BingoUtil.copyAndAdd(bingo$constants, flag); - return copy; - } - - @Override - public boolean bingo$hasFlag(CommandSwitch flag) { - return bingo$constants.contains(flag); - } - - @Override - public CommandSourceStack bingo$withArgument(CommandSwitch arg, T value) { - final var copy = bingo$copy(); - ((MixinCommandSourceStack)(CommandSourceStackExt)copy).bingo$arguments = - Util.copyAndPut(bingo$arguments, arg, value); - return copy; - } - - @Override - @SuppressWarnings("unchecked") - public Optional bingo$getArgument(CommandSwitch arg) { - return Optional.ofNullable((T)bingo$arguments.get(arg)); - } - - @Override - public CommandSourceStack bingo$withRepeatableArgument(CommandSwitch arg, T value) { - final var copy = bingo$copy(); - ((MixinCommandSourceStack)(CommandSourceStackExt)copy).bingo$repeatableArguments = - BingoUtil.copyAndPut(bingo$repeatableArguments, arg, value); - return copy; - } - - @Override - @SuppressWarnings("unchecked") - public Collection bingo$getRepeatableArgument(CommandSwitch arg) { - return (Collection)bingo$repeatableArguments.get(arg); - } - - @Unique - @NotNull - private CommandSourceStack bingo$copy() { - return copyExtraFields(create( - source, - worldPosition, - rotation, - level, - permissionLevel, - textName, - displayName, - server, - entity, - silent, - resultCallback, - anchor, - signingContext, - chatMessageChainer - )); - } - - @SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"}) - @ModifyExpressionValue( - method = "*", +public class MixinCommandSourceStack { + @Inject( + method = "suggestRegistryElements", at = @At( - value = "NEW", - target = "net/minecraft/commands/CommandSourceStack" + value = "INVOKE", + target = "Lnet/minecraft/commands/CommandSourceStack;registryAccess()Lnet/minecraft/core/RegistryAccess;" ), - require = 0, - expect = 0 + cancellable = true ) - private CommandSourceStack copyExtraFields(@NotNull CommandSourceStack newStack) { - final var ext = (MixinCommandSourceStack)(CommandSourceStackExt)newStack; - ext.bingo$constants = bingo$constants; - ext.bingo$arguments = bingo$arguments; - ext.bingo$repeatableArguments = bingo$repeatableArguments; - return newStack; + private void suggestBingoGoals( + ResourceKey> resourceKey, + SharedSuggestionProvider.ElementSuggestionType registryKey, + SuggestionsBuilder builder, + CommandContext context, + CallbackInfoReturnable> cir + ) { + if (resourceKey == BingoRegistries.GOAL) { + cir.setReturnValue(SharedSuggestionProvider.suggestResource(GoalManager.getGoalIds(), builder)); + } } } diff --git a/common/src/main/java/io/github/gaming32/bingo/mixin/common/commandswitch/MixinCommandSourceStack.java b/common/src/main/java/io/github/gaming32/bingo/mixin/common/commandswitch/MixinCommandSourceStack.java new file mode 100644 index 00000000..36338a71 --- /dev/null +++ b/common/src/main/java/io/github/gaming32/bingo/mixin/common/commandswitch/MixinCommandSourceStack.java @@ -0,0 +1,164 @@ +package io.github.gaming32.bingo.mixin.common.commandswitch; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import io.github.gaming32.bingo.commandswitch.CommandSwitch; +import io.github.gaming32.bingo.ext.CommandSourceStackExt; +import io.github.gaming32.bingo.util.BingoUtil; +import net.minecraft.Util; +import net.minecraft.commands.CommandResultCallback; +import net.minecraft.commands.CommandSigningContext; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.EntityAnchorArgument; +import net.minecraft.network.chat.Component; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.TaskChainer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +@Mixin(CommandSourceStack.class) +public class MixinCommandSourceStack implements CommandSourceStackExt { + @Shadow @Final private CommandSource source; + @Shadow @Final private Vec3 worldPosition; + @Shadow @Final private Vec2 rotation; + @Shadow @Final private ServerLevel level; + @Shadow @Final private int permissionLevel; + @Shadow @Final private String textName; + @Shadow @Final private Component displayName; + @Shadow @Final private MinecraftServer server; + @Shadow @Final private @Nullable Entity entity; + @Shadow @Final private boolean silent; + @Shadow @Final private CommandResultCallback resultCallback; + @Shadow @Final private EntityAnchorArgument.Anchor anchor; + @Shadow @Final private CommandSigningContext signingContext; + @Shadow @Final private TaskChainer chatMessageChainer; + + @Unique + private Set> bingo$constants = ImmutableSet.of(); + @Unique + private Map, Object> bingo$arguments = ImmutableMap.of(); + @Unique + private Multimap, Object> bingo$repeatableArguments = ImmutableMultimap.of(); + + private MixinCommandSourceStack() { + } + + @Invoker("") + static CommandSourceStack create( + CommandSource source, + Vec3 worldPosition, + Vec2 rotation, + ServerLevel level, + int permissionLevel, + String textName, + Component displayName, + MinecraftServer server, + @Nullable Entity entity, + boolean silent, + CommandResultCallback resultCallback, + EntityAnchorArgument.Anchor anchor, + CommandSigningContext signingContext, + TaskChainer chatMessageChainer + ) { + throw new AssertionError(); + } + + @Override + public CommandSourceStack bingo$withFlag(CommandSwitch flag) { + final var copy = bingo$copy(); + ((MixinCommandSourceStack)(CommandSourceStackExt)copy).bingo$constants = + BingoUtil.copyAndAdd(bingo$constants, flag); + return copy; + } + + @Override + public boolean bingo$hasFlag(CommandSwitch flag) { + return bingo$constants.contains(flag); + } + + @Override + public CommandSourceStack bingo$withArgument(CommandSwitch arg, T value) { + final var copy = bingo$copy(); + ((MixinCommandSourceStack)(CommandSourceStackExt)copy).bingo$arguments = + Util.copyAndPut(bingo$arguments, arg, value); + return copy; + } + + @Override + @SuppressWarnings("unchecked") + public Optional bingo$getArgument(CommandSwitch arg) { + return Optional.ofNullable((T)bingo$arguments.get(arg)); + } + + @Override + public CommandSourceStack bingo$withRepeatableArgument(CommandSwitch arg, T value) { + final var copy = bingo$copy(); + ((MixinCommandSourceStack)(CommandSourceStackExt)copy).bingo$repeatableArguments = + BingoUtil.copyAndPut(bingo$repeatableArguments, arg, value); + return copy; + } + + @Override + @SuppressWarnings("unchecked") + public Collection bingo$getRepeatableArgument(CommandSwitch arg) { + return (Collection)bingo$repeatableArguments.get(arg); + } + + @Unique + @NotNull + private CommandSourceStack bingo$copy() { + return copyExtraFields(create( + source, + worldPosition, + rotation, + level, + permissionLevel, + textName, + displayName, + server, + entity, + silent, + resultCallback, + anchor, + signingContext, + chatMessageChainer + )); + } + + @SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"}) + @ModifyExpressionValue( + method = "*", + at = @At( + value = "NEW", + target = "net/minecraft/commands/CommandSourceStack" + ), + require = 0, + expect = 0 + ) + private CommandSourceStack copyExtraFields(@NotNull CommandSourceStack newStack) { + final var ext = (MixinCommandSourceStack)(CommandSourceStackExt)newStack; + ext.bingo$constants = bingo$constants; + ext.bingo$arguments = bingo$arguments; + ext.bingo$repeatableArguments = bingo$repeatableArguments; + return newStack; + } +} diff --git a/common/src/main/java/io/github/gaming32/bingo/util/BingoUtil.java b/common/src/main/java/io/github/gaming32/bingo/util/BingoUtil.java index ab64876b..88d09d9a 100644 --- a/common/src/main/java/io/github/gaming32/bingo/util/BingoUtil.java +++ b/common/src/main/java/io/github/gaming32/bingo/util/BingoUtil.java @@ -13,8 +13,10 @@ import com.mojang.serialization.JsonOps; import io.github.gaming32.bingo.Bingo; import it.unimi.dsi.fastutil.Hash; +import net.minecraft.commands.arguments.ResourceOrTagKeyArgument; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; import net.minecraft.locale.Language; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -40,7 +42,6 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; -import java.util.stream.Stream; public class BingoUtil { private static final Hash.Strategy> HOLDER_STRATEGY = new Hash.Strategy<>() { @@ -252,14 +253,11 @@ public static double distanceToSquareEdge(double angle, double squareRadius) { : squareRadius / sin; } - public static HolderSet concatHolderSets(HolderSet a, HolderSet b) { - if (a.size() == 0) { - return b; - } - if (b.size() == 0) { - return a; - } - return HolderSet.direct(Stream.concat(a.stream(), b.stream()).distinct().toList()); + public static HolderSet toHolderSet(Registry registry, ResourceOrTagKeyArgument.Result result) { + return result.unwrap().map( + resource -> HolderSet.direct(registry.getOrThrow(resource)), + registry::getOrThrow + ); } public static Set copyAndAdd(Set set, T value) { diff --git a/common/src/main/resources/bingo-common.mixins.json b/common/src/main/resources/bingo-common.mixins.json index 4a8f503c..e63d9988 100644 --- a/common/src/main/resources/bingo-common.mixins.json +++ b/common/src/main/resources/bingo-common.mixins.json @@ -57,7 +57,8 @@ "MixinZombie", "PlayerAdvancementsAccessor", "ServerExplosionAccessor", - "StatsCounterAccessor" + "StatsCounterAccessor", + "commandswitch.MixinCommandSourceStack" ], "client": [ "client.CameraAccessor", diff --git a/common/src/main/resources/bingo.accessWidener b/common/src/main/resources/bingo.accessWidener index 40b0dd46..06a46892 100644 --- a/common/src/main/resources/bingo.accessWidener +++ b/common/src/main/resources/bingo.accessWidener @@ -1,7 +1,13 @@ accessWidener v2 named accessible class net/minecraft/advancements/critereon/PlayerPredicate$StatMatcher + accessible method net/minecraft/client/gui/GuiGraphics renderTooltipInternal (Lnet/minecraft/client/gui/Font;Ljava/util/List;IILnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;Lnet/minecraft/resources/ResourceLocation;)V + +accessible method net/minecraft/commands/arguments/ResourceKeyArgument getRegistryKey (Lcom/mojang/brigadier/context/CommandContext;Ljava/lang/String;Lnet/minecraft/resources/ResourceKey;Lcom/mojang/brigadier/exceptions/DynamicCommandExceptionType;)Lnet/minecraft/resources/ResourceKey; accessible method net/minecraft/commands/arguments/ResourceKeyArgument resolveKey (Lcom/mojang/brigadier/context/CommandContext;Ljava/lang/String;Lnet/minecraft/resources/ResourceKey;Lcom/mojang/brigadier/exceptions/DynamicCommandExceptionType;)Lnet/minecraft/core/Holder$Reference; + accessible method net/minecraft/world/level/storage/loot/parameters/LootContextParamSets register (Ljava/lang/String;Ljava/util/function/Consumer;)Lnet/minecraft/util/context/ContextKeySet; + accessible field net/minecraft/world/inventory/GrindstoneMenu repairSlots Lnet/minecraft/world/Container; + accessible method net/minecraft/world/level/storage/LevelResource (Ljava/lang/String;)V diff --git a/fabric/src/main/java/io/github/gaming32/bingo/fabric/datagen/goal/EasyGoalProvider.java b/fabric/src/main/java/io/github/gaming32/bingo/fabric/datagen/goal/EasyGoalProvider.java index edc9928b..15593784 100644 --- a/fabric/src/main/java/io/github/gaming32/bingo/fabric/datagen/goal/EasyGoalProvider.java +++ b/fabric/src/main/java/io/github/gaming32/bingo/fabric/datagen/goal/EasyGoalProvider.java @@ -89,6 +89,7 @@ import net.minecraft.advancements.critereon.UsingItemTrigger; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.ByteTag; @@ -523,6 +524,10 @@ public void addGoals() { addGoal(BingoGoal.builder(id("finish_at_spawn")) .criterion("nearby", CriteriaTriggers.LOCATION.createCriterion( new PlayerTrigger.TriggerInstance(Optional.of(ContextAwarePredicate.create( + new LocationCheck( + Optional.of(LocationPredicate.Builder.inDimension(Level.OVERWORLD).build()), + BlockPos.ZERO + ), new DistanceFromSpawnCondition( Optional.of(DistancePredicate.horizontal(MinMaxBounds.Doubles.atMost(3))) ),