diff --git a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java index cd5a74823..0b617c989 100644 --- a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java +++ b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java @@ -8,6 +8,7 @@ import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.TinkersConstruct; import com.cleanroommc.groovyscript.compat.vanilla.VanillaModule; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.StandardInfoParserRegistry; import com.cleanroommc.groovyscript.core.mixin.DefaultResourcePackAccessor; import com.cleanroommc.groovyscript.documentation.Documentation; import com.cleanroommc.groovyscript.documentation.linkgenerator.LinkGeneratorHooks; @@ -163,6 +164,7 @@ public static void initializeRunConfig(File minecraftHome) { public static void initializeGroovyPreInit() { // called via mixin in between construction and fml pre init ObjectMapperManager.init(); + StandardInfoParserRegistry.init(); VanillaModule.initializeBinding(); ModSupport.init(); for (ObjectMapper goh : ObjectMapperManager.getObjectMappers()) { diff --git a/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParser.java b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParser.java new file mode 100644 index 000000000..3c252e47d --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParser.java @@ -0,0 +1,44 @@ +package com.cleanroommc.groovyscript.api.infocommand; + +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextFormatting; + +public interface InfoParser { + + /** + * The style for any parser header - bold and light purple. + */ + Style headerStyle = new Style().setColor(TextFormatting.WHITE).setBold(true); + + /** + * Priority of the parser for determining the order they are logged in chat, + * with lowest being first and highest being last. + * The is 100, and {@link com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserItem#priority()} is set to 1. + * + * @return the priority of the Parser + */ + int priority(); + + /** + * The id used to determine what modes are active when running the command. + * Displayed in-game as part of the allowed argument list for the command. + * + * @return id of the parser + */ + String id(); + + /** + * Checks if the parser is enabled and parses it if it is. + * Regardless of if {@code enabled} is {@code true}, the parser should first check + * to see if {@link #id()} is disabled via a {@code -} prefix and should run if it was disabled. + * Then, it should check if {@link #id()} was enabled, and run if it was or if the method is enabled by default. + * Typically, {@code enabled} will be {@code true} if there are no arguments, the arguments included "{@code all}", + * or all arguments started with {@code -} to negate a specific parser being enabled. + * + * @param info the info package, containing all the information of the command + * @param enabled if this should always be parsed + * @see InfoParserPackage + */ + void parse(InfoParserPackage info, boolean enabled); + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java new file mode 100644 index 000000000..8791006ce --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java @@ -0,0 +1,181 @@ +package com.cleanroommc.groovyscript.api.infocommand; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Created when /gs info is executed + */ +public class InfoParserPackage { + + /** + * Server where the command is executed + */ + @NotNull + private final MinecraftServer server; + /** + * Player who executes the command + */ + @NotNull + private final EntityPlayer player; + /** + * Arguments of the command + */ + @NotNull + private final List args; + /** + * A list of messages that will be sent to the player after this event. + * Add or remove your messages here. + */ + @NotNull + private final List messages; + /** + * If pretty nbt is enabled + */ + private final boolean prettyNbt; + /** + * The held item or the item form of the block being looked at. + */ + @NotNull + private ItemStack stack; + /** + * The entity the player is looking at + */ + @Nullable + private Entity entity; + /** + * The block position the player is looking at + */ + @Nullable + private BlockPos pos; + /** + * The block state of the held item or the block state the player is looking at + */ + @Nullable + private IBlockState blockState; + /** + * The block of the held item or the block the player is looking at + */ + @Nullable + private Block block; + /** + * The tile entity the player is looking at + */ + @Nullable + private TileEntity tileEntity; + + public InfoParserPackage( + @NotNull MinecraftServer server, + @NotNull EntityPlayer player, + @NotNull List args, + @NotNull List messages, + boolean prettyNbt + ) { + this.server = server; + this.player = player; + this.args = args; + this.messages = messages; + this.stack = ItemStack.EMPTY; + this.prettyNbt = prettyNbt; + } + + public @NotNull MinecraftServer getServer() { + return server; + } + + public @NotNull EntityPlayer getPlayer() { + return player; + } + + public @NotNull List getArgs() { + return args; + } + + public @NotNull List getMessages() { + return messages; + } + + public @NotNull ItemStack getStack() { + return stack; + } + + public void setStack(@NotNull ItemStack stack) { + this.stack = stack; + } + + public boolean isPrettyNbt() { + return prettyNbt; + } + + public @Nullable Entity getEntity() { + return entity; + } + + public void setEntity(@Nullable Entity entity) { + this.entity = entity; + } + + public @Nullable BlockPos getPos() { + return pos; + } + + public void setPos(@Nullable BlockPos pos) { + this.pos = pos; + } + + public @Nullable IBlockState getBlockState() { + return blockState; + } + + public void setBlockState(@Nullable IBlockState blockState) { + this.blockState = blockState; + } + + public @Nullable Block getBlock() { + return block; + } + + public void setBlock(@Nullable Block block) { + this.block = block; + } + + public @Nullable TileEntity getTileEntity() { + return tileEntity; + } + + public void setTileEntity(@Nullable TileEntity tileEntity) { + this.tileEntity = tileEntity; + } + + public void copyFromPos(BlockPos pos) { + if (pos == null) return; + this.pos = pos; + this.blockState = player.world.getBlockState(pos); + this.block = blockState.getBlock(); + this.tileEntity = player.world.getTileEntity(pos); + + this.stack = block.getPickBlock(blockState, Minecraft.getMinecraft().objectMouseOver, player.world, pos, player); + if (this.stack.isEmpty()) this.stack = new ItemStack(block, 1, block.getMetaFromState(blockState)); + } + + public void parse() { + parse(false); + } + + public void parse(boolean enabled) { + InfoParserRegistry.getInfoParsers().forEach(x -> x.parse(this, enabled)); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserRegistry.java b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserRegistry.java new file mode 100644 index 000000000..7b3ea9542 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserRegistry.java @@ -0,0 +1,24 @@ +package com.cleanroommc.groovyscript.api.infocommand; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class InfoParserRegistry { + + private static final List INFO_PARSERS = new ArrayList<>(); + + public static void addInfoParser(InfoParser command) { + INFO_PARSERS.add(command); + } + + public static List getInfoParsers() { + return INFO_PARSERS.stream().sorted(Comparator.comparing(InfoParser::priority)).collect(Collectors.toList()); + } + + public static List getIds() { + return INFO_PARSERS.stream().sorted(Comparator.comparing(InfoParser::priority)).map(InfoParser::id).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java new file mode 100644 index 000000000..a9100527f --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java @@ -0,0 +1,150 @@ +package com.cleanroommc.groovyscript.command; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; +import com.cleanroommc.groovyscript.event.GsHandEvent; +import com.google.common.base.Predicates; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.EntitySelectors; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.common.MinecraftForge; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class BaseInfoCommand extends CommandBase { + + /** + * gets the block being looked at, stopping on fluid blocks + */ + protected static BlockPos getBlockLookingAt(EntityPlayer player) { + double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); + Vec3d eyes = player.getPositionEyes(0.0F); + Vec3d look = player.getLook(0.0F); + Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); + + RayTraceResult result = player.getEntityWorld().rayTraceBlocks(eyes, end, true); + if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { + return result.getBlockPos(); + } + return null; + } + + /** + * gets the closest entity being looked at + */ + protected static Entity getEntityLookingAt(EntityPlayer player) { + Entity entity = null; + double d0 = 0.0D; + + double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); + Vec3d eyes = player.getPositionEyes(0.0F); + Vec3d look = player.getLook(0.0F); + Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); + + List list = player.world.getEntitiesInAABBexcluding( + player, + player.getEntityBoundingBox() + .expand(look.x * distance, look.y * distance, look.z * distance) + .grow(1.0D, 1.0D, 1.0D), + Predicates.and(EntitySelectors.NOT_SPECTATING, e -> e != null && e.canBeCollidedWith())); + + for (Entity entity1 : list) { + AxisAlignedBB axisalignedbb = entity1.getEntityBoundingBox().grow(0.3); + RayTraceResult raytraceresult = axisalignedbb.calculateIntercept(eyes, end); + + if (raytraceresult != null) { + double d1 = eyes.squareDistanceTo(raytraceresult.hitVec); + if (d1 < d0 || d0 == 0.0D) { + entity = entity1; + d0 = d1; + } + } + } + return entity; + } + + @Override + public @NotNull String getUsage(@NotNull ICommandSender sender) { + return String.format("/gs %s [all, pretty, %s, %s]", + getName(), + String.join(", ", InfoParserRegistry.getIds()), + InfoParserRegistry.getIds().stream().map(x -> "-" + x).collect(Collectors.joining(", "))); + } + + @Override + public int getRequiredPermissionLevel() { + return 0; + } + + @Override + public @NotNull List getTabCompletions(@NotNull MinecraftServer server, @NotNull ICommandSender sender, String @NotNull [] args, + @Nullable BlockPos targetPos) { + List enabledModes = new ArrayList<>(); + enabledModes.add("all"); + enabledModes.add("pretty"); + InfoParserRegistry.getIds().forEach(x -> enabledModes.add("-" + x)); + enabledModes.addAll(InfoParserRegistry.getIds()); + Arrays.stream(args).map(String::toLowerCase).forEach(enabledModes::remove); + return getListOfStringsMatchingLastWord(args, enabledModes); + } + + abstract String targetDescription(); + + protected void print(EntityPlayer player, List messages, List argList) { + if (messages.isEmpty()) { + if (argList.isEmpty()) { + player.sendMessage(new TextComponentString(String.format("Couldn't find %s!", targetDescription())).setStyle(new Style().setColor(TextFormatting.RED))); + } else { + player.sendMessage(new TextComponentString(String.format("Couldn't find %s matching the given arguments!", targetDescription())).setStyle(new Style().setColor(TextFormatting.RED))); + player.sendMessage(new TextComponentString("The following arguments were provided: " + String.join(", ", argList))); + } + } else { + // have a horizontal bar to improve readability when running multiple consecutive info commands + player.sendMessage(new TextComponentString("================================").setStyle(new Style().setColor(TextFormatting.GOLD))); + messages.forEach(player::sendMessage); + } + } + + abstract void gatherInfo(InfoParserPackage info, EntityPlayer player); + + @Override + public void execute(@NotNull MinecraftServer server, @NotNull ICommandSender sender, String @NotNull [] args) { + if (sender instanceof EntityPlayer player) { + List messages = new ArrayList<>(); + + // get all distinct arguments + List argList = Arrays.stream(args).distinct().collect(Collectors.toList()); + + // if there are 0 args, the args contain "all", or all the args are negative and disabling a specific feature, we want to print every option + boolean enabled = args.length == 0 || argList.contains("all") || argList.stream().allMatch(x -> x.startsWith("-") || "pretty".equals(x)); + + InfoParserPackage info = new InfoParserPackage(server, player, argList, messages, argList.contains("pretty")); + + // add different data to the info parser depending on the command being used + gatherInfo(info, player); + + GsHandEvent event = new GsHandEvent(info); + MinecraftForge.EVENT_BUS.post(event); + + info.parse(enabled); + print(player, messages, argList); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java index f8b0fddcb..c113453c8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java +++ b/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java @@ -5,47 +5,26 @@ import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.compat.mods.jei.JeiPlugin; import com.cleanroommc.groovyscript.documentation.Documentation; -import com.cleanroommc.groovyscript.event.GsHandEvent; import com.cleanroommc.groovyscript.network.NetworkHandler; import com.cleanroommc.groovyscript.network.SReloadScripts; import com.cleanroommc.groovyscript.sandbox.LoadStage; -import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; import net.minecraft.command.ICommandSender; import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.Style; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.HoverEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.server.command.CommandTreeBase; import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import java.io.File; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; public class GSCommand extends CommandTreeBase { @@ -82,72 +61,10 @@ public GSCommand() { addSubcommand(new PackmodeCommand()); - addSubcommand(new SimpleCommand("hand", (server, sender, args) -> { - if (sender instanceof EntityPlayer player) { - ItemStack stack = player.getHeldItem(EnumHand.MAIN_HAND); - if (stack.isEmpty()) stack = player.getHeldItem(EnumHand.OFF_HAND); - BlockPos pos = null; - IBlockState blockState = null; - Block block = null; - if (stack.isEmpty()) { - pos = getBlockLookingAt(player); - if (pos == null) return; - blockState = player.world.getBlockState(pos); - block = blockState.getBlock(); - stack = new ItemStack(block, 1, block.getMetaFromState(blockState)); - } - - List messages = new ArrayList<>(); - - if (stack.getItem() instanceof ItemBlock) { - block = ((ItemBlock) stack.getItem()).getBlock(); - blockState = block.getStateFromMeta(stack.getMetadata()); - } - - boolean prettyNbt = false; - for (String arg : args) { - if ("pretty".equals(arg) || "-p".equals(arg)) { - prettyNbt = true; - break; - } - } - - // add the item and oredict info - GSHandCommand.itemInformation(messages, stack, prettyNbt); - GSHandCommand.oredictInformation(messages, stack); - - // if the item holds fluids, add that info - if (stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)) { - IFluidHandler handler = stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); - if (handler != null) { - GSHandCommand.fluidInformation(messages, Arrays.stream(handler.getTankProperties()) - .map(IFluidTankProperties::getContents) - .filter(Objects::nonNull) - .collect(Collectors.toList()), prettyNbt); - } - } - - if (blockState != null) { - // if the block is a fluid, add the fluid's info - Fluid fluid = FluidRegistry.lookupFluidForBlock(block); - if (fluid != null) { - GSHandCommand.fluidInformation(messages, new FluidStack(fluid, 1000), prettyNbt); - } - - GSHandCommand.blockStateInformation(messages, blockState); - } - - TileEntity tileEntity = pos != null ? player.world.getTileEntity(pos) : null; - if (tileEntity != null) { - GSHandCommand.tileInformation(messages, tileEntity); - } - GsHandEvent event = new GsHandEvent(server, player, args, messages, stack, blockState, block, tileEntity); - MinecraftForge.EVENT_BUS.post(event); - for (ITextComponent msg : event.messages) { - player.sendMessage(msg); - } - } - })); + addSubcommand(new InfoInfoCommand()); + addSubcommand(new InfoHandCommand()); + addSubcommand(new InfoLookingCommand()); + addSubcommand(new InfoSelfCommand()); addSubcommand(new SimpleCommand("wiki", (server, sender, args) -> sender.sendMessage(new TextComponentString("GroovyScript wiki") @@ -232,16 +149,4 @@ public static ITextComponent getTextForFile(String name, String path, ITextCompo .setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverText))); } - private static BlockPos getBlockLookingAt(EntityPlayer player) { - double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); - Vec3d eyes = player.getPositionEyes(0.0F); - Vec3d look = player.getLook(0.0F); - Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); - - RayTraceResult result = player.getEntityWorld().rayTraceBlocks(eyes, end, true); - if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { - return result.getBlockPos(); - } - return null; - } } diff --git a/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java deleted file mode 100644 index 5f4a8595e..000000000 --- a/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.cleanroommc.groovyscript.command; - -import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; -import com.cleanroommc.groovyscript.helper.ingredient.NbtHelper; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.Style; -import net.minecraft.util.text.TextComponentString; -import net.minecraft.util.text.TextFormatting; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.oredict.OreDictionary; -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -/** - * Creates and sends information to the player for the `/gs hand` command - * Used in {@link GSCommand} - */ -public class GSHandCommand { - - public static void itemInformation(List messages, @NotNull ItemStack stack, boolean prettyNbt) { - String itemPretty = IngredientHelper.asGroovyCode(stack, true, prettyNbt); - String item = IngredientHelper.asGroovyCode(stack, false, prettyNbt); - - messages.add(new TextComponentString("Item:") - .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true))); - messages.add(TextCopyable.string(item, " - " + itemPretty).build()); - GuiScreen.setClipboardString(item); - String copy = stack.getItem().getTranslationKey(stack); - - messages.add(new TextComponentString("Translation key:") - .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true))); - - messages.add(TextCopyable.string(copy, " - " + TextFormatting.YELLOW + copy).build()); - } - - public static void blockStateInformation(List messages, @NotNull IBlockState state) { - String copyText = IngredientHelper.asGroovyCode(state, false); - messages.add(new TextComponentString("Block state:") - .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true))); - messages.add(TextCopyable.string(copyText, " - " + IngredientHelper.asGroovyCode(state, true)).build()); - } - - public static void fluidInformation(List messages, @NotNull FluidStack stack, boolean prettyNbt) { - fluidInformation(messages, Collections.singletonList(stack), prettyNbt); - } - - public static void fluidInformation(List messages, @NotNull List fluidStacks, boolean prettyNbt) { - if (fluidStacks.isEmpty()) return; - messages.add(new TextComponentString("Fluids:") - .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true))); - - for (FluidStack stack : fluidStacks) { - String copyText = IngredientHelper.asGroovyCode(stack, false, prettyNbt); - messages.add(TextCopyable.string(copyText, " - " + IngredientHelper.asGroovyCode(stack, true, false)).build()); - } - } - - public static void oredictInformation(List messages, ItemStack stack) { - String s; - int[] ids = OreDictionary.getOreIDs(stack); - if (ids.length > 0) { - messages.add(new TextComponentString("Ore Dictionaries:") - .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true))); - for (int id : ids) { - String oreName = OreDictionary.getOreName(id); - s = IngredientHelper.asGroovyCode(oreName, true); - - messages.add(TextCopyable.string(s, " - \u00A7b" + oreName).build()); - } - } - } - - public static void tileInformation(List messages, TileEntity tile) { - NBTTagCompound nbt = tile.serializeNBT(); - String copyText = NbtHelper.toGroovyCode(nbt, false, false); - String msg = NbtHelper.toGroovyCode(nbt, true, true); - int trimLocation = StringUtils.ordinalIndexOf(msg, "\n", 8); - - messages.add(new TextComponentString("Tile NBT:") - .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true))); - messages.add(TextCopyable.string(copyText, trimLocation == -1 ? msg : msg.substring(0, trimLocation) + "\n\u00A7c(trimmed)").build()); - } -} diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java new file mode 100644 index 000000000..8e7cef6ae --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java @@ -0,0 +1,32 @@ +package com.cleanroommc.groovyscript.command; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.util.EnumHand; +import org.jetbrains.annotations.NotNull; + +public class InfoHandCommand extends BaseInfoCommand { + + @Override + public @NotNull String getName() { + return "hand"; + } + + @Override + protected String targetDescription() { + return "anything in your hands"; + } + + @Override + void gatherInfo(InfoParserPackage info, EntityPlayer player) { + info.setStack(player.getHeldItem(EnumHand.MAIN_HAND)); + if (info.getStack().isEmpty()) info.setStack(player.getHeldItem(EnumHand.OFF_HAND)); + + if (info.getStack().getItem() instanceof ItemBlock itemBlock) { + info.setBlock(itemBlock.getBlock()); + info.setBlockState(itemBlock.getBlock().getStateFromMeta(info.getStack().getMetadata())); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java new file mode 100644 index 000000000..7103b26e5 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java @@ -0,0 +1,42 @@ +package com.cleanroommc.groovyscript.command; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.util.EnumHand; +import org.jetbrains.annotations.NotNull; + +public class InfoInfoCommand extends BaseInfoCommand { + + @Override + public @NotNull String getName() { + return "info"; + } + + @Override + protected String targetDescription() { + return "anything in your hands or being looked at"; + } + + @Override + void gatherInfo(InfoParserPackage info, EntityPlayer player) { + info.setStack(player.getHeldItem(EnumHand.MAIN_HAND)); + if (info.getStack().isEmpty()) info.setStack(player.getHeldItem(EnumHand.OFF_HAND)); + + // if there's nothing in the player's hands, get the entity being looked at and then the block position + // because entity should be preferred + if (info.getStack().isEmpty()) { + info.setEntity(getEntityLookingAt(player)); + if (info.getEntity() == null) { + info.copyFromPos(getBlockLookingAt(player)); + if (info.getPos() == null) { + info.setEntity(player); + } + } + } else if (info.getStack().getItem() instanceof ItemBlock itemBlock) { + info.setBlock(itemBlock.getBlock()); + info.setBlockState(itemBlock.getBlock().getStateFromMeta(info.getStack().getMetadata())); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java new file mode 100644 index 000000000..4106988ff --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java @@ -0,0 +1,28 @@ +package com.cleanroommc.groovyscript.command; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import net.minecraft.entity.player.EntityPlayer; +import org.jetbrains.annotations.NotNull; + +public class InfoLookingCommand extends BaseInfoCommand { + + @Override + public @NotNull String getName() { + return "looking"; + } + + @Override + protected String targetDescription() { + return "anything being looked at"; + } + + @Override + void gatherInfo(InfoParserPackage info, EntityPlayer player) { + // get the entity being looked at and then the block position because entity should be preferred + info.setEntity(getEntityLookingAt(player)); + if (info.getEntity() == null) { + info.copyFromPos(getBlockLookingAt(player)); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoSelfCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoSelfCommand.java new file mode 100644 index 000000000..d19f2a176 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoSelfCommand.java @@ -0,0 +1,24 @@ +package com.cleanroommc.groovyscript.command; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import net.minecraft.entity.player.EntityPlayer; +import org.jetbrains.annotations.NotNull; + +public class InfoSelfCommand extends BaseInfoCommand { + + @Override + public @NotNull String getName() { + return "self"; + } + + @Override + protected String targetDescription() { + return "anything targeting yourself"; + } + + @Override + void gatherInfo(InfoParserPackage info, EntityPlayer player) { + info.setEntity(player); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Alchemistry.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Alchemistry.java index c00701056..e423fae86 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Alchemistry.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Alchemistry.java @@ -5,8 +5,10 @@ import al132.alchemistry.chemistry.CompoundRegistry; import al132.alchemistry.chemistry.ElementRegistry; import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import net.minecraft.item.ItemStack; public class Alchemistry extends GroovyPropertyContainer { @@ -20,6 +22,14 @@ public class Alchemistry extends GroovyPropertyContainer { // TODO: // Compound Creation and Element Creation + public static String asGroovyCode(ChemicalCompound compound, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("element", compound.getName(), colored); + } + + public static String asGroovyCode(ChemicalElement element, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("element", element.getName(), colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("element", ItemStack.class) @@ -40,5 +50,8 @@ public void initialize(GroovyContainer container) { .completerOfNamed(ElementRegistry.INSTANCE::getAllElements, ChemicalElement::getName) .docOfType("chemical element or compound as item stack") .register(); + + InfoParserRegistry.addInfoParser(InfoParserElement.instance); + InfoParserRegistry.addInfoParser(InfoParserCompound.instance); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/InfoParserCompound.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/InfoParserCompound.java new file mode 100644 index 000000000..845e0b7cf --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/InfoParserCompound.java @@ -0,0 +1,39 @@ +package com.cleanroommc.groovyscript.compat.mods.alchemistry; + +import al132.alchemistry.chemistry.ChemicalCompound; +import al132.alchemistry.chemistry.CompoundRegistry; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class InfoParserCompound extends GenericInfoParser { + + public static final InfoParserCompound instance = new InfoParserCompound(); + + @Override + public String id() { + return "compound"; + } + + @Override + public String name() { + return "Compound"; + } + + @Override + public String text(@NotNull ChemicalCompound entry, boolean colored, boolean prettyNbt) { + return Alchemistry.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + for (ChemicalCompound x : CompoundRegistry.INSTANCE.compounds()) { + if (ItemStack.areItemsEqual(x.toItemStack(1), info.getStack())) { + instance.add(info.getMessages(), x, info.isPrettyNbt()); + } + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/InfoParserElement.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/InfoParserElement.java new file mode 100644 index 000000000..faa277cfc --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/InfoParserElement.java @@ -0,0 +1,39 @@ +package com.cleanroommc.groovyscript.compat.mods.alchemistry; + +import al132.alchemistry.chemistry.ChemicalElement; +import al132.alchemistry.chemistry.ElementRegistry; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class InfoParserElement extends GenericInfoParser { + + public static final InfoParserElement instance = new InfoParserElement(); + + @Override + public String id() { + return "element"; + } + + @Override + public String name() { + return "Element"; + } + + @Override + public String text(@NotNull ChemicalElement entry, boolean colored, boolean prettyNbt) { + return Alchemistry.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + for (ChemicalElement x : ElementRegistry.INSTANCE.getAllElements()) { + if (ItemStack.areItemsEqual(x.toItemStack(1), info.getStack())) { + instance.add(info.getMessages(), x, info.isPrettyNbt()); + } + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/AppliedEnergistics2.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/AppliedEnergistics2.java index fdaafb371..17a160698 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/AppliedEnergistics2.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/AppliedEnergistics2.java @@ -2,8 +2,10 @@ import appeng.api.config.TunnelType; import com.cleanroommc.groovyscript.api.IObjectParser; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import java.util.Arrays; import java.util.Locale; @@ -16,6 +18,10 @@ public class AppliedEnergistics2 extends GroovyPropertyContainer { public final Spatial spatial = new Spatial(); public final Attunement attunement = new Attunement(); + public static String asGroovyCode(TunnelType tunnel, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("tunnel", tunnel.name().toLowerCase(Locale.ROOT), colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("tunnel", TunnelType.class) @@ -23,5 +29,7 @@ public void initialize(GroovyContainer container) { .completerOfNamed(() -> Arrays.asList(TunnelType.values()), v -> v.name().toUpperCase(Locale.ROOT)) .docOfType("P2P tunnel type") .register(); + + InfoParserRegistry.addInfoParser(InfoParserTunnel.instance); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/InfoParserTunnel.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/InfoParserTunnel.java new file mode 100644 index 000000000..25e6c1a71 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/appliedenergistics2/InfoParserTunnel.java @@ -0,0 +1,39 @@ +package com.cleanroommc.groovyscript.compat.mods.appliedenergistics2; + +import appeng.api.AEApi; +import appeng.api.config.TunnelType; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import org.jetbrains.annotations.NotNull; + +public class InfoParserTunnel extends GenericInfoParser { + + public static final InfoParserTunnel instance = new InfoParserTunnel(); + + @Override + public String id() { + return "tunnel"; + } + + @Override + public String name() { + return "Tunnel Attunement Type"; + } + + @Override + public String text(@NotNull TunnelType entry, boolean colored, boolean prettyNbt) { + return AppliedEnergistics2.asGroovyCode(entry, colored); + } + + @SuppressWarnings("ConstantValue") + @Override + public void parse(InfoParserPackage info) { +// if (info.getBlock()) + if (info.getStack().isEmpty()) return; + + TunnelType tunnelType = AEApi.instance().registries().p2pTunnel().getTunnelTypeByItem(info.getStack()); + if (tunnelType == null) return; + instance.add(info.getMessages(), tunnelType, info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/AstralSorcery.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/AstralSorcery.java index 6fc9c7e76..9c75a2cd8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/AstralSorcery.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/AstralSorcery.java @@ -2,6 +2,7 @@ import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; import com.cleanroommc.groovyscript.compat.mods.astralsorcery.crystal.CrystalItemStackExpansion; @@ -9,6 +10,7 @@ import com.cleanroommc.groovyscript.compat.mods.astralsorcery.perktree.PerkTreeConfig; import com.cleanroommc.groovyscript.compat.mods.astralsorcery.starlightaltar.StarlightAltar; import com.cleanroommc.groovyscript.core.mixin.astralsorcery.ConstellationRegistryAccessor; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; import hellfirepvp.astralsorcery.common.constellation.IConstellation; @@ -34,6 +36,10 @@ public class AstralSorcery extends GroovyPropertyContainer { public final OreChance treasureShrineOreChance = OreChance.treasureShrineRegistry(); public final PerkTreeConfig perkTreeConfig = new PerkTreeConfig(); + public static String asGroovyCode(IConstellation constellation, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("constellation", constellation.getSimpleName(), colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("constellation", IConstellation.class) @@ -49,6 +55,8 @@ public void initialize(GroovyContainer container) { .docOfType("constellation") .register(); ExpansionHelper.mixinClass(ItemStack.class, CrystalItemStackExpansion.class); + + InfoParserRegistry.addInfoParser(InfoParserConstellation.instance); } public static ItemHandle toItemHandle(IIngredient ingredient) { diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/InfoParserConstellation.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/InfoParserConstellation.java new file mode 100644 index 000000000..60ee91109 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/InfoParserConstellation.java @@ -0,0 +1,53 @@ +package com.cleanroommc.groovyscript.compat.mods.astralsorcery; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserTranslationKey; +import hellfirepvp.astralsorcery.common.constellation.IConstellation; +import hellfirepvp.astralsorcery.common.data.DataActiveCelestials; +import hellfirepvp.astralsorcery.common.data.SyncDataHolder; +import hellfirepvp.astralsorcery.common.util.nbt.NBTHelper; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class InfoParserConstellation extends GenericInfoParser { + + public static final InfoParserConstellation instance = new InfoParserConstellation(); + + @Override + public String id() { + return "constellation"; + } + + @Override + public String name() { + return "Constellation"; + } + + @Override + public String text(@NotNull IConstellation entry, boolean colored, boolean prettyNbt) { + return AstralSorcery.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) { + if (info.getEntity() == null) return; + DataActiveCelestials s = SyncDataHolder.getDataClient("AstralConstellations"); + Collection constellations = s.getActiveConstellations(info.getEntity().dimension); + if (constellations == null) return; + instance.add(info.getMessages(), constellations, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), constellations.stream().map(IConstellation::getUnlocalizedName).collect(Collectors.toList()), info.isPrettyNbt()); + return; + } + + if (!NBTHelper.hasPersistentData(info.getStack())) return; + IConstellation constellation = IConstellation.readFromNBT(NBTHelper.getPersistentData(info.getStack())); + if (constellation == null) return; + instance.add(info.getMessages(), constellation, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), constellation.getUnlocalizedName(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java index 175193e9a..9ba97e428 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java @@ -1,8 +1,10 @@ package com.cleanroommc.groovyscript.compat.mods.botania; import com.cleanroommc.groovyscript.api.IObjectParser; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.lexicon.LexiconCategory; import vazkii.botania.api.lexicon.LexiconEntry; @@ -23,6 +25,10 @@ public class Botania extends GroovyPropertyContainer { public final Magnet magnet = new Magnet(); public final Flowers flowers = new Flowers(); + public static String asGroovyCode(vazkii.botania.api.brew.Brew entry, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("brew", entry.getKey(), colored); + } + public Botania() { addProperty(lexicon.category); addProperty(lexicon.entry); @@ -51,5 +57,7 @@ public void initialize(GroovyContainer container) { .defaultValue(() -> BotaniaAPI.fallbackBrew) .docOfType("brew") .register(); + + InfoParserRegistry.addInfoParser(InfoParserBrew.instance); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/InfoParserBrew.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/InfoParserBrew.java new file mode 100644 index 000000000..800540068 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/InfoParserBrew.java @@ -0,0 +1,43 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserTranslationKey; +import net.minecraft.nbt.NBTTagCompound; +import org.jetbrains.annotations.NotNull; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.brew.Brew; + +public class InfoParserBrew extends GenericInfoParser { + + public static final InfoParserBrew instance = new InfoParserBrew(); + + @Override + public String id() { + return "brew"; + } + + @Override + public String name() { + return "Brew"; + } + + @Override + public String text(@NotNull Brew entry, boolean colored, boolean prettyNbt) { + return Botania.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + NBTTagCompound tag = info.getStack().getTagCompound(); + if (tag == null) return; + String key = tag.getString("brewKey"); + if (key.isEmpty()) return; + Brew brew = BotaniaAPI.brewMap.get(key); + if (brew == null) return; + instance.add(info.getMessages(), brew, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), brew.getUnlocalizedName(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java index 808de8951..eae973237 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java @@ -6,7 +6,7 @@ import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription; import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription; import com.cleanroommc.groovyscript.compat.mods.ModSupport; -import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import net.minecraft.item.ItemStack; @@ -60,7 +60,7 @@ public void addVariation(String groupName, ItemStack item) { } catch (UnsupportedOperationException e) { GroovyLog.msg("Error adding a Chisel Carving variation") .add("you cannot add variations to Oredict chisel groups {}", groupName) - .add("instead, edit the oredict via `oredict.add('{}', {})`", groupName, IngredientHelper.asGroovyCode(item, false)) + .add("instead, edit the oredict via `oredict.add('{}', {})`", groupName, GroovyScriptCodeConverter.asGroovyCode(item, false, false)) .error() .post(); } @@ -74,7 +74,7 @@ public void removeVariation(String groupName, ItemStack item) { } catch (UnsupportedOperationException e) { GroovyLog.msg("Error removing a Chisel Carving variation") .add("you cannot remove variations to Oredict chisel groups {}", groupName) - .add("instead, edit the oredict via `oredict.remove('{}', {})`", groupName, IngredientHelper.asGroovyCode(item, false)) + .add("instead, edit the oredict via `oredict.remove('{}', {})`", groupName, GroovyScriptCodeConverter.asGroovyCode(item, false, false)) .error() .post(); } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java index b1992cb66..8d6ca678f 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java @@ -1,8 +1,10 @@ package com.cleanroommc.groovyscript.compat.mods.evilcraft; import com.cleanroommc.groovyscript.api.IObjectParser; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import org.cyclops.evilcraft.core.weather.WeatherType; import java.util.Arrays; @@ -13,6 +15,10 @@ public class EvilCraft extends GroovyPropertyContainer { public final BloodInfuser bloodInfuser = new BloodInfuser(); public final EnvironmentalAccumulator environmentalAccumulator = new EnvironmentalAccumulator(); + public static String asGroovyCode(String weatherType, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("weather", weatherType, colored); + } + @Override public void initialize(GroovyContainer container) { final List weatherTypes = Arrays.asList("any", "clear", "rain", "lightning"); @@ -22,5 +28,7 @@ public void initialize(GroovyContainer container) { .defaultValue(() -> WeatherType.ANY) .docOfType("weather type") .register(); + + InfoParserRegistry.addInfoParser(InfoParserWeather.instance); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/InfoParserWeather.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/InfoParserWeather.java new file mode 100644 index 000000000..611f80c95 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/InfoParserWeather.java @@ -0,0 +1,43 @@ +package com.cleanroommc.groovyscript.compat.mods.evilcraft; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; + +public class InfoParserWeather extends GenericInfoParser { + + public static final InfoParserWeather instance = new InfoParserWeather(); + + @Override + public String id() { + return "weather"; + } + + @Override + public String name() { + return "Weather"; + } + + @Override + public String text(@NotNull String entry, boolean colored, boolean prettyNbt) { + return EvilCraft.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() == null) return; + + World world = info.getEntity().getEntityWorld(); + if (world.isThundering()) { + instance.add(info.getMessages(), "lightning", info.isPrettyNbt()); + return; + } + if (world.isRaining()) { + instance.add(info.getMessages(), "rain", info.isPrettyNbt()); + return; + } + instance.add(info.getMessages(), "clear", info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/InfoParserTab.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/InfoParserTab.java new file mode 100644 index 000000000..836f6d190 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/InfoParserTab.java @@ -0,0 +1,52 @@ +package com.cleanroommc.groovyscript.compat.mods.jei; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.core.mixin.jei.ModRegistryAccessor; +import mezz.jei.api.recipe.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.TextFormatting; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@SuppressWarnings("rawtypes") +public class InfoParserTab extends GenericInfoParser { + + public static final InfoParserTab instance = new InfoParserTab(); + + @Override + public String id() { + return "jeitab"; + } + + @Override + public String name() { + return "JEI Tab Catalyst"; + } + + @Override + public String text(@NotNull IRecipeCategory entry, boolean colored, boolean prettyNbt) { + return colored ? TextFormatting.YELLOW + entry.getUid() : entry.getUid(); + } + + @Override + @SuppressWarnings("rawtypes") + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + + // this gets all categories the item appears on - and there isn't any inbuilt method to get *just* catalysts. + List allowed = ((ModRegistryAccessor) JeiPlugin.modRegistry).getRecipeCatalysts() + .entrySet() + .stream() + .filter(entry -> entry.getValue().stream().anyMatch(x -> x instanceof ItemStack stack && ItemStack.areItemStacksEqual(stack, info.getStack()))) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + List list = JeiPlugin.recipeRegistry.getRecipeCategories(allowed); + + instance.add(info.getMessages(), list, info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/JustEnoughItems.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/JustEnoughItems.java index abb931f2d..66e6172e4 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/JustEnoughItems.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/jei/JustEnoughItems.java @@ -1,5 +1,7 @@ package com.cleanroommc.groovyscript.compat.mods.jei; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; +import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; public class JustEnoughItems extends GroovyPropertyContainer { @@ -9,4 +11,9 @@ public class JustEnoughItems extends GroovyPropertyContainer { public final Description description = new Description(); public final Catalyst catalyst = new Catalyst(); + @Override + public void initialize(GroovyContainer owner) { + InfoParserRegistry.addInfoParser(InfoParserTab.instance); + } + } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/InfoParserGas.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/InfoParserGas.java new file mode 100644 index 000000000..4b98038bb --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/InfoParserGas.java @@ -0,0 +1,43 @@ +package com.cleanroommc.groovyscript.compat.mods.mekanism; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserTranslationKey; +import mekanism.api.gas.GasStack; +import mekanism.api.gas.IGasItem; +import org.jetbrains.annotations.NotNull; + +public class InfoParserGas extends GenericInfoParser { + + public static final InfoParserGas instance = new InfoParserGas(); + + @Override + public String id() { + return "gas"; + } + + @Override + public String name() { + return "Gas"; + } + + @Override + public String plural() { + return "Gases"; + } + + @Override + public String text(@NotNull GasStack entry, boolean colored, boolean prettyNbt) { + return Mekanism.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().getItem() instanceof IGasItem item) { + GasStack stack = item.getGas(info.getStack()); + instance.add(info.getMessages(), stack, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), stack.getGas().getTranslationKey(), info.isPrettyNbt()); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/InfoParserInfusion.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/InfoParserInfusion.java new file mode 100644 index 000000000..00c6cfe06 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/InfoParserInfusion.java @@ -0,0 +1,38 @@ +package com.cleanroommc.groovyscript.compat.mods.mekanism; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserTranslationKey; +import mekanism.api.infuse.InfuseObject; +import mekanism.api.infuse.InfuseRegistry; +import org.jetbrains.annotations.NotNull; + +public class InfoParserInfusion extends GenericInfoParser { + + public static final InfoParserInfusion instance = new InfoParserInfusion(); + + @Override + public String id() { + return "infusion"; + } + + @Override + public String name() { + return "Infusion Type"; + } + + @Override + public String text(@NotNull InfuseObject entry, boolean colored, boolean prettyNbt) { + return Mekanism.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + InfuseObject obj = InfuseRegistry.getObject(info.getStack()); + if (obj == null) return; + instance.add(info.getMessages(), obj, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), obj.type.unlocalizedName, info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Mekanism.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Mekanism.java index b75fd36ef..0fcf32742 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Mekanism.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Mekanism.java @@ -3,14 +3,16 @@ import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.api.IObjectParser; import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import mekanism.api.gas.Gas; import mekanism.api.gas.GasRegistry; import mekanism.api.gas.GasStack; +import mekanism.api.infuse.InfuseObject; import mekanism.api.infuse.InfuseRegistry; import mekanism.api.infuse.InfuseType; -import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Optional; import org.jetbrains.annotations.Nullable; @@ -38,6 +40,37 @@ public class Mekanism extends GroovyPropertyContainer { public final ThermalEvaporationPlant thermalEvaporationPlant = new ThermalEvaporationPlant(); public final Washer washer = new Washer(); + + @Optional.Method(modid = "mekanism") + public static String asGroovyCode(Gas gasStack, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("gas", gasStack.getName(), colored); + } + + @Optional.Method(modid = "mekanism") + public static boolean isGas(IIngredient ingredient) { + return Loader.isModLoaded("mekanism") && ingredient instanceof GasStack; + } + + @Optional.Method(modid = "mekanism") + public static boolean isEmpty(@Nullable GasStack gasStack) { + return gasStack == null || gasStack.getGas() == null || gasStack.amount <= 0; + } + + @Optional.Method(modid = "mekanism") + public static String asGroovyCode(GasStack gasStack, boolean colored) { + return asGroovyCode(gasStack.getGas(), colored) + GroovyScriptCodeConverter.formatMultiple(gasStack.amount, colored); + } + + @Optional.Method(modid = "mekanism") + public static String asGroovyCode(InfuseType infuseType, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("infusionType", infuseType.unlocalizedName, colored); + } + + @Optional.Method(modid = "mekanism") + public static String asGroovyCode(InfuseObject infuseObject, boolean colored) { + return asGroovyCode(infuseObject.type, colored) + GroovyScriptCodeConverter.formatMultiple(infuseObject.stored, colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("gas", GasStack.class) @@ -53,29 +86,9 @@ public void initialize(GroovyContainer container) { .completerOfNames(InfuseRegistry.getInfuseMap()::keySet) .docOfType("infusion type") .register(); - } - - @Optional.Method(modid = "mekanism") - public static boolean isGas(IIngredient ingredient) { - return Loader.isModLoaded("mekanism") && ingredient instanceof GasStack; - } - @Optional.Method(modid = "mekanism") - public static boolean isEmpty(@Nullable GasStack gasStack) { - return gasStack == null || gasStack.getGas() == null || gasStack.amount <= 0; + InfoParserRegistry.addInfoParser(InfoParserGas.instance); + InfoParserRegistry.addInfoParser(InfoParserInfusion.instance); } - @Optional.Method(modid = "mekanism") - public static String asGroovyCode(Gas gasStack, boolean colored) { - StringBuilder builder = new StringBuilder(); - if (colored) builder.append(TextFormatting.DARK_GREEN); - builder.append("gas"); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("('"); - if (colored) builder.append(TextFormatting.AQUA); - builder.append(gasStack.getName()); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("')"); - return builder.toString(); - } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserHerb.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserHerb.java new file mode 100644 index 000000000..d3153ea94 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserHerb.java @@ -0,0 +1,38 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import epicsquid.roots.api.Herb; +import epicsquid.roots.init.HerbRegistry; +import org.jetbrains.annotations.NotNull; + +public class InfoParserHerb extends GenericInfoParser { + + public static final InfoParserHerb instance = new InfoParserHerb(); + + @Override + public String id() { + return "herb"; + } + + @Override + public String name() { + return "Herb"; + } + + @Override + public String text(@NotNull Herb entry, boolean colored, boolean prettyNbt) { + return Roots.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + if (HerbRegistry.isHerb(info.getStack())) { + Herb herb = HerbRegistry.getHerbByItem(info.getStack().getItem()); + if (herb == null) return; + instance.add(info.getMessages(), herb, info.isPrettyNbt()); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserModifier.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserModifier.java new file mode 100644 index 000000000..6536d6d9d --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserModifier.java @@ -0,0 +1,44 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserTranslationKey; +import epicsquid.roots.modifiers.Modifier; +import epicsquid.roots.modifiers.ModifierRegistry; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +public class InfoParserModifier extends GenericInfoParser { + + public static final InfoParserModifier instance = new InfoParserModifier(); + + @Override + public String id() { + return "modifier"; + } + + @Override + public String name() { + return "Modifier"; + } + + @Override + public String text(@NotNull Modifier entry, boolean colored, boolean prettyNbt) { + return Roots.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + NBTTagCompound tag = info.getStack().getTagCompound(); + if (tag == null) return; + String key = tag.getString("modifier"); + if (key.isEmpty()) return; + Modifier modifier = ModifierRegistry.get(new ResourceLocation(key)); + if (modifier == null) return; + instance.add(info.getMessages(), modifier, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), modifier.getTranslationKey(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserSpell.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserSpell.java new file mode 100644 index 000000000..c74eef8bf --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/InfoParserSpell.java @@ -0,0 +1,46 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.InfoParserTranslationKey; +import epicsquid.roots.spell.SpellBase; +import epicsquid.roots.spell.SpellRegistry; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +public class InfoParserSpell extends GenericInfoParser { + + public static final InfoParserSpell instance = new InfoParserSpell(); + + @Override + public String id() { + return "spell"; + } + + @Override + public String name() { + return "Spell"; + } + + @Override + public String text(@NotNull SpellBase entry, boolean colored, boolean prettyNbt) { + return Roots.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + NBTTagCompound tag = info.getStack().getTagCompound(); + if (tag == null) return; + NBTTagCompound spell_storage = tag.getCompoundTag("spell_storage"); + if (spell_storage.isEmpty()) return; + String key = spell_storage.getString("s"); + if (key.isEmpty()) return; + SpellBase spell = SpellRegistry.getSpell(new ResourceLocation(key)); + if (spell == null) return; + instance.add(info.getMessages(), spell, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), spell.getTranslationKey(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java index 282b870a6..0e2f0ec62 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java @@ -2,8 +2,10 @@ import com.cleanroommc.groovyscript.api.IObjectParser; import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.cleanroommc.groovyscript.mapper.ObjectMappers; import epicsquid.roots.api.Herb; import epicsquid.roots.init.HerbRegistry; @@ -39,6 +41,18 @@ public class Roots extends GroovyPropertyContainer { public final SummonCreature summonCreature = new SummonCreature(); public final Transmutation transmutation = new Transmutation(); + public static String asGroovyCode(Herb entry, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("herb", entry.getName(), colored); + } + + public static String asGroovyCode(SpellBase entry, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("spell", entry.getName(), colored); + } + + public static String asGroovyCode(Modifier entry, boolean colored) { + return GroovyScriptCodeConverter.formatResourceLocation("modifier", entry.getRegistryName(), colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("ritual", RitualBase.class) @@ -67,6 +81,10 @@ public void initialize(GroovyContainer container) { .completerOfNamed(ModifierRegistry::getModifiers, v -> v.getRegistryName().toString()) .docOfType("modifier") .register(); + + InfoParserRegistry.addInfoParser(InfoParserHerb.instance); + InfoParserRegistry.addInfoParser(InfoParserSpell.instance); + InfoParserRegistry.addInfoParser(InfoParserModifier.instance); } private static Result getSpell(String s, Object... args) { diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/InfoParserAspect.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/InfoParserAspect.java new file mode 100644 index 000000000..93ae9f539 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/InfoParserAspect.java @@ -0,0 +1,49 @@ +package com.cleanroommc.groovyscript.compat.mods.thaumcraft; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.mods.thaumcraft.aspect.AspectStack; +import com.cleanroommc.groovyscript.compat.vanilla.command.infoparser.GenericInfoParser; +import org.jetbrains.annotations.NotNull; +import thaumcraft.api.aspects.AspectHelper; +import thaumcraft.api.aspects.AspectList; + +import java.util.List; +import java.util.stream.Collectors; + +public class InfoParserAspect extends GenericInfoParser { + + public static final InfoParserAspect instance = new InfoParserAspect(); + + @Override + public String id() { + return "aspect"; + } + + @Override + public String name() { + return "Aspect"; + } + + @Override + public String text(@NotNull AspectStack entry, boolean colored, boolean prettyNbt) { + return Thaumcraft.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() == null && info.getStack().isEmpty()) return; + AspectList list = info.getStack().isEmpty() + ? AspectHelper.getEntityAspects(info.getEntity()) + : AspectHelper.getObjectAspects(info.getStack()); + + if (list == null) return; + + // convert it into groovyscript AspectStack, so we can easily represent quantity + List target = list.aspects.entrySet().stream() + .map(x -> new AspectStack(x.getKey(), x.getValue())) + .collect(Collectors.toList()); + + instance.add(info.getMessages(), target, info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Thaumcraft.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Thaumcraft.java index 8486e1e30..56e8d6da4 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Thaumcraft.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Thaumcraft.java @@ -2,6 +2,7 @@ import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.api.IObjectParser; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; import com.cleanroommc.groovyscript.compat.mods.thaumcraft.arcane.ArcaneWorkbench; @@ -11,6 +12,7 @@ import com.cleanroommc.groovyscript.compat.mods.thaumcraft.aspect.AspectStack; import com.cleanroommc.groovyscript.compat.mods.thaumcraft.warp.Warp; import com.cleanroommc.groovyscript.compat.mods.thaumcraft.warp.WarpItemStackExpansion; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; import net.minecraft.item.ItemStack; import thaumcraft.api.ThaumcraftApiHelper; @@ -32,6 +34,14 @@ public class Thaumcraft extends GroovyPropertyContainer { public final AspectHelper aspectHelper = new AspectHelper(); + public static String asGroovyCode(thaumcraft.api.aspects.Aspect aspect, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("aspect", aspect.getTag(), colored); + } + + public static String asGroovyCode(AspectStack aspectStack, boolean colored) { + return asGroovyCode(aspectStack.getAspect(), colored) + GroovyScriptCodeConverter.formatMultiple(aspectStack.getAmount(), colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("aspect", AspectStack.class) @@ -47,6 +57,8 @@ public void initialize(GroovyContainer container) { .register(); ExpansionHelper.mixinClass(ItemStack.class, AspectItemStackExpansion.class); ExpansionHelper.mixinClass(ItemStack.class, WarpItemStackExpansion.class); + + InfoParserRegistry.addInfoParser(InfoParserAspect.instance); } public static AspectList makeAspectList(Collection aspects) { diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/GenericInfoParser.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/GenericInfoParser.java new file mode 100644 index 000000000..fc4a74eb7 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/GenericInfoParser.java @@ -0,0 +1,216 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParser; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.command.TextCopyable; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.util.text.event.HoverEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public abstract class GenericInfoParser implements InfoParser { + + @Override + public int priority() { + return 100; + } + + /** + * The name of the parser to display in-game. Should be capitalized + * and in the singular form, see {@link #plural()}. + * + * @return the name of the parser + */ + public abstract String name(); + + /** + * The name of the parser to display in-game if the number of entries is greater than 1. + * Defaults to {@link #name()}s. + * + * @return the plural form of the name + */ + public String plural() { + return name() + "s"; + } + + + /** + * A lang key for the text that appears when hovering over the name in chat. + * Defaults to "{@code groovyscript.infoparser.}{@link #id()}" + * + * @return the lang key for the hover text + */ + public String description() { + return String.format("groovyscript.infoparser.%s", id()); + } + + /** + * The text that appears when hovering over the name in chat. + * Typically, a description of the command, with a fallback value of the name. + * + * @return the hover text + * @see #description() + */ + public ITextComponent hoverTitle() { + return new TextComponentTranslation(description()); + } + + /** + * The formatted header of the parser. Uses the {@link #headerStyle}, with hover text from {@link #hoverTitle()}. + * + * @param plural if the name should be in {@link #plural()} or singular {@link #name()} form. + * @return the header for the parser + */ + public ITextComponent header(boolean plural) { + String name = plural ? plural() : name(); + Style style = headerStyle.createShallowCopy().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverTitle())); + return new TextComponentString(name + ":").setStyle(style); + } + + /** + * Adds the header to the message list. + * + * @see #header(boolean) + */ + public void header(List messages, boolean plural) { + messages.add(header(plural)); + } + + /** + * Combines the default {@link #msg} and {@link #copyText} code. + * + * @param entry the entry to be parsed + * @param colored if the text should be colored or not + * @param prettyNbt if nbt data, if any, should be formatted "prettily" + * @return the message that appears in chat and is copied, depending on the value of {@code colored} + */ + public abstract String text(@NotNull T entry, boolean colored, boolean prettyNbt); + + /** + * The text that will display in chat. + * The primary difference from {@link #copyText} is containing formatting codes. + * Typically valid GroovyScript code. + * + * @param entry the entry to be parsed + * @param prettyNbt if nbt data, if any, should be formatted "prettily" + * @return the message that appears in chat + */ + public String msg(@NotNull T entry, boolean prettyNbt) { + return text(entry, true, prettyNbt); + } + + /** + * The text that will be copied when the entry is clicked on. + * The primary difference from {@link #msg} is lacking formatting codes. + * Typically valid GroovyScript code. + * + * @param entry the entry to be parsed + * @param prettyNbt if nbt data, if any, should be formatted "prettily" + * @return the text that is copied when clicking on the message + */ + public String copyText(@NotNull T entry, boolean prettyNbt) { + return text(entry, false, prettyNbt); + } + + /** + * The copyable component that will be added to the message list. + * + * @param copyText the text that is copied when clicking on the message + * @param msg the message that appears in chat + * @return the chat component + */ + public ITextComponent information(String copyText, String msg) { + return TextCopyable.string(copyText, msg).build(); + } + + /** + * The copyable component that will be added to the message list. + * Calls {@link #information(String, String)} with the values from {@link #copyText(Object, boolean)} and {@link #msg(Object, boolean)}. + * Also adds a {@literal - } to the message for formatting reasons. + * + * @param entry the entry to be parsed + * @param prettyNbt if nbt data, if any, should be formatted "prettily" + * @return the chat component + */ + public ITextComponent information(@NotNull T entry, boolean prettyNbt) { + return information(copyText(entry, prettyNbt), " - " + msg(entry, prettyNbt)); + } + + /** + * Iterates through the entries, adding them to the message list as it goes. + * + * @param messages the message list that will be printed to chat + * @param entries a list of the entries to print + * @param prettyNbt if nbt data, if any, should be formatted "prettily" + */ + public void iterate(List messages, @NotNull Iterator entries, boolean prettyNbt) { + while (entries.hasNext()) messages.add(information(entries.next(), prettyNbt)); + } + + /** + * Adds the {@link #header(List, boolean)} and {@link #iterate(List, Iterator, boolean)} to the message list. + * Only does so if the list isn't empty. + * + * @param messages the message list that will be printed to chat + * @param entries a list of the entries to print + * @param prettyNbt if nbt data, if any, should be formatted "prettily" + */ + public void add(List messages, @NotNull Collection entries, boolean prettyNbt) { + if (entries.isEmpty()) return; + header(messages, entries.size() != 1); + iterate(messages, entries.iterator(), prettyNbt); + } + + /** + * Wraps the entry in a singleton list for {@link #add(List, Collection, boolean)}. + * + * @see #add(List, Collection, boolean) + */ + public void add(List messages, @NotNull T entry, boolean prettyNbt) { + add(messages, Collections.singletonList(entry), prettyNbt); + } + + /** + * Parses the {@link InfoParserPackage}, and runs {@link #add} if it passes validation. + * + * @param info the info package, containing all the information of the command + * @see InfoParserPackage + */ + public abstract void parse(InfoParserPackage info); + + /** + * Determines if the parser will be prevented from running. + * Simply checks if {@code -}{@link #id()} is in the args list. + * + * @param args list of arguments passed into the command + * @return if the parser is prevented from being displayed + */ + public boolean blocked(List args) { + return args.contains("-" + id()); + } + + /** + * Determines if the parser will be run. + * Simply checks if {@link #id()} is in the args list. + * + * @param args list of arguments passed into the command + * @return if the parser is allowed to be displayed + */ + public boolean allowed(List args) { + return args.contains(id()); + } + + @Override + public void parse(InfoParserPackage info, boolean enabled) { + if (blocked(info.getArgs())) return; + if (enabled || allowed(info.getArgs())) parse(info); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBiome.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBiome.java new file mode 100644 index 000000000..00236c284 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBiome.java @@ -0,0 +1,33 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.world.biome.Biome; +import org.jetbrains.annotations.NotNull; + +public class InfoParserBiome extends GenericInfoParser { + + public static final InfoParserBiome instance = new InfoParserBiome(); + + @Override + public String id() { + return "biome"; + } + + @Override + public String name() { + return "Biome"; + } + + @Override + public String text(@NotNull Biome entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getPos() == null || info.getEntity() == null) return; + instance.add(info.getMessages(), info.getEntity().getEntityWorld().getBiome(info.getPos()), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBlock.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBlock.java new file mode 100644 index 000000000..e937a3c86 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBlock.java @@ -0,0 +1,34 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.block.Block; +import org.jetbrains.annotations.NotNull; + +public class InfoParserBlock extends GenericInfoParser { + + public static final InfoParserBlock instance = new InfoParserBlock(); + + @Override + public String id() { + return "block"; + } + + @Override + public String name() { + return "Block"; + } + + @Override + public String text(@NotNull Block entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getBlock() == null) return; + instance.add(info.getMessages(), info.getBlock(), info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), info.getBlock().getTranslationKey(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBlockState.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBlockState.java new file mode 100644 index 000000000..ccc5709cb --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserBlockState.java @@ -0,0 +1,33 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.block.state.IBlockState; +import org.jetbrains.annotations.NotNull; + +public class InfoParserBlockState extends GenericInfoParser { + + public static final InfoParserBlockState instance = new InfoParserBlockState(); + + @Override + public String id() { + return "blockstate"; + } + + @Override + public String name() { + return "Block state"; + } + + @Override + public String text(@NotNull IBlockState entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getBlockState() == null) return; + instance.add(info.getMessages(), info.getBlockState(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserCreativeTab.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserCreativeTab.java new file mode 100644 index 000000000..d81fbd2c9 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserCreativeTab.java @@ -0,0 +1,37 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.creativetab.CreativeTabs; +import org.jetbrains.annotations.NotNull; + +public class InfoParserCreativeTab extends GenericInfoParser { + + public static final InfoParserCreativeTab instance = new InfoParserCreativeTab(); + + @Override + public String id() { + return "creativetab"; + } + + @Override + public String name() { + return "Creative Tab"; + } + + @Override + public String text(@NotNull CreativeTabs entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + CreativeTabs tab = info.getStack().getItem().getCreativeTab(); + if (tab != null) { + instance.add(info.getMessages(), tab, info.isPrettyNbt()); + } + + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserDimension.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserDimension.java new file mode 100644 index 000000000..d78a9c89e --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserDimension.java @@ -0,0 +1,33 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.world.DimensionType; +import org.jetbrains.annotations.NotNull; + +public class InfoParserDimension extends GenericInfoParser { + + public static final InfoParserDimension instance = new InfoParserDimension(); + + @Override + public String id() { + return "dimension"; + } + + @Override + public String name() { + return "Dimension"; + } + + @Override + public String text(@NotNull DimensionType entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() == null) return; + instance.add(info.getMessages(), info.getEntity().world.provider.getDimensionType(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserEnchantment.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserEnchantment.java new file mode 100644 index 000000000..ae33fafb7 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserEnchantment.java @@ -0,0 +1,38 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class InfoParserEnchantment extends GenericInfoParser { + + public static final InfoParserEnchantment instance = new InfoParserEnchantment(); + + @Override + public String id() { + return "enchantment"; + } + + @Override + public String name() { + return "Enchantment"; + } + + @Override + public String text(@NotNull Enchantment entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + List list = new ArrayList<>(EnchantmentHelper.getEnchantments(info.getStack()).keySet()); + instance.add(info.getMessages(), list, info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserEntity.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserEntity.java new file mode 100644 index 000000000..2941c6389 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserEntity.java @@ -0,0 +1,46 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLiving; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +public class InfoParserEntity extends GenericInfoParser { + + public static final InfoParserEntity instance = new InfoParserEntity(); + + @Override + public String id() { + return "entity"; + } + + @Override + public String name() { + return "Entity"; + } + + @Override + public String plural() { + return "Entities"; + } + + @Override + public String text(@NotNull Entity entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() == null || !(info.getEntity() instanceof EntityLiving)) return; + instance.add(info.getMessages(), info.getEntity(), info.isPrettyNbt()); + + ResourceLocation rl = EntityList.getKey(info.getEntity()); + if (rl != null) { + InfoParserTranslationKey.instance.add(info.getMessages(), rl.toString(), info.isPrettyNbt()); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserFluid.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserFluid.java new file mode 100644 index 000000000..49992328c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserFluid.java @@ -0,0 +1,67 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class InfoParserFluid extends GenericInfoParser { + + public static final InfoParserFluid instance = new InfoParserFluid(); + + @Override + public String id() { + return "fluid"; + } + + @Override + public String name() { + return "Fluid"; + } + + @Override + public String text(@NotNull FluidStack entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored, prettyNbt); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) { + // if the item holds fluids, add that info + Fluid fluid = FluidRegistry.lookupFluidForBlock(info.getBlock()); + if (fluid == null) return; + FluidStack fluidStack = new FluidStack(fluid, Fluid.BUCKET_VOLUME); + instance.add(info.getMessages(), fluidStack, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), fluidStack.getUnlocalizedName(), info.isPrettyNbt()); + return; + } + // if the item holds fluids, add that info + if (info.getStack().hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)) { + IFluidHandler handler = info.getStack().getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); + if (handler != null) { + List fluids = Arrays.stream(handler.getTankProperties()) + .map(IFluidTankProperties::getContents) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + instance.add(info.getMessages(), fluids, info.isPrettyNbt()); + + List keys = fluids.stream() + .map(FluidStack::getUnlocalizedName) + .collect(Collectors.toList()); + InfoParserTranslationKey.instance.add(info.getMessages(), keys, info.isPrettyNbt()); + } + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserItem.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserItem.java new file mode 100644 index 000000000..7e31aba8a --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserItem.java @@ -0,0 +1,56 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.List; + +public class InfoParserItem extends GenericInfoParser { + + public static final InfoParserItem instance = new InfoParserItem(); + + @Override + public int priority() { + return 1; + } + + @Override + public String id() { + return "item"; + } + + @Override + public String name() { + return "Item"; + } + + @Override + public String text(@NotNull ItemStack entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored, prettyNbt); + } + + @Override + public void iterate(List messages, @NotNull Iterator entries, boolean prettyNbt) { + if (entries.hasNext()) { + ItemStack entry = entries.next(); + messages.add(information(entry, prettyNbt)); + GuiScreen.setClipboardString(copyText(entry, prettyNbt)); + } + while (entries.hasNext()) { + messages.add(information(entries.next(), prettyNbt)); + } + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + instance.add(info.getMessages(), info.getStack(), info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), info.getStack().getTranslationKey(), info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserNBT.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserNBT.java new file mode 100644 index 000000000..b742d7b7c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserNBT.java @@ -0,0 +1,85 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.NbtHelper; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; + +public class InfoParserNBT extends GenericInfoParser { + + public static final InfoParserNBT instance = new InfoParserNBT(); + + @Override + public int priority() { + return 500; + } + + @Override + public String id() { + return "nbt"; + } + + @Override + public String name() { + return "NBT"; + } + + @Override + public String plural() { + return name(); + } + + private String trimText() { + return TextFormatting.RED + "(trimmed)"; + } + + /** + * if the length is above 300 characters, we trim to the first space after that, + * and we there's more than 8 lines, we trim to that. + * this prevents the entire chatbox from being filled with just the NBT data. + * note that we do *have* to use {@link StringUtils#indexOf} because + * if the cut happens just after a section sign it would break the formatting of {@link #trimText}. + */ + @Override + public String text(@NotNull NBTTagCompound entry, boolean colored, boolean prettyNbt) { + String msg = NbtHelper.toGroovyCode(entry, prettyNbt, true); + if (msg.length() > 300) { + int endIndex = StringUtils.indexOf(msg, " ", 300); + return endIndex == -1 ? msg : msg.substring(0, StringUtils.indexOf(msg, " ", 300)) + trimText(); + } + int trimLocation = StringUtils.ordinalIndexOf(msg, "\n", 8); + return trimLocation == -1 ? msg : msg.substring(0, trimLocation) + "\n" + trimText(); + } + + @Override + public String copyText(@NotNull NBTTagCompound entry, boolean prettyNbt) { + return NbtHelper.toGroovyCode(entry, prettyNbt, false); + } + + @Override + public ITextComponent information(@NotNull NBTTagCompound entry, boolean prettyNbt) { + return information(copyText(entry, prettyNbt), msg(entry, prettyNbt)); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() != null) { + if (info.getEntity() instanceof EntityPlayer) { + NBTTagCompound nbt = new NBTTagCompound(); + info.getEntity().writeToNBT(nbt); + instance.add(info.getMessages(), nbt, info.isPrettyNbt()); + } else { + instance.add(info.getMessages(), info.getEntity().serializeNBT(), info.isPrettyNbt()); + } + } else if (info.getTileEntity() != null) { + instance.add(info.getMessages(), info.getTileEntity().serializeNBT(), info.isPrettyNbt()); + } else if (!info.getStack().isEmpty()) { + instance.add(info.getMessages(), info.getStack().serializeNBT(), info.isPrettyNbt()); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserOreDict.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserOreDict.java new file mode 100644 index 000000000..f5a26b6a1 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserOreDict.java @@ -0,0 +1,42 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraftforge.oredict.OreDictionary; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class InfoParserOreDict extends GenericInfoParser { + + public static final InfoParserOreDict instance = new InfoParserOreDict(); + + @Override + public String id() { + return "oredict"; + } + + @Override + public String name() { + return "Ore Dictionary"; + } + + @Override + public String plural() { + return "Ore Dictionaries"; + } + + @Override + public String text(@NotNull String entry, boolean colored, boolean prettyNbt) { + return colored ? GroovyScriptCodeConverter.asGroovyCode(entry, true) : entry; + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) return; + List ores = Arrays.stream(OreDictionary.getOreIDs(info.getStack())).mapToObj(OreDictionary::getOreName).collect(Collectors.toList()); + instance.add(info.getMessages(), ores, info.isPrettyNbt()); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserPotionEffect.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserPotionEffect.java new file mode 100644 index 000000000..6e96258db --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserPotionEffect.java @@ -0,0 +1,45 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.potion.PotionEffect; +import net.minecraft.potion.PotionUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class InfoParserPotionEffect extends GenericInfoParser { + + public static final InfoParserPotionEffect instance = new InfoParserPotionEffect(); + + @Override + public String id() { + return "potioneffect"; + } + + @Override + public String name() { + return "Potion Effect"; + } + + @Override + public String text(@NotNull PotionEffect entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getStack().isEmpty()) { + if (info.getEntity() instanceof EntityLivingBase entityLivingBase) { + instance.add(info.getMessages(), new ArrayList<>(entityLivingBase.getActivePotionEffects()), info.isPrettyNbt()); + } + return; + } + List list = PotionUtils.getEffectsFromStack(info.getStack()); + if (list.isEmpty()) return; + instance.add(info.getMessages(), list, info.isPrettyNbt()); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserTranslationKey.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserTranslationKey.java new file mode 100644 index 000000000..a611bb5e5 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserTranslationKey.java @@ -0,0 +1,31 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import net.minecraft.util.text.TextFormatting; +import org.jetbrains.annotations.NotNull; + +public class InfoParserTranslationKey extends GenericInfoParser { + + public static final InfoParserTranslationKey instance = new InfoParserTranslationKey(); + + @Override + public String id() { + return "translation"; + } + + @Override + public String name() { + return "Translation key"; + } + + @Override + public String text(@NotNull String entry, boolean colored, boolean prettyNbt) { + return colored ? TextFormatting.YELLOW + entry : entry; + } + + @Override + public void parse(InfoParserPackage info) { + // translation isn't used via the registry (what parse does) but is instead directly called by individual InfoParsers + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserVillagerCareer.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserVillagerCareer.java new file mode 100644 index 000000000..943cad9a4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserVillagerCareer.java @@ -0,0 +1,43 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.entity.passive.EntityVillager; +import net.minecraftforge.fml.common.registry.VillagerRegistry; +import org.jetbrains.annotations.NotNull; + +public class InfoParserVillagerCareer extends GenericInfoParser { + + public static final InfoParserVillagerCareer instance = new InfoParserVillagerCareer(); + + @Override + public int priority() { + return 201; + } + + @Override + public String id() { + return "villagercareer"; + } + + @Override + public String name() { + return "Villager Career"; + } + + @Override + public String text(@NotNull VillagerRegistry.VillagerCareer entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() == null) return; + if (info.getEntity() instanceof EntityVillager villager) { + VillagerRegistry.VillagerCareer career = villager.getProfessionForge().getCareer(villager.careerId - 1); + instance.add(info.getMessages(), career, info.isPrettyNbt()); + InfoParserTranslationKey.instance.add(info.getMessages(), "entity.Villager." + career.getName(), info.isPrettyNbt()); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserVillagerProfession.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserVillagerProfession.java new file mode 100644 index 000000000..fbb396821 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/InfoParserVillagerProfession.java @@ -0,0 +1,41 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; +import net.minecraft.entity.passive.EntityVillager; +import net.minecraftforge.fml.common.registry.VillagerRegistry; +import org.jetbrains.annotations.NotNull; + +public class InfoParserVillagerProfession extends GenericInfoParser { + + public static final InfoParserVillagerProfession instance = new InfoParserVillagerProfession(); + + @Override + public int priority() { + return 200; + } + + @Override + public String id() { + return "villagerprofession"; + } + + @Override + public String name() { + return "Villager Profession"; + } + + @Override + public String text(@NotNull VillagerRegistry.VillagerProfession entry, boolean colored, boolean prettyNbt) { + return GroovyScriptCodeConverter.asGroovyCode(entry, colored); + } + + @Override + public void parse(InfoParserPackage info) { + if (info.getEntity() == null) return; + if (info.getEntity() instanceof EntityVillager villager) { + instance.add(info.getMessages(), villager.getProfessionForge(), info.isPrettyNbt()); + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/StandardInfoParserRegistry.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/StandardInfoParserRegistry.java new file mode 100644 index 000000000..f6920d943 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/command/infoparser/StandardInfoParserRegistry.java @@ -0,0 +1,24 @@ +package com.cleanroommc.groovyscript.compat.vanilla.command.infoparser; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; + +public class StandardInfoParserRegistry { + + public static void init() { + InfoParserRegistry.addInfoParser(InfoParserItem.instance); + InfoParserRegistry.addInfoParser(InfoParserFluid.instance); + InfoParserRegistry.addInfoParser(InfoParserBlock.instance); + InfoParserRegistry.addInfoParser(InfoParserBlockState.instance); + InfoParserRegistry.addInfoParser(InfoParserOreDict.instance); + InfoParserRegistry.addInfoParser(InfoParserNBT.instance); + InfoParserRegistry.addInfoParser(InfoParserEntity.instance); + InfoParserRegistry.addInfoParser(InfoParserVillagerProfession.instance); + InfoParserRegistry.addInfoParser(InfoParserVillagerCareer.instance); + InfoParserRegistry.addInfoParser(InfoParserBiome.instance); + InfoParserRegistry.addInfoParser(InfoParserDimension.instance); + InfoParserRegistry.addInfoParser(InfoParserCreativeTab.instance); + InfoParserRegistry.addInfoParser(InfoParserEnchantment.instance); + InfoParserRegistry.addInfoParser(InfoParserPotionEffect.instance); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/VillagerProfessionAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/VillagerProfessionAccessor.java new file mode 100644 index 000000000..c19ce7bf4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/VillagerProfessionAccessor.java @@ -0,0 +1,15 @@ +package com.cleanroommc.groovyscript.core.mixin; + +import net.minecraftforge.fml.common.registry.VillagerRegistry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(value = VillagerRegistry.VillagerProfession.class, remap = false) +public interface VillagerProfessionAccessor { + + @Accessor + List getCareers(); + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/extendedcrafting/ItemRecipeMakerMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/extendedcrafting/ItemRecipeMakerMixin.java index 8d00cf1d0..01b4b3d49 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/extendedcrafting/ItemRecipeMakerMixin.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/extendedcrafting/ItemRecipeMakerMixin.java @@ -4,7 +4,7 @@ import com.blakebr0.extendedcrafting.item.ItemRecipeMaker; import com.blakebr0.extendedcrafting.lib.IExtendedTable; import com.blakebr0.extendedcrafting.tile.TileEnderCrafter; -import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.google.common.base.Joiner; import net.minecraft.item.ItemStack; import net.minecraftforge.oredict.OreDictionary; @@ -118,12 +118,12 @@ public void setClipboard(IExtendedTable table, ItemStack stack, CallbackInfoRetu if (ModConfig.confRMOredict) { int[] oreIds = OreDictionary.getOreIDs(stack); if (oreIds.length > 0) { - return IngredientHelper.asGroovyCode(OreDictionary.getOreName(oreIds[0]), false); + return GroovyScriptCodeConverter.asGroovyCode(OreDictionary.getOreName(oreIds[0]), false); } } if (ModConfig.confRMNBT) { - return IngredientHelper.asGroovyCode(stack, false, false); + return GroovyScriptCodeConverter.asGroovyCode(stack, false, false); } - return IngredientHelper.asGroovyCode(stack, false); + return GroovyScriptCodeConverter.asGroovyCode(stack, false); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/event/GsHandEvent.java b/src/main/java/com/cleanroommc/groovyscript/event/GsHandEvent.java index d280c4808..329353b73 100644 --- a/src/main/java/com/cleanroommc/groovyscript/event/GsHandEvent.java +++ b/src/main/java/com/cleanroommc/groovyscript/event/GsHandEvent.java @@ -1,11 +1,14 @@ package com.cleanroommc.groovyscript.event; +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.fml.common.eventhandler.Event; import org.jetbrains.annotations.NotNull; @@ -23,11 +26,13 @@ public class GsHandEvent extends Event { */ @NotNull public final MinecraftServer server; + /** * Player who executes the command */ @NotNull public final EntityPlayer player; + /** * Arguments of the command */ @@ -46,36 +51,80 @@ public class GsHandEvent extends Event { */ @NotNull public final ItemStack stack; + + /** + * The entity the player is looking at + */ + @Nullable + public final Entity entity; + + /** + * The block position the player is looking at + */ + @Nullable + public final BlockPos pos; + /** * The block state of the held item or the block state the player is looking at */ @Nullable public final IBlockState blockState; + /** * The block of the held item or the block the player is looking at */ @Nullable public final Block block; + /** * The tile entity the player is looking at */ @Nullable public final TileEntity tileEntity; - public GsHandEvent(@NotNull MinecraftServer server, - @NotNull EntityPlayer player, - String[] commandArgs, - @NotNull List messages, - @NotNull ItemStack stack, - @Nullable IBlockState blockState, - @Nullable Block block, @Nullable TileEntity tileEntity) { + /** + * If pretty nbt is enabled + */ + public final boolean prettyNbt; + + + public GsHandEvent( + @NotNull MinecraftServer server, + @NotNull EntityPlayer player, + String[] commandArgs, + @NotNull List messages, + @NotNull ItemStack stack, + @Nullable Entity entity, + @Nullable BlockPos pos, + @Nullable IBlockState blockState, + @Nullable Block block, + @Nullable TileEntity tileEntity, + boolean prettyNbt + ) { this.server = server; this.player = player; this.commandArgs = commandArgs; this.messages = messages; this.stack = stack; + this.entity = entity; + this.pos = pos; this.blockState = blockState; this.block = block; this.tileEntity = tileEntity; + this.prettyNbt = prettyNbt; + } + + public GsHandEvent(InfoParserPackage infoParserPackage) { + this.server = infoParserPackage.getServer(); + this.player = infoParserPackage.getPlayer(); + this.commandArgs = infoParserPackage.getArgs().toArray(new String[0]); + this.messages = infoParserPackage.getMessages(); + this.stack = infoParserPackage.getStack(); + this.entity = infoParserPackage.getEntity(); + this.pos = infoParserPackage.getPos(); + this.blockState = infoParserPackage.getBlockState(); + this.block = infoParserPackage.getBlock(); + this.tileEntity = infoParserPackage.getTileEntity(); + this.prettyNbt = infoParserPackage.isPrettyNbt(); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java new file mode 100644 index 000000000..cc8fdafa4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java @@ -0,0 +1,215 @@ +package com.cleanroommc.groovyscript.helper.ingredient; + +import com.cleanroommc.groovyscript.core.mixin.CreativeTabsAccessor; +import com.google.common.collect.Lists; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.DimensionType; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.common.registry.VillagerRegistry; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import java.util.List; +import java.util.Map; + +public class GroovyScriptCodeConverter { + + public static String formatNumber(int number, boolean colored) { + StringBuilder builder = new StringBuilder(); + if (colored) builder.append(TextFormatting.YELLOW); + builder.append(number); + return builder.toString(); + } + + public static String formatGenericHandler(String handler, String target, boolean colored) { + StringBuilder builder = new StringBuilder(); + if (colored) builder.append(TextFormatting.DARK_GREEN); + builder.append(handler); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("('"); + if (colored) builder.append(TextFormatting.AQUA); + builder.append(target); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("')"); + return builder.toString(); + } + + public static String formatMultiple(int amount, boolean colored) { + StringBuilder builder = new StringBuilder(); + if (amount > 1) { + if (colored) builder.append(TextFormatting.GRAY); + builder.append(" * "); + builder.append(formatNumber(amount, colored)); + } + return builder.toString(); + } + + public static String formatInstantiation(String clazz, List params, boolean colored) { + StringBuilder builder = new StringBuilder(); + if (colored) builder.append(TextFormatting.LIGHT_PURPLE); + builder.append("new "); + if (colored) builder.append(TextFormatting.GOLD); + builder.append(clazz); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("("); + builder.append(String.join((colored ? TextFormatting.GRAY.toString() : "") + ", ", params)); + if (colored) builder.append(TextFormatting.GRAY); + builder.append(")"); + return builder.toString(); + } + + public static String formatResourceLocation(String handler, ResourceLocation resourceLocation, boolean colored) { + if (resourceLocation == null) return null; + return formatGenericHandler(handler, resourceLocation.toString(), colored); + } + + public static String formatForgeRegistryImpl(String handler, IForgeRegistryEntry.Impl impl, boolean colored) { + return formatResourceLocation(handler, impl.getRegistryName(), colored); + } + + public static String formatNBTTag(NBTTagCompound tag, boolean colored, boolean prettyNbt) { + StringBuilder builder = new StringBuilder(); + if (tag != null) { + builder.append(".withNbt("); + builder.append(NbtHelper.toGroovyCode(tag, prettyNbt, colored)); + if (colored) builder.append(TextFormatting.GRAY); + builder.append(")"); + } + return builder.toString(); + } + + private static String getSingleItemStack(ItemStack itemStack, boolean colored) { + StringBuilder builder = new StringBuilder(); + if (colored) builder.append(TextFormatting.DARK_GREEN); + builder.append("item"); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("('"); + if (colored) builder.append(TextFormatting.AQUA); + builder.append(itemStack.getItem().getRegistryName()); + // code is more complex than strictly needed here to allow using the wildcard + if (itemStack.getMetadata() == Short.MAX_VALUE) { + builder.append(":"); + builder.append("*"); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("'"); + } else if (itemStack.getMetadata() == 0) { + if (colored) builder.append(TextFormatting.GRAY); + builder.append("'"); + } else { + if (colored) builder.append(TextFormatting.GRAY); + builder.append("'"); + builder.append(", "); + builder.append(formatNumber(itemStack.getMetadata(), colored)); + if (colored) builder.append(TextFormatting.GRAY); + } + builder.append(")"); + return builder.toString(); + } + + public static String asGroovyCode(ItemStack itemStack, boolean colored) { + return getSingleItemStack(itemStack, colored) + formatMultiple(itemStack.getCount(), colored); + } + + public static String asGroovyCode(ItemStack itemStack, boolean colored, boolean prettyNbt) { + return getSingleItemStack(itemStack, colored) + formatNBTTag(itemStack.getTagCompound(), colored, prettyNbt) + formatMultiple(itemStack.getCount(), colored); + } + + public static String asGroovyCode(FluidStack fluidStack, boolean colored) { + return formatGenericHandler("fluid", fluidStack.getFluid().getName(), colored) + formatMultiple(fluidStack.amount, colored); + } + + public static String asGroovyCode(FluidStack fluidStack, boolean colored, boolean prettyNbt) { + return formatGenericHandler("fluid", fluidStack.getFluid().getName(), colored) + formatNBTTag(fluidStack.tag, colored, prettyNbt) + formatMultiple(fluidStack.amount, colored); + } + + public static String asGroovyCode(String oreDict, boolean colored) { + return formatGenericHandler("ore", oreDict, colored); + } + + public static String asGroovyCode(Biome biome, boolean colored) { + return formatForgeRegistryImpl("biome", biome, colored); + } + + public static String asGroovyCode(VillagerRegistry.VillagerProfession profession, boolean colored) { + return formatForgeRegistryImpl("profession", profession, colored); + } + + public static String asGroovyCode(VillagerRegistry.VillagerCareer career, boolean colored) { + return formatGenericHandler("career", career.getName(), colored); + } + + public static String asGroovyCode(DimensionType dimensionType, boolean colored) { + return formatGenericHandler("dimension", dimensionType.getName(), colored); + } + + public static String asGroovyCode(Entity entity, boolean colored) { + return formatResourceLocation("entity", EntityList.getKey(entity), colored); + } + + public static String asGroovyCode(CreativeTabs tab, boolean colored) { + return formatGenericHandler("creativeTab", ((CreativeTabsAccessor) tab).getTabLabel2(), colored); + } + + public static String asGroovyCode(Enchantment enchantment, boolean colored) { + return formatForgeRegistryImpl("enchantment", enchantment, colored); + } + + public static String asGroovyCode(Potion potion, boolean colored) { + return formatResourceLocation("potion", Potion.REGISTRY.getNameForObject(potion), colored); + } + + public static String asGroovyCode(PotionEffect potionEffect, boolean colored) { + StringBuilder builder = new StringBuilder(); + List list = Lists.newArrayList(asGroovyCode(potionEffect.getPotion(), colored), + formatNumber(potionEffect.getDuration(), colored), + formatNumber(potionEffect.getAmplifier(), colored)); + builder.append(formatInstantiation("PotionEffect", list, colored)); + return builder.toString(); + } + + public static String asGroovyCode(Block state, boolean colored) { + return formatResourceLocation("block", state.getRegistryName(), colored); + } + + @SuppressWarnings("all") + public static String asGroovyCode(IBlockState state, boolean colored) { + StringBuilder builder = new StringBuilder(); + if (colored) builder.append(TextFormatting.DARK_GREEN); + builder.append("blockstate"); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("('"); + if (colored) builder.append(TextFormatting.AQUA); + builder.append(state.getBlock().getRegistryName()); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("'"); + if (!state.getProperties().isEmpty()) { + for (Map.Entry, Comparable> entry : state.getProperties().entrySet()) { + IProperty property = entry.getKey(); + if (colored) builder.append(TextFormatting.GRAY); + builder.append(", ").append("'"); + if (colored) builder.append(TextFormatting.YELLOW); + builder.append(property.getName()); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("="); + if (colored) builder.append(TextFormatting.YELLOW); + builder.append(property.getName(entry.getValue())); + if (colored) builder.append(TextFormatting.GRAY); + builder.append("'"); + } + } + builder.append(")"); + return builder.toString(); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java index 638770b67..d3d789a3b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java +++ b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java @@ -3,13 +3,11 @@ import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.sandbox.expand.LambdaClosure; import groovy.lang.Closure; -import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.Ingredient; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.NonNullList; -import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -17,7 +15,6 @@ import java.util.Collection; import java.util.Collections; -import java.util.Map; public class IngredientHelper { @@ -242,101 +239,34 @@ public static FluidStack copy(FluidStack fluid) { return fluid == null ? null : fluid.copy(); } + @Deprecated public static String asGroovyCode(ItemStack itemStack, boolean colored) { - StringBuilder builder = new StringBuilder(); - if (colored) builder.append(TextFormatting.DARK_GREEN); - builder.append("item"); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("('"); - if (colored) builder.append(TextFormatting.AQUA); - builder.append(itemStack.getItem().getRegistryName()); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("'"); - if (itemStack.getMetadata() != 0) { - builder.append(", "); - if (colored) builder.append(TextFormatting.GOLD); - builder.append(itemStack.getMetadata()); - if (colored) builder.append(TextFormatting.GRAY); - } - builder.append(")"); - return builder.toString(); + return GroovyScriptCodeConverter.asGroovyCode(itemStack, colored); } + @Deprecated public static String asGroovyCode(ItemStack itemStack, boolean colored, boolean prettyNbt) { - StringBuilder builder = new StringBuilder().append(asGroovyCode(itemStack, colored)); - if (itemStack.hasTagCompound()) { - builder.append(".withNbt("); - builder.append(NbtHelper.toGroovyCode(itemStack.getTagCompound(), prettyNbt, colored)); - if (colored) builder.append(TextFormatting.GRAY); - builder.append(")"); - } - return builder.toString(); + return GroovyScriptCodeConverter.asGroovyCode(itemStack, colored, prettyNbt); } + @Deprecated public static String asGroovyCode(FluidStack fluidStack, boolean colored) { - StringBuilder builder = new StringBuilder(); - if (colored) builder.append(TextFormatting.DARK_GREEN); - builder.append("fluid"); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("('"); - if (colored) builder.append(TextFormatting.AQUA); - builder.append(fluidStack.getFluid().getName()); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("')"); - return builder.toString(); + return GroovyScriptCodeConverter.asGroovyCode(fluidStack, colored); } + @Deprecated public static String asGroovyCode(FluidStack fluidStack, boolean colored, boolean prettyNbt) { - StringBuilder builder = new StringBuilder().append(asGroovyCode(fluidStack, colored)); - if (fluidStack.tag != null) { - builder.append(".withNbt("); - builder.append(NbtHelper.toGroovyCode(fluidStack.tag, prettyNbt, colored)); - if (colored) builder.append(TextFormatting.GRAY); - builder.append(")"); - } - return builder.toString(); + return GroovyScriptCodeConverter.asGroovyCode(fluidStack, colored, prettyNbt); } + @Deprecated public static String asGroovyCode(String oreDict, boolean colored) { - StringBuilder builder = new StringBuilder(); - if (colored) builder.append(TextFormatting.DARK_GREEN); - builder.append("ore"); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("('"); - if (colored) builder.append(TextFormatting.AQUA); - builder.append(oreDict); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("')"); - return builder.toString(); + return GroovyScriptCodeConverter.asGroovyCode(oreDict, colored); } - @SuppressWarnings("all") + @Deprecated public static String asGroovyCode(IBlockState state, boolean colored) { - StringBuilder builder = new StringBuilder(); - if (colored) builder.append(TextFormatting.DARK_GREEN); - builder.append("blockstate"); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("('"); - if (colored) builder.append(TextFormatting.AQUA); - builder.append(state.getBlock().getRegistryName()); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("'"); - if (!state.getProperties().isEmpty()) { - for (Map.Entry, Comparable> entry : state.getProperties().entrySet()) { - IProperty property = entry.getKey(); - if (colored) builder.append(TextFormatting.GRAY); - builder.append(", ").append("'"); - if (colored) builder.append(TextFormatting.YELLOW); - builder.append(property.getName()); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("="); - if (colored) builder.append(TextFormatting.YELLOW); - builder.append(property.getName(entry.getValue())); - if (colored) builder.append(TextFormatting.GRAY); - builder.append("'"); - } - } - builder.append(")"); - return builder.toString(); + return GroovyScriptCodeConverter.asGroovyCode(state, colored); } + } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java index e095d8602..f15d5ad17 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java @@ -7,6 +7,7 @@ import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; import com.cleanroommc.groovyscript.core.mixin.CreativeTabsAccessor; import com.cleanroommc.groovyscript.core.mixin.OreDictionaryAccessor; +import com.cleanroommc.groovyscript.core.mixin.VillagerProfessionAccessor; import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; import com.cleanroommc.groovyscript.helper.ingredient.OreDictWildcardIngredient; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; @@ -24,6 +25,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.DimensionType; import net.minecraft.world.biome.Biome; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; @@ -138,6 +140,11 @@ public static void init() { .completer(ForgeRegistries.ENTITIES) .docOfType("entity entry") .register(); + ObjectMapper.builder("dimension", DimensionType.class) + .parser(IObjectParser.wrapStringGetter(DimensionType::byName)) + .completerOfNamed(() -> Arrays.asList(DimensionType.values()), DimensionType::getName) + .docOfType("dimension") + .register(); ObjectMapper.builder("biome", Biome.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.BIOMES)) .completer(ForgeRegistries.BIOMES) @@ -148,6 +155,22 @@ public static void init() { .completer(ForgeRegistries.VILLAGER_PROFESSIONS) .docOfType("villager profession") .register(); + + final List careerList = new ArrayList<>(); + for (var profession : ForgeRegistries.VILLAGER_PROFESSIONS) { + if (profession != null) { + for (var career : ((VillagerProfessionAccessor) profession).getCareers()) { + if (career != null) { + careerList.add(career.getName()); + } + } + } + } + ObjectMapper.builder("career", VillagerRegistry.VillagerCareer.class) + .parser(ObjectMappers::parseVillagerCareer) + .completerOfNames(() -> careerList) + .docOfType("villager career") + .register(); ObjectMapper.builder("creativeTab", CreativeTabs.class) .parser(ObjectMappers::parseCreativeTab) .completerOfNamed(() -> Arrays.asList(CreativeTabs.CREATIVE_TAB_ARRAY), v -> ((CreativeTabsAccessor) v).getTabLabel2()) diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java index 5d2731b55..6ce1e9ee1 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java @@ -3,6 +3,7 @@ import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.core.mixin.CreativeTabsAccessor; +import com.cleanroommc.groovyscript.core.mixin.VillagerProfessionAccessor; import com.google.common.base.Optional; import com.google.common.collect.Iterators; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -22,14 +23,13 @@ import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.registry.ForgeRegistries; +import net.minecraftforge.fml.common.registry.VillagerRegistry; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; import static com.cleanroommc.groovyscript.mapper.ObjectMapperManager.SPLITTER; import static com.cleanroommc.groovyscript.mapper.ObjectMapperManager.WILDCARD; @@ -167,6 +167,18 @@ private static Result parseBlockStates(IBlockState defaultState, It return Result.some(defaultState); } + public static Result parseVillagerCareer(String mainArg, Object... args) { + for (var profession : ForgeRegistries.VILLAGER_PROFESSIONS) { + if (profession != null) { + for (var career : ((VillagerProfessionAccessor) (profession)).getCareers()) { + if (career != null && mainArg.equals(career.getName())) { + return Result.some(career); + } + } + } + } + return Result.error(); + } public static Result parseCreativeTab(String mainArg, Object... args) { for (CreativeTabs tab : CreativeTabs.CREATIVE_TAB_ARRAY) { diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang index 4cb3258d8..52bbc88e2 100644 --- a/src/main/resources/assets/groovyscript/lang/en_us.lang +++ b/src/main/resources/assets/groovyscript/lang/en_us.lang @@ -24,6 +24,38 @@ groovyscript.packmode.normal.description=A normal pack mode. Nothing special. groovyscript.packmode.hard.name=Hard groovyscript.packmode.hard.description=Hard mode. Everything requires at least 50 diamonds and nether stars. +# Info Parser Descriptions +groovyscript.infoparser.biome=Biome the block being targeted is in +groovyscript.infoparser.block=Block being targeted or representing the held item +groovyscript.infoparser.blockstate=BlockState being looked at or representing the held item +groovyscript.infoparser.creativetab=Creative Tab the targeted ItemStack is contained by, if any +groovyscript.infoparser.dimension=Dimension type the player is in +groovyscript.infoparser.enchantment=Enchantments on the held ItemStack +groovyscript.infoparser.entity=Entity being looked at +groovyscript.infoparser.fluid=Fluid being looked at in world or being contained in the item being held +groovyscript.infoparser.item=ItemStack in the player's main hand, offhand, or representing the block being looked at +groovyscript.infoparser.nbt=NBT data of target, trimmed if it gets too long +groovyscript.infoparser.oredict=Ore Dicts the held ItemStack is part of +groovyscript.infoparser.potioneffect=Potion effects for the held item, active potion effects for the entity being looked at, or active potion effects on the player +groovyscript.infoparser.translation=Translation key for the target +groovyscript.infoparser.villagercareer=The Villager Career of the villager being targeted +groovyscript.infoparser.villagerprofession=The Villager Profession of the villager being targeted + +# Modded Info Parser Descriptions +groovyscript.infoparser.aspect=Thaumcraft Aspects contained by the held item, targeted entity, or current player +groovyscript.infoparser.brew=Botania Brews attached to the held item +groovyscript.infoparser.compound=Alchemistry Compound of the held item +groovyscript.infoparser.constellation=Astral Sorcery Constellations for the held item or enabled in the current dimension +groovyscript.infoparser.element=Alchemistry Element of the held item +groovyscript.infoparser.gas=Mekanism Gases contained within the targeted ItemStack +groovyscript.infoparser.herb=Roots Herb of the held item +groovyscript.infoparser.infusion=Mekanism Infusion Types the targeted stack provides +groovyscript.infoparser.jeitab=Just Enough Items Categories the target ItemStack is a catalyst for +groovyscript.infoparser.modifier=Roots Spell Modifiers attached to the held item +groovyscript.infoparser.spell=Roots Spells attached to the held item +groovyscript.infoparser.tunnel=Applied Energistics 2 Tunnel Attunement types for the held item +groovyscript.infoparser.weather=EvilCraft Weather state + # Wiki groovyscript.wiki.categories=Categories diff --git a/src/main/resources/mixin.groovyscript.json b/src/main/resources/mixin.groovyscript.json index 89234bc1b..5fb8103ae 100644 --- a/src/main/resources/mixin.groovyscript.json +++ b/src/main/resources/mixin.groovyscript.json @@ -20,6 +20,7 @@ "OreIngredientMixin", "SlotCraftingAccess", "TileEntityPistonMixin", + "VillagerProfessionAccessor", "groovy.AsmDecompilerMixin", "groovy.ClassCollectorMixin", "groovy.ClosureMixin",