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+) * `'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 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 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 triples, or `null` if its a shaped recipe and a given slot in the patterns is left 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: 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. * `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3.
* `['shapeless']` - shapeless crafting * `['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 * `['special']` - special crafting recipe, typically not present in the crafting menu
* `['custom']` - other recipe types * `['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 Also note that some recipes leave some products in the crafting window, and these can be determined using
`crafting_remaining_item()` function `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)` ### `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 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)` ### `inventory_size(inventory)`
+2 -2
View File
@@ -3,10 +3,10 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties # Fabric Properties
# check https://fabricmc.net/develop/ # check https://fabricmc.net/develop/
minecraft_version=24w39a minecraft_version=24w40a
loader_version=0.16.5 loader_version=0.16.5
jsr305_version=3.0.2 jsr305_version=3.0.2
fabric_version=0.102.0+1.21 fabric_version=0.105.1+1.21.2
# Mod Properties # Mod Properties
mod_version = 1.4.154 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; package carpet.helpers;
import carpet.CarpetServer; import carpet.CarpetServer;
import carpet.fakes.RecipeManagerInterface; import carpet.script.utils.RecipeHelper;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongMap;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries; 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.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; 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.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.AbstractBannerBlock;
import net.minecraft.world.level.block.BeaconBeamBlock; import net.minecraft.world.level.block.BeaconBeamBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@@ -36,7 +37,6 @@ import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Map.entry; import static java.util.Map.entry;
@@ -101,7 +101,9 @@ public class HopperCounter
this.color = color; this.color = color;
String hexColor = Integer.toHexString(color.getTextColor()); String hexColor = Integer.toHexString(color.getTextColor());
if (hexColor.length() < 6) if (hexColor.length() < 6)
{
hexColor = "0".repeat(6 - hexColor.length()) + hexColor; hexColor = "0".repeat(6 - hexColor.length()) + hexColor;
}
this.coloredName = '#' + hexColor + ' ' + color.getName(); this.coloredName = '#' + hexColor + ' ' + color.getName();
} }
@@ -135,6 +137,7 @@ public class HopperCounter
/** /**
* Resets all counters, clearing their items. * Resets all counters, clearing their items.
*
* @param fresh Whether or not to start the clocks going immediately or later. * @param fresh Whether or not to start the clocks going immediately or later.
*/ */
public static void resetAll(MinecraftServer server, boolean fresh) public static void resetAll(MinecraftServer server, boolean fresh)
@@ -142,7 +145,10 @@ public class HopperCounter
for (HopperCounter counter : COUNTERS.values()) for (HopperCounter counter : COUNTERS.values())
{ {
counter.reset(server); 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); List<Component> temp = counter.format(server, realtime, false);
if (temp.size() > 1) if (temp.size() > 1)
{ {
if (!text.isEmpty()) text.add(Messenger.s("")); if (!text.isEmpty())
{
text.add(Messenger.s(""));
}
text.addAll(temp); text.addAll(temp);
} }
} }
@@ -214,7 +223,7 @@ public class HopperCounter
Item item = e.getKey(); Item item = e.getKey();
MutableComponent itemName = Component.translatable(item.getDescriptionId()); MutableComponent itemName = Component.translatable(item.getDescriptionId());
Style itemStyle = itemName.getStyle(); 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)); itemName.setStyle((color != null) ? itemStyle.withColor(color) : itemStyle.withItalic(true));
long count = e.getLongValue(); long count = e.getLongValue();
return Messenger.c("g - ", itemName, return Messenger.c("g - ", itemName,
@@ -231,13 +240,25 @@ public class HopperCounter
*/ */
public static int appropriateColor(int color) 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 r = (color >> 16 & 255);
int g = (color >> 8 & 255); int g = (color >> 8 & 255);
int b = (color & 255); int b = (color & 255);
if (r < 70) r = 70; if (r < 70)
if (g < 70) g = 70; {
if (b < 70) b = 70; r = 70;
}
if (g < 70)
{
g = 70;
}
if (b < 70)
{
b = 70;
}
return (r << 16) + (g << 8) + b; return (r << 16) + (g << 8) + b;
} }
@@ -337,8 +358,14 @@ public class HopperCounter
*/ */
public static TextColor fromItem(Item item, RegistryAccess registryAccess) public static TextColor fromItem(Item item, RegistryAccess registryAccess)
{ {
if (DEFAULTS.containsKey(item)) return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).defaultMapColor().col)); if (DEFAULTS.containsKey(item))
if (item instanceof DyeItem dye) return TextColor.fromRgb(appropriateColor(dye.getDyeColor().getMapColor().col)); {
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; Block block = null;
final Registry<Item> itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM); final Registry<Item> itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM);
final Registry<Block> blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK); final Registry<Block> blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK);
@@ -353,8 +380,14 @@ public class HopperCounter
} }
if (block != null) if (block != null)
{ {
if (block instanceof AbstractBannerBlock) return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col)); if (block instanceof AbstractBannerBlock)
if (block instanceof BeaconBeamBlock) return TextColor.fromRgb(appropriateColor( ((BeaconBeamBlock) block).getColor().getMapColor().col)); {
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 TextColor.fromRgb(appropriateColor(block.defaultMapColor().col));
} }
return null; 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 * 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 * 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); TextColor direct = fromItem(item, registryAccess);
if (direct != null) return direct; if (direct != null)
if (CarpetServer.minecraft_server == null) return WHITE; {
return direct;
}
if (CarpetServer.minecraft_server == null)
{
return WHITE;
}
ResourceLocation id = registryAccess.lookupOrThrow(Registries.ITEM).getKey(item); 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) if (cand != null)
{
return cand; return cand;
} }
} }
} }
} }
return null; return null;
} }
/** /**
* Returns the hopper counter for the given color * Returns the hopper counter for the given color
*/ */
public static HopperCounter getCounter(DyeColor color) { public static HopperCounter getCounter(DyeColor color)
{
return COUNTERS.get(color); return COUNTERS.get(color);
} }
@@ -1,6 +1,7 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.AbstractContainerMenuInterface; import carpet.fakes.AbstractContainerMenuInterface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractCraftingMenu; import net.minecraft.world.inventory.AbstractCraftingMenu;
@@ -15,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class AbstractCraftingMenu_scarpetMixin public class AbstractCraftingMenu_scarpetMixin
{ {
@Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true) @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)) if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll))
cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING); cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING);
} }
@@ -1,6 +1,7 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.AbstractContainerMenuInterface; import carpet.fakes.AbstractContainerMenuInterface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractFurnaceMenu; import net.minecraft.world.inventory.AbstractFurnaceMenu;
@@ -15,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class AbstractFurnaceMenu_scarpetMixin public class AbstractFurnaceMenu_scarpetMixin
{ {
@Inject(method = "handlePlacement",at = @At("HEAD"), cancellable = true) @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)) if(((AbstractContainerMenuInterface) this).callSelectRecipeListener((ServerPlayer) player.player ,recipe,craftAll))
cir.setReturnValue(RecipeBookMenu.PostPlaceAction.NOTHING); 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 carpet.fakes.EntityInterface;
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; import net.minecraft.network.protocol.game.ServerboundChatCommandPacket;
import net.minecraft.world.entity.player.Input; 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.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -255,7 +256,11 @@ public class ServerGamePacketListenerImpl_scarpetEventsMixin
{ {
if (PLAYER_CHOOSES_RECIPE.isNeeded()) 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.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; 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 net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -86,20 +86,20 @@ public abstract class ServerPlayer_scarpetEventMixin extends Player implements S
private Vec3 previousLocation; private Vec3 previousLocation;
private ResourceKey<Level> previousDimension; private ResourceKey<Level> previousDimension;
@Inject(method = "changeDimension", at = @At("HEAD")) @Inject(method = "teleport", at = @At("HEAD"))
private void logPreviousCoordinates(DimensionTransition serverWorld, CallbackInfoReturnable<Entity> cir) private void logPreviousCoordinates(TeleportTransition serverWorld, CallbackInfoReturnable<Entity> cir)
{ {
previousLocation = position(); previousLocation = position();
previousDimension = level().dimension(); //dimension type previousDimension = level().dimension(); //dimension type
} }
@Inject(method = "changeDimension", at = @At("RETURN")) @Inject(method = "teleport", at = @At("RETURN"))
private void atChangeDimension(DimensionTransition destinationP, CallbackInfoReturnable<Entity> cir) private void atChangeDimension(TeleportTransition destinationP, CallbackInfoReturnable<Entity> cir)
{ {
if (PLAYER_CHANGES_DIMENSION.isNeeded()) if (PLAYER_CHANGES_DIMENSION.isNeeded())
{ {
ServerPlayer player = (ServerPlayer) (Object)this; ServerPlayer player = (ServerPlayer) (Object)this;
DimensionTransition destinationTransition = destinationP; TeleportTransition destinationTransition = destinationP;
ServerLevel destination = destinationTransition.newLevel(); ServerLevel destination = destinationTransition.newLevel();
Vec3 to = null; Vec3 to = null;
if (!wonGame || previousDimension != Level.END || destination.dimension() != Level.OVERWORLD) 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.Component;
import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.network.protocol.PacketFlow; 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.ClientboundPlayerInfoUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket; import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; 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.Level;
import net.minecraft.world.level.block.entity.SkullBlockEntity; import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.state.BlockState; 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 net.minecraft.world.phys.Vec3;
import carpet.fakes.ServerPlayerInterface; import carpet.fakes.ServerPlayerInterface;
import carpet.utils.Messenger; import carpet.utils.Messenger;
@@ -84,7 +84,7 @@ public class EntityPlayerMPFake extends ServerPlayer
instance.getAttribute(Attributes.STEP_HEIGHT).setBaseValue(0.6F); instance.getAttribute(Attributes.STEP_HEIGHT).setBaseValue(0.6F);
instance.gameMode.changeGameModeForPlayer(gamemode); instance.gameMode.changeGameModeForPlayer(gamemode);
server.getPlayerList().broadcastAll(new ClientboundRotateHeadPacket(instance, (byte) (instance.yHeadRot * 256 / 360)), dimensionId);//instance.dimension); 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.world.getChunkManager(). updatePosition(instance);
instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0x7f); // show all model layers (incl. capes) instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0x7f); // show all model layers (incl. capes)
instance.getAbilities().flying = flying; instance.getAbilities().flying = flying;
@@ -216,9 +216,9 @@ public class EntityPlayerMPFake extends ServerPlayer
} }
@Override @Override
public Player changeDimension(DimensionTransition serverLevel) public ServerPlayer teleport(TeleportTransition serverLevel)
{ {
super.changeDimension(serverLevel); super.teleport(serverLevel);
if (wonGame) { if (wonGame) {
ServerboundClientCommandPacket p = new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN); ServerboundClientCommandPacket p = new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN);
connection.handleClientCommand(p); connection.handleClientCommand(p);
@@ -6,8 +6,8 @@ import carpet.script.argument.FunctionArgument;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ThrowStatement; import carpet.script.exception.ThrowStatement;
import carpet.script.exception.Throwables; import carpet.script.exception.Throwables;
import carpet.script.external.Vanilla;
import carpet.script.utils.InputValidator; import carpet.script.utils.InputValidator;
import carpet.script.utils.RecipeHelper;
import carpet.script.value.BooleanValue; import carpet.script.value.BooleanValue;
import carpet.script.value.EntityValue; import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue; 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.ShapedRecipe;
import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.item.crafting.ShapelessRecipe;
import net.minecraft.world.item.crafting.SingleItemRecipe; import net.minecraft.world.item.crafting.SingleItemRecipe;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public class Inventories public class Inventories
@@ -103,7 +104,7 @@ public class Inventories
throw new InternalExpressionException("'recipe_data' requires at least one argument"); throw new InternalExpressionException("'recipe_data' requires at least one argument");
} }
String recipeName = lv.get(0).getString(); String recipeName = lv.get(0).getString();
RecipeType<?> type = RecipeType.CRAFTING; RecipeType<? extends Recipe<?>> type = RecipeType.CRAFTING;
if (lv.size() > 1) if (lv.size() > 1)
{ {
String recipeType = lv.get(1).getString(); String recipeType = lv.get(1).getString();
@@ -113,30 +114,44 @@ public class Inventories
throw new InternalExpressionException("Unknown recipe type: " + recipeType); 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()) if (recipes.isEmpty())
{ {
return Value.NULL; return Value.NULL;
} }
List<Value> recipesOutput = new ArrayList<>(); List<Value> recipesOutput = new ArrayList<>();
RegistryAccess regs = cc.registryAccess(); RegistryAccess regs = cc.registryAccess();
SlotDisplay.ResolutionContext context = SlotDisplay.ResolutionContext.forLevel(cc.level());
for (Recipe<?> recipe : recipes) 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<>(); List<Value> ingredientValue = new ArrayList<>();
recipe.placementInfo().slotInfo().forEach(ingredient -> { for (Optional<PlacementInfo.SlotInfo> info : recipe.placementInfo().slotInfo())
if (ingredient.isEmpty()) {
if (info.isEmpty())
{ {
ingredientValue.add(Value.NULL); ingredientValue.add(Value.NULL);
return; continue;
} }
PlacementInfo.SlotInfo value = ingredient.get(); PlacementInfo.SlotInfo value = info.get();
int position = value.placerOutputPosition(); int ingredientIndex = value.placerOutputPosition();
List<Value> alternatives = new ArrayList<>(); 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)); ingredientValue.add(ListValue.wrap(alternatives));
}); }
}
Value recipeSpec; Value recipeSpec;
if (recipe instanceof ShapedRecipe shapedRecipe) if (recipe instanceof ShapedRecipe shapedRecipe)
@@ -155,8 +170,8 @@ public class Inventories
{ {
recipeSpec = ListValue.of( recipeSpec = ListValue.of(
new StringValue("smelting"), new StringValue("smelting"),
new NumericValue(abstractCookingRecipe.getCookingTime()), new NumericValue(abstractCookingRecipe.cookingTime()),
new NumericValue(abstractCookingRecipe.getExperience()) new NumericValue(abstractCookingRecipe.experience())
); );
} }
else if (recipe instanceof SingleItemRecipe) else if (recipe instanceof SingleItemRecipe)
@@ -172,7 +187,7 @@ public class Inventories
recipeSpec = ListValue.of(new StringValue("custom")); 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); return ListValue.wrap(recipesOutput);
}); });
@@ -181,10 +196,11 @@ public class Inventories
{ {
String itemStr = v.get(0).getString(); String itemStr = v.get(0).getString();
ResourceLocation id = InputValidator.identifierOf(itemStr); 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 item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM));
Item reminder = item.getCraftingRemainingItem(); ItemStack reminder = item.getCraftingRemainder();
return reminder == null ? Value.NULL : NBTSerializableValue.nameFromRegistryId(registry.getKey(reminder)); return reminder.isEmpty() ? Value.NULL : ValueConversions.of(reminder, cc.registryAccess());
}); });
expression.addContextFunction("inventory_size", -1, (c, t, lv) -> expression.addContextFunction("inventory_size", -1, (c, t, lv) ->
@@ -55,7 +55,6 @@ import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.advancements.critereon.MinMaxBounds;
import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@@ -204,12 +203,8 @@ public abstract class CommandArgument
// resource / identifier section // resource / identifier section
new VanillaUnconfigurableArgument("recipe", ResourceLocationArgument::id, new VanillaUnconfigurableArgument("recipe", Registries.RECIPE),
(c, p) -> ValueConversions.of(ResourceLocationArgument.getRecipe(c, p).id()), SuggestionProviders.ALL_RECIPES new VanillaUnconfigurableArgument("advancement", Registries.ADVANCEMENT),
),
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("lootcondition", ResourceLocationArgument::id, 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) (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.MinecraftServerInterface;
import carpet.fakes.MobEntityInterface; import carpet.fakes.MobEntityInterface;
import carpet.fakes.RandomStateVisitorAccessor; import carpet.fakes.RandomStateVisitorAccessor;
import carpet.fakes.RecipeManagerInterface;
import carpet.fakes.AbstractContainerMenuInterface; import carpet.fakes.AbstractContainerMenuInterface;
import carpet.fakes.ServerPlayerInterface; import carpet.fakes.ServerPlayerInterface;
import carpet.fakes.ServerPlayerInteractionManagerInterface; import carpet.fakes.ServerPlayerInteractionManagerInterface;
import carpet.fakes.ServerWorldInterface; import carpet.fakes.ServerWorldInterface;
import carpet.fakes.SpawnHelperInnerInterface; import carpet.fakes.SpawnHelperInnerInterface;
import carpet.fakes.ThreadedAnvilChunkStorageInterface;
import carpet.mixins.Objective_scarpetMixin; import carpet.mixins.Objective_scarpetMixin;
import carpet.mixins.PoiRecord_scarpetMixin; import carpet.mixins.PoiRecord_scarpetMixin;
import carpet.mixins.Scoreboard_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.CommandSourceStack;
import net.minecraft.commands.arguments.blocks.BlockInput; import net.minecraft.commands.arguments.blocks.BlockInput;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager; 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.entity.item.ItemEntity;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.DataSlot; 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.ChunkPos;
import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.NaturalSpawner; 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.Scoreboard;
import net.minecraft.world.scores.criteria.ObjectiveCriteria; import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -107,11 +97,6 @@ public class Vanilla
return Map.of(); //return ((ThreadedAnvilChunkStorageInterface) chunkMap).regenerateChunkRegion(requestedChunks); 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() public static int NaturalSpawner_MAGIC_NUMBER()
{ {
return SpawnReporter.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.core.registries.Registries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag; 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.ClientboundSetExperiencePacket;
import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket; import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket;
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
@@ -922,7 +924,7 @@ public class EntityValue extends Value
} }
else 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.behavior.PositionTracker;
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities;
import net.minecraft.world.entity.ai.memory.WalkTarget; import net.minecraft.world.entity.ai.memory.WalkTarget;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@@ -99,12 +100,17 @@ public class ValueConversions
public static Value of(ItemStack stack, RegistryAccess regs) public static Value of(ItemStack stack, RegistryAccess regs)
{ {
return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of( 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()), new NumericValue(stack.getCount()),
NBTSerializableValue.fromStack(stack, regs) 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) public static Value of(Objective objective)
{ {
return ListValue.of( return ListValue.of(
-1
View File
@@ -151,7 +151,6 @@
"CommandDispatcher_scarpetCommandsMixin", "CommandDispatcher_scarpetCommandsMixin",
"FoodData_scarpetMixin", "FoodData_scarpetMixin",
"RecipeManager_scarpetMixin",
"BlockInput_scarpetMixin", "BlockInput_scarpetMixin",
"BlockPredicate_scarpetMixin", "BlockPredicate_scarpetMixin",
"TagPredicate_scarpetMixin", "TagPredicate_scarpetMixin",