This commit is contained in:
gnembon committed 2024-10-04 20:16:39 +02:00
1 parent 6144967299
commit 3a66dd0a9b
17 files changed
+198 -161

No files matched your search

+3 -7
View File
@@ -70,8 +70,8 @@ Recipe type can take one of the following options:
* `'smithing'` - smithing table (1.16+)
The return value is a list of available recipes (even if there is only one recipe available). Each recipe contains of
an item triple of the crafting result, list of ingredients, each containing a list of possible variants of the
ingredients in this slot, as item triples, or `null` if its a shaped recipe and a given slot in the patterns is left
an item triple of the crafting results as a list of item stacks, list of ingredients, each containing a list of possible variants of the
ingredients in this slot, as item ids, or `null` if it is a shaped recipe and a given slot in the patterns is left
empty, and recipe specification as another list. Possible recipe specs is:
* `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3.
* `['shapeless']` - shapeless crafting
@@ -80,10 +80,6 @@ Recipe type can take one of the following options:
* `['special']` - special crafting recipe, typically not present in the crafting menu
* `['custom']` - other recipe types
Note that ingredients are specified as tripes, with count and nbt information. Currently all recipes require always one
of the ingredients, and for some recipes, even if the nbt data for the ingredient is specified (e.g. `dispenser`), it
can accept items of any tags.
Also note that some recipes leave some products in the crafting window, and these can be determined using
`crafting_remaining_item()` function
@@ -97,7 +93,7 @@ Also note that some recipes leave some products in the crafting window, and thes
### `crafting_remaining_item(item)`
returns `null` if the item has no remaining item in the crafting window when used as a crafting ingredient, or an
item name that serves as a replacement after crafting is done. Currently it can only be buckets and glass bottles.
item tuple that serves as a replacement after crafting is done. Currently, it can only be buckets and glass bottles.
### `inventory_size(inventory)`
+2 -2
View File
@@ -3,10 +3,10 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check https://fabricmc.net/develop/
minecraft_version=24w39a
minecraft_version=24w40a
loader_version=0.16.5
jsr305_version=3.0.2
fabric_version=0.102.0+1.21
fabric_version=0.105.1+1.21.2
# Mod Properties
mod_version = 1.4.154
@@ -1,17 +0,0 @@
package carpet.fakes;
import java.util.List;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType;
public interface RecipeManagerInterface
{
/**
* Gets all the recipes for a given item. Also used for {@link carpet.helpers.HopperCounter#guessColor} to guess the
* colour of an item to display it prettily
*/
List<Recipe<?>> getAllMatching(final RecipeType<?> type, final ResourceLocation itemId, final RegistryAccess registryAccess);
}
+70 -24
View File
@@ -1,11 +1,12 @@
package carpet.helpers;
import carpet.CarpetServer;
import carpet.fakes.RecipeManagerInterface;
import carpet.script.utils.RecipeHelper;
import carpet.utils.Messenger;
import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
@@ -21,9 +22,9 @@ import net.minecraft.world.item.DyeItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.PlacementInfo;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.AbstractBannerBlock;
import net.minecraft.world.level.block.BeaconBeamBlock;
import net.minecraft.world.level.block.Block;
@@ -36,7 +37,6 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static java.util.Map.entry;
@@ -101,7 +101,9 @@ public class HopperCounter
this.color = color;
String hexColor = Integer.toHexString(color.getTextColor());
if (hexColor.length() < 6)
{
hexColor = "0".repeat(6 - hexColor.length()) + hexColor;
}
this.coloredName = '#' + hexColor + ' ' + color.getName();
}
@@ -135,6 +137,7 @@ public class HopperCounter
/**
* Resets all counters, clearing their items.
*
* @param fresh Whether or not to start the clocks going immediately or later.
*/
public static void resetAll(MinecraftServer server, boolean fresh)
@@ -142,7 +145,10 @@ public class HopperCounter
for (HopperCounter counter : COUNTERS.values())
{
counter.reset(server);
if (fresh) counter.startTick = -1;
if (fresh)
{
counter.startTick = -1;
}
}
}
@@ -158,7 +164,10 @@ public class HopperCounter
List<Component> temp = counter.format(server, realtime, false);
if (temp.size() > 1)
{
if (!text.isEmpty()) text.add(Messenger.s(""));
if (!text.isEmpty())
{
text.add(Messenger.s(""));
}
text.addAll(temp);
}
}
@@ -214,7 +223,7 @@ public class HopperCounter
Item item = e.getKey();
MutableComponent itemName = Component.translatable(item.getDescriptionId());
Style itemStyle = itemName.getStyle();
TextColor color = guessColor(item, server.registryAccess());
TextColor color = guessColor(item, server.overworld());
itemName.setStyle((color != null) ? itemStyle.withColor(color) : itemStyle.withItalic(true));
long count = e.getLongValue();
return Messenger.c("g - ", itemName,
@@ -231,13 +240,25 @@ public class HopperCounter
*/
public static int appropriateColor(int color)
{
if (color == 0) return MapColor.SNOW.col;
if (color == 0)
{
return MapColor.SNOW.col;
}
int r = (color >> 16 & 255);
int g = (color >> 8 & 255);
int b = (color & 255);
if (r < 70) r = 70;
if (g < 70) g = 70;
if (b < 70) b = 70;
if (r < 70)
{
r = 70;
}
if (g < 70)
{
g = 70;
}
if (b < 70)
{
b = 70;
}
return (r << 16) + (g << 8) + b;
}
@@ -337,8 +358,14 @@ public class HopperCounter
*/
public static TextColor fromItem(Item item, RegistryAccess registryAccess)
{
if (DEFAULTS.containsKey(item)) return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col));
if (item instanceof DyeItem dye) return TextColor.fromRgb(appropriateColor(dye.getDyeColor().getMapColor().col));
if (DEFAULTS.containsKey(item))
{
return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col));
}
if (item instanceof DyeItem dye)
{
return TextColor.fromRgb(appropriateColor(dye.getDyeColor().getMapColor().col));
}
Block block = null;
final Registry<Item> itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM);
final Registry<Block> blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK);
@@ -353,8 +380,14 @@ public class HopperCounter
}
if (block != null)
{
if (block instanceof AbstractBannerBlock) return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col));
if (block instanceof BeaconBeamBlock) return TextColor.fromRgb(appropriateColor( ((BeaconBeamBlock) block).getColor().getMapColor().col));
if (block instanceof AbstractBannerBlock)
{
return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col));
}
if (block instanceof BeaconBeamBlock)
{
return TextColor.fromRgb(appropriateColor(((BeaconBeamBlock) block).getColor().getMapColor().col));
}
return TextColor.fromRgb(appropriateColor(block.defaultMapColor().col));
}
return null;
@@ -364,35 +397,48 @@ public class HopperCounter
* Guesses the item's colour from the item itself. It first calls {@link HopperCounter#fromItem} to see if it has a
* valid colour there, if not just makes a guess, and if that fails just returns null
*/
public static TextColor guessColor(Item item, RegistryAccess registryAccess)
public static TextColor guessColor(Item item, Level level)
{
RegistryAccess registryAccess = level.registryAccess();
TextColor direct = fromItem(item, registryAccess);
if (direct != null) return direct;
if (CarpetServer.minecraft_server == null) return WHITE;
if (direct != null)
{
return direct;
}
if (CarpetServer.minecraft_server == null)
{
return WHITE;
}
ResourceLocation id = registryAccess.lookupOrThrow(Registries.ITEM).getKey(item);
for (RecipeType<?> type: registryAccess.lookupOrThrow(Registries.RECIPE_TYPE))
if (id == null)
{
for (Recipe<?> r: ((RecipeManagerInterface) CarpetServer.minecraft_server.getRecipeManager()).getAllMatching(type, id, registryAccess))
return null;
}
for (Recipe<?> r : RecipeHelper.getRecipesForOutput(CarpetServer.minecraft_server.getRecipeManager(), id, level))
{
for (Optional<PlacementInfo.SlotInfo> ingredient: r.placementInfo().slotInfo())
for (Ingredient ingredient : r.placementInfo().ingredients())
{
for(ItemStack stack : ingredient.get().possibleItems())
for (Holder<Item> stack : ingredient.items())
{
TextColor cand = fromItem(stack.getItem(), registryAccess);
TextColor cand = fromItem(stack.value(), registryAccess);
if (cand != null)
{
return cand;
}
}
}
}
return null;
}
/**
* Returns the hopper counter for the given color
*/
public static HopperCounter getCounter(DyeColor color) {
public static HopperCounter getCounter(DyeColor color)
{
return COUNTERS.get(color);
}
@@ -1,6 +1,7 @@
package carpet.mixins;
import carpet.fakes.AbstractContainerMenuInterface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractCraftingMenu;
@@ -15,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class AbstractCraftingMenu_scarpetMixin
{
@Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true)
private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder<?> recipe, Inventory player, CallbackInfoReturnable<RecipeBookMenu.PostPlaceAction> cir) {
private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder<?> recipe, ServerLevel serverLevel, Inventory player, CallbackInfoReturnable<RecipeBookMenu.PostPlaceAction> cir) {
if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll))
cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING);
}
@@ -1,6 +1,7 @@
package carpet.mixins;
import carpet.fakes.AbstractContainerMenuInterface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractFurnaceMenu;
@@ -15,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class AbstractFurnaceMenu_scarpetMixin
{
@Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true)
private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder<?> recipe, Inventory player, CallbackInfoReturnable<RecipeBookMenu.PostPlaceAction> cir) {
private void selectRecipeCallback(boolean craftAll, boolean b, RecipeHolder<?> recipe, ServerLevel level, Inventory player, CallbackInfoReturnable<RecipeBookMenu.PostPlaceAction> cir) {
if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll))
cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING);
}
@@ -1,55 +0,0 @@
package carpet.mixins;
import carpet.fakes.RecipeManagerInterface;
import com.google.common.collect.Multimap;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType;
@Mixin(RecipeManager.class)
public class RecipeManager_scarpetMixin implements RecipeManagerInterface
{
@Shadow private Multimap<RecipeType<?>, RecipeHolder<?>> byType;
@Shadow private Map<ResourceLocation, RecipeHolder<?>> byName;
@Override
public List<Recipe<?>> getAllMatching(RecipeType<?> type, ResourceLocation itemId, RegistryAccess registryAccess)
{
// quiq cheq
RecipeHolder<?> recipe = byName.get(itemId);
if (recipe != null && recipe.value().getType().equals(type))
{
return List.of(recipe.value());
}
if (!byType.containsKey(type))
{
// happens when mods add recipe to the registry without updating recipe manager
return List.of();
}
Collection<RecipeHolder<?>> typeRecipes = byType.get(type);
Registry<Item> regs = registryAccess.lookupOrThrow(Registries.ITEM);
Item item = regs.getValue(itemId);
if (item == Items.AIR)
{
return List.of();
}
return typeRecipes.stream()
.<Recipe<?>>map(RecipeHolder::value)
.filter(r -> r.getResultItem(registryAccess).is(item))
.toList();
}
}
@@ -3,6 +3,7 @@ package carpet.mixins;
import carpet.fakes.EntityInterface;
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket;
import net.minecraft.world.entity.player.Input;
import net.minecraft.world.item.crafting.RecipeManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@@ -255,7 +256,11 @@ public class ServerGamePacketListenerImpl_scarpetEventsMixin
{
if (PLAYER_CHOOSES_RECIPE.isNeeded())
{
if(PLAYER_CHOOSES_RECIPE.onRecipeSelected(player, packet.getRecipe(), packet.isUseMaxItems())) ci.cancel();
RecipeManager.ServerDisplayInfo displayInfo = player.server.getRecipeManager().getRecipeFromDisplay(packet.recipe());
if (displayInfo == null) {
return;
}
if(PLAYER_CHOOSES_RECIPE.onRecipeSelected(player, displayInfo.parent().id().location(), packet.useMaxItems())) ci.cancel();
}
}
@@ -14,7 +14,7 @@ import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -86,20 +86,20 @@ public abstract class ServerPlayer_scarpetEventMixin extends Player implements S
private Vec3 previousLocation;
private ResourceKey<Level> previousDimension;
@Inject(method = "changeDimension", at = @At("HEAD"))
private void logPreviousCoordinates(DimensionTransition serverWorld, CallbackInfoReturnable<Entity> cir)
@Inject(method = "teleport", at = @At("HEAD"))
private void logPreviousCoordinates(TeleportTransition serverWorld, CallbackInfoReturnable<Entity> cir)
{
previousLocation = position();
previousDimension = level().dimension(); //dimension type
}
@Inject(method = "changeDimension", at = @At("RETURN"))
private void atChangeDimension(DimensionTransition destinationP, CallbackInfoReturnable<Entity> cir)
@Inject(method = "teleport", at = @At("RETURN"))
private void atChangeDimension(TeleportTransition destinationP, CallbackInfoReturnable<Entity> cir)
{
if (PLAYER_CHANGES_DIMENSION.isNeeded())
{
ServerPlayer player = (ServerPlayer) (Object)this;
DimensionTransition destinationTransition = destinationP;
TeleportTransition destinationTransition = destinationP;
ServerLevel destination = destinationTransition.newLevel();
Vec3 to = null;
if (!wonGame || previousDimension != Level.END || destination.dimension() != Level.OVERWORLD)
@@ -8,9 +8,9 @@ import net.minecraft.network.DisconnectionDetails;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
@@ -31,7 +31,7 @@ import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
import carpet.fakes.ServerPlayerInterface;
import carpet.utils.Messenger;
@@ -84,7 +84,7 @@ public class EntityPlayerMPFake extends ServerPlayer
instance.getAttribute(Attributes.STEP_HEIGHT).setBaseValue(0.6F);
instance.gameMode.changeGameModeForPlayer(gamemode);
server.getPlayerList().broadcastAll(new ClientboundRotateHeadPacket(instance, (byte) (instance.yHeadRot * 256 / 360)), dimensionId);//instance.dimension);
server.getPlayerList().broadcastAll(new ClientboundTeleportEntityPacket(instance), dimensionId);//instance.dimension);
server.getPlayerList().broadcastAll(ClientboundEntityPositionSyncPacket.of(instance), dimensionId);//instance.dimension);
//instance.world.getChunkManager(). updatePosition(instance);
instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0x7f); // show all model layers (incl. capes)
instance.getAbilities().flying = flying;
@@ -216,9 +216,9 @@ public class EntityPlayerMPFake extends ServerPlayer
}
@Override
public Player changeDimension(DimensionTransition serverLevel)
public ServerPlayer teleport(TeleportTransition serverLevel)
{
super.changeDimension(serverLevel);
super.teleport(serverLevel);
if (wonGame) {
ServerboundClientCommandPacket p = new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN);
connection.handleClientCommand(p);
@@ -6,8 +6,8 @@ import carpet.script.argument.FunctionArgument;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ThrowStatement;
import carpet.script.exception.Throwables;
import carpet.script.external.Vanilla;
import carpet.script.utils.InputValidator;
import carpet.script.utils.RecipeHelper;
import carpet.script.value.BooleanValue;
import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue;
@@ -49,6 +49,7 @@ import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.ShapedRecipe;
import net.minecraft.world.item.crafting.ShapelessRecipe;
import net.minecraft.world.item.crafting.SingleItemRecipe;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.minecraft.world.phys.Vec3;
public class Inventories
@@ -103,7 +104,7 @@ public class Inventories
throw new InternalExpressionException("'recipe_data' requires at least one argument");
}
String recipeName = lv.get(0).getString();
RecipeType<?> type = RecipeType.CRAFTING;
RecipeType<? extends Recipe<?>> type = RecipeType.CRAFTING;
if (lv.size() > 1)
{
String recipeType = lv.get(1).getString();
@@ -113,30 +114,44 @@ public class Inventories
throw new InternalExpressionException("Unknown recipe type: " + recipeType);
}
}
List<Recipe<?>> recipes = Vanilla.RecipeManager_getAllMatching(cc.server().getRecipeManager(), type, InputValidator.identifierOf(recipeName), cc.registryAccess());
List<Recipe<?>> recipes = RecipeHelper.getRecipesForOutput(cc.server().getRecipeManager(), type, InputValidator.identifierOf(recipeName), cc.level());
if (recipes.isEmpty())
{
return Value.NULL;
}
List<Value> recipesOutput = new ArrayList<>();
RegistryAccess regs = cc.registryAccess();
SlotDisplay.ResolutionContext context = SlotDisplay.ResolutionContext.forLevel(cc.level());
for (Recipe<?> recipe : recipes)
{
ItemStack result = recipe.getResultItem(regs);
List<Value> results = new ArrayList<>();
//ItemStack result = recipe.display().forEach(); getResultItem(regs);
recipe.display().forEach(rd -> rd.result().resolveForStacks(context).forEach(is -> results.add(ValueConversions.of(is, regs))));
List<Value> ingredientValue = new ArrayList<>();
recipe.placementInfo().slotInfo().forEach(ingredient -> {
if (ingredient.isEmpty())
for (Optional<PlacementInfo.SlotInfo> info : recipe.placementInfo().slotInfo())
{
if (info.isEmpty())
{
ingredientValue.add(Value.NULL);
return;
continue;
}
PlacementInfo.SlotInfo value = ingredient.get();
int position = value.placerOutputPosition();
PlacementInfo.SlotInfo value = info.get();
int ingredientIndex = value.placerOutputPosition();
List<Value> alternatives = new ArrayList<>();
value.possibleItems().stream().map(is -> ValueConversions.of(is, regs)).forEach(alternatives::add);
recipe.placementInfo().ingredients().get(ingredientIndex).items().forEach(item -> alternatives.add(ValueConversions.of(item.value(), regs)));
if (alternatives.isEmpty())
{
ingredientValue.add(Value.NULL);
}
else
{
ingredientValue.add(ListValue.wrap(alternatives));
});
}
}
Value recipeSpec;
if (recipe instanceof ShapedRecipe shapedRecipe)
@@ -155,8 +170,8 @@ public class Inventories
{
recipeSpec = ListValue.of(
new StringValue("smelting"),
new NumericValue(abstractCookingRecipe.getCookingTime()),
new NumericValue(abstractCookingRecipe.getExperience())
new NumericValue(abstractCookingRecipe.cookingTime()),
new NumericValue(abstractCookingRecipe.experience())
);
}
else if (recipe instanceof SingleItemRecipe)
@@ -172,7 +187,7 @@ public class Inventories
recipeSpec = ListValue.of(new StringValue("custom"));
}
recipesOutput.add(ListValue.of(ValueConversions.of(result, regs), ListValue.wrap(ingredientValue), recipeSpec));
recipesOutput.add(ListValue.of(ListValue.wrap(results), ListValue.wrap(ingredientValue), recipeSpec));
}
return ListValue.wrap(recipesOutput);
});
@@ -181,10 +196,11 @@ public class Inventories
{
String itemStr = v.get(0).getString();
ResourceLocation id = InputValidator.identifierOf(itemStr);
Registry<Item> registry = ((CarpetContext) c).registry(Registries.ITEM);
CarpetContext cc = (CarpetContext) c;
Registry<Item> registry = cc.registry(Registries.ITEM);
Item item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM));
Item reminder = item.getCraftingRemainingItem();
return reminder == null ? Value.NULL : NBTSerializableValue.nameFromRegistryId(registry.getKey(reminder));
ItemStack reminder = item.getCraftingRemainder();
return reminder.isEmpty() ? Value.NULL : ValueConversions.of(reminder, cc.registryAccess());
});
expression.addContextFunction("inventory_size", -1, (c, t, lv) ->
@@ -55,7 +55,6 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import net.minecraft.ChatFormatting;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.advancements.critereon.MinMaxBounds;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
@@ -204,12 +203,8 @@ public abstract class CommandArgument
// resource / identifier section
new VanillaUnconfigurableArgument("recipe", ResourceLocationArgument::id,
(c, p) -> ValueConversions.of(ResourceLocationArgument.getRecipe(c, p).id()), SuggestionProviders.ALL_RECIPES
),
new VanillaUnconfigurableArgument("advancement", ResourceLocationArgument::id,
(c, p) -> ValueConversions.of(ResourceLocationArgument.getAdvancement(c, p).id()), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getAdvancements().getAllAdvancements().stream().map(AdvancementHolder::id), builder)
),
new VanillaUnconfigurableArgument("recipe", Registries.RECIPE),
new VanillaUnconfigurableArgument("advancement", Registries.ADVANCEMENT),
new VanillaUnconfigurableArgument("lootcondition", ResourceLocationArgument::id,
(c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().reloadableRegistries().getKeys(Registries.LOOT_CONDITION_TYPE), builder)
),
-15
View File
@@ -13,13 +13,11 @@ import carpet.fakes.LivingEntityInterface;
import carpet.fakes.MinecraftServerInterface;
import carpet.fakes.MobEntityInterface;
import carpet.fakes.RandomStateVisitorAccessor;
import carpet.fakes.RecipeManagerInterface;
import carpet.fakes.AbstractContainerMenuInterface;
import carpet.fakes.ServerPlayerInterface;
import carpet.fakes.ServerPlayerInteractionManagerInterface;
import carpet.fakes.ServerWorldInterface;
import carpet.fakes.SpawnHelperInnerInterface;
import carpet.fakes.ThreadedAnvilChunkStorageInterface;
import carpet.mixins.Objective_scarpetMixin;
import carpet.mixins.PoiRecord_scarpetMixin;
import carpet.mixins.Scoreboard_scarpetMixin;
@@ -38,10 +36,8 @@ import net.fabricmc.loader.api.ModContainer;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.blocks.BlockInput;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager;
@@ -62,11 +58,6 @@ import net.minecraft.world.entity.animal.horse.AbstractHorse;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.DataSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.NaturalSpawner;
@@ -83,7 +74,6 @@ import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -107,11 +97,6 @@ public class Vanilla
return Map.of(); //return ((ThreadedAnvilChunkStorageInterface) chunkMap).regenerateChunkRegion(requestedChunks);
}
public static List<Recipe<?>> RecipeManager_getAllMatching(RecipeManager recipeManager, RecipeType<?> type, ResourceLocation output, RegistryAccess registryAccess)
{
return ((RecipeManagerInterface) recipeManager).getAllMatching(type, output, registryAccess);
}
public static int NaturalSpawner_MAGIC_NUMBER()
{
return SpawnReporter.MAGIC_NUMBER;
@@ -0,0 +1,57 @@
package carpet.script.utils;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.display.RecipeDisplay;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.minecraft.world.level.Level;
import java.util.ArrayList;
import java.util.List;
public class RecipeHelper
{
public static List<Recipe<?>> getRecipesForOutput(RecipeManager recipeManager, RecipeType<?> type, ResourceLocation id, Level level)
{
List<Recipe<?>> results = new ArrayList<>();
SlotDisplay.ResolutionContext context = SlotDisplay.ResolutionContext.forLevel(level);
recipeManager.getRecipes().forEach(r -> {
if (r.value().getType() == type)
{
for (RecipeDisplay recipeDisplay : r.value().display())
{
recipeDisplay.result().resolveForStacks(context).forEach(stack -> {
if (BuiltInRegistries.ITEM.wrapAsHolder(stack.getItem()).unwrapKey().map(ResourceKey::location).orElseThrow(IllegalStateException::new).equals(id))
{
results.add(r.value());
}
});
}
}
});
return results;
}
public static List<Recipe<?>> getRecipesForOutput(RecipeManager recipeManager, ResourceLocation id, Level level)
{
List<Recipe<?>> results = new ArrayList<>();
SlotDisplay.ResolutionContext context = SlotDisplay.ResolutionContext.forLevel(level);
recipeManager.getRecipes().forEach(r -> {
for (RecipeDisplay recipeDisplay : r.value().display())
{
recipeDisplay.result().resolveForStacks(context).forEach(stack -> {
if (BuiltInRegistries.ITEM.wrapAsHolder(stack.getItem()).unwrapKey().map(ResourceKey::location).orElseThrow(IllegalStateException::new).equals(id))
{
results.add(r.value());
}
});
}
});
return results;
}
}
@@ -26,6 +26,8 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket;
import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket;
import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket;
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
@@ -922,7 +924,7 @@ public class EntityValue extends Value
}
else
{
((ServerLevel) e.getCommandSenderWorld()).getChunkSource().broadcastAndSend(e, new ClientboundTeleportEntityPacket(e));
((ServerLevel) e.getCommandSenderWorld()).getChunkSource().broadcastAndSend(e, ClientboundEntityPositionSyncPacket.of(e));
}
}
}
@@ -31,6 +31,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.behavior.PositionTracker;
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities;
import net.minecraft.world.entity.ai.memory.WalkTarget;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
@@ -99,12 +100,17 @@ public class ValueConversions
public static Value of(ItemStack stack, RegistryAccess regs)
{
return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of(
of(regs.lookupOrThrow(Registries.ITEM).getKey(stack.getItem())),
of(stack.getItem(), regs),
new NumericValue(stack.getCount()),
NBTSerializableValue.fromStack(stack, regs)
);
}
public static Value of(Item item, RegistryAccess regs)
{
return of(regs.lookupOrThrow(Registries.ITEM).getKey(item));
}
public static Value of(Objective objective)
{
return ListValue.of(
-1
View File
@@ -151,7 +151,6 @@
"CommandDispatcher_scarpetCommandsMixin",
"FoodData_scarpetMixin",
"RecipeManager_scarpetMixin",
"BlockInput_scarpetMixin",
"BlockPredicate_scarpetMixin",
"TagPredicate_scarpetMixin",