diff --git a/examples/preInit/mekanism.groovy b/examples/preInit/mekanism.groovy index e6dccd671..15c0792a3 100644 --- a/examples/preInit/mekanism.groovy +++ b/examples/preInit/mekanism.groovy @@ -5,6 +5,6 @@ import net.minecraftforge.client.event.TextureStitchEvent if (!isLoaded('mekanism')) return println 'mod \'mekanism\' detected, running script' -eventManager.listen(TextureStitchEvent.Pre) { event -> - event.getMap().registerSprite(resource('placeholdername:blocks/mekanism_infusion_texture')) +eventManager.listen { TextureStitchEvent.Pre event -> + event.getMap().registerSprite(resource('groovyscriptdev:blocks/mekanism_infusion_texture')) } 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 e423fae86..4a55f2b57 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 @@ -30,6 +30,20 @@ public static String asGroovyCode(ChemicalElement element, boolean colored) { return GroovyScriptCodeConverter.formatGenericHandler("element", element.getName(), colored); } + public static String itemStackToElementGroovyCode(ItemStack itemStack, boolean colored) { + for (var x : ElementRegistry.INSTANCE.getAllElements()) { + if (ItemStack.areItemsEqual(x.toItemStack(1), itemStack)) { + return asGroovyCode(x, colored); + } + } + for (var x : CompoundRegistry.INSTANCE.compounds()) { + if (ItemStack.areItemsEqual(x.toItemStack(1), itemStack)) { + return asGroovyCode(x, colored); + } + } + return null; + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("element", ItemStack.class) @@ -49,6 +63,7 @@ public void initialize(GroovyContainer container) { .completerOfNamed(CompoundRegistry.INSTANCE::compounds, ChemicalCompound::getName) .completerOfNamed(ElementRegistry.INSTANCE::getAllElements, ChemicalElement::getName) .docOfType("chemical element or compound as item stack") + .toGroovyCode(x -> itemStackToElementGroovyCode(x, false)) .register(); InfoParserRegistry.addInfoParser(InfoParserElement.instance); 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 3e0f03d96..d9489e179 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 @@ -29,6 +29,7 @@ public void initialize(GroovyContainer container) { .completerOfNamed(() -> Arrays.asList(TunnelType.values()), v -> v.name().toUpperCase(Locale.ROOT)) .defaultValue(() -> TunnelType.ME) .docOfType("P2P tunnel type") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); InfoParserRegistry.addInfoParser(InfoParserTunnel.instance); 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 0163c408e..e33f41bd4 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 @@ -53,6 +53,7 @@ public void initialize(GroovyContainer container) { }) .completerOfNamed(ConstellationRegistryAccessor::getConstellationList, IConstellation::getSimpleName) .docOfType("constellation") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); ExpansionHelper.mixinClass(ItemStack.class, CrystalItemStackExpansion.class); 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 9ba97e428..a08c41e73 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 @@ -56,6 +56,7 @@ public void initialize(GroovyContainer container) { .completerOfNames(() -> BotaniaAPI.brewMap.keySet()) .defaultValue(() -> BotaniaAPI.fallbackBrew) .docOfType("brew") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); InfoParserRegistry.addInfoParser(InfoParserBrew.instance); 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 8d6ca678f..f2fbcdd54 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 @@ -19,6 +19,10 @@ public static String asGroovyCode(String weatherType, boolean colored) { return GroovyScriptCodeConverter.formatGenericHandler("weather", weatherType, colored); } + public static String asGroovyCode(WeatherType weatherType, boolean colored) { + return asGroovyCode(weatherType.toString(), colored); + } + @Override public void initialize(GroovyContainer container) { final List weatherTypes = Arrays.asList("any", "clear", "rain", "lightning"); @@ -27,6 +31,7 @@ public void initialize(GroovyContainer container) { .completerOfNames(() -> weatherTypes) // elements don't have names .defaultValue(() -> WeatherType.ANY) .docOfType("weather type") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); InfoParserRegistry.addInfoParser(InfoParserWeather.instance); 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 22b0b3120..eb2368bbe 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 @@ -80,11 +80,13 @@ public void initialize(GroovyContainer container) { }) .completerOfNamed(GasRegistry::getRegisteredGasses, Gas::getName) .docOfType("gas stack") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); container.objectMapperBuilder("infusionType", InfuseType.class) .parser(IObjectParser.wrapStringGetter(InfuseRegistry::get, true)) .completerOfNames(InfuseRegistry.getInfuseMap()::keySet) .docOfType("infusion type") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); InfoParserRegistry.addInfoParser(InfoParserGas.instance); 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 0e2f0ec62..c499b3200 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 @@ -59,27 +59,32 @@ public void initialize(GroovyContainer container) { .parser(IObjectParser.wrapStringGetter(RitualRegistry::getRitual)) .completerOfNames(() -> RitualRegistry.ritualRegistry.keySet()) .docOfType("ritual") + .toGroovyCode(x -> GroovyScriptCodeConverter.formatGenericHandler("ritual", x.getName(), false)) .register(); container.objectMapperBuilder("herb", Herb.class) .parser(IObjectParser.wrapStringGetter(HerbRegistry::getHerbByName)) .completerOfNames(HerbRegistry.registry::keySet) .docOfType("herb") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); container.objectMapperBuilder("cost", CostType.class) .parser(IObjectParser.wrapEnum(CostType.class, false)) .completerOfEnum(CostType.class, false) .docOfType("cost") + .toGroovyCode(x -> GroovyScriptCodeConverter.formatGenericHandler("cost", x.name(), false)) .register(); container.objectMapperBuilder("spell", SpellBase.class) .parser(Roots::getSpell) .completer(SpellRegistry.spellRegistry::keySet) .defaultValueSup(() -> Result.some(FakeSpell.INSTANCE)) // crashes otherwise .docOfType("spell") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); container.objectMapperBuilder("modifier", Modifier.class) .parser(Roots::getModifier) .completerOfNamed(ModifierRegistry::getModifiers, v -> v.getRegistryName().toString()) .docOfType("modifier") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); InfoParserRegistry.addInfoParser(InfoParserHerb.instance); 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 56e8d6da4..93c27aa87 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 @@ -17,6 +17,8 @@ import net.minecraft.item.ItemStack; import thaumcraft.api.ThaumcraftApiHelper; import thaumcraft.api.aspects.AspectList; +import thaumcraft.api.aspects.IEssentiaContainerItem; +import thaumcraft.api.items.ItemsTC; import java.util.Collection; @@ -42,18 +44,26 @@ public static String asGroovyCode(AspectStack aspectStack, boolean colored) { return asGroovyCode(aspectStack.getAspect(), colored) + GroovyScriptCodeConverter.formatMultiple(aspectStack.getAmount(), colored); } + public static String itemStackCrystalToAspectGroovyCode(ItemStack itemStack, boolean colored) { + if (itemStack.getItem() != ItemsTC.crystalEssence) return null; + var aspects = ((IEssentiaContainerItem) ItemsTC.crystalEssence).getAspects(itemStack); + return aspects.size() > 0 ? asGroovyCode(aspects.getAspects()[0], colored) : null; + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("aspect", AspectStack.class) .parser(IObjectParser.wrapStringGetter(Thaumcraft::getAspect, AspectStack::new)) .completerOfNames(thaumcraft.api.aspects.Aspect.aspects::keySet) .docOfType("aspect stack") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); container.objectMapperBuilder("crystal", ItemStack.class) .parser(IObjectParser.wrapStringGetter(Thaumcraft::getAspect, ThaumcraftApiHelper::makeCrystal)) .completerOfNames(thaumcraft.api.aspects.Aspect.aspects::keySet) .defaultValue(() -> ItemStack.EMPTY) .docOfType("aspect crystal as item stack") + .toGroovyCode(x -> itemStackCrystalToAspectGroovyCode(x, false)) .register(); ExpansionHelper.mixinClass(ItemStack.class, AspectItemStackExpansion.class); ExpansionHelper.mixinClass(ItemStack.class, WarpItemStackExpansion.class); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java index e80f8ae0d..632179a4c 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java @@ -7,9 +7,7 @@ import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device.*; import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo.*; import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine.*; - -import java.util.Arrays; -import java.util.Locale; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; public class ThermalExpansion extends GroovyPropertyContainer { @@ -53,8 +51,9 @@ public class ThermalExpansion extends GroovyPropertyContainer { public void initialize(GroovyContainer container) { container.objectMapperBuilder("compactorMode", CompactorManager.Mode.class) .parser(IObjectParser.wrapEnum(CompactorManager.Mode.class, false)) - .completerOfNamed(() -> Arrays.asList(CompactorManager.Mode.values()), v -> v.name().toUpperCase(Locale.ROOT)) + .completerOfEnum(CompactorManager.Mode.class, false) .defaultValue(() -> CompactorManager.Mode.ALL) + .toGroovyCode(x -> GroovyScriptCodeConverter.formatGenericHandler("compactorMode", x.name(), false)) .register(); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/TinkersConstruct.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/TinkersConstruct.java index a7900f445..cca0d4c95 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/TinkersConstruct.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/TinkersConstruct.java @@ -8,6 +8,7 @@ import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.material.ToolMaterialBuilder; import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.material.traits.TraitRegistryEvent; import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import net.minecraftforge.common.MinecraftForge; import slimeknights.tconstruct.library.materials.Material; import slimeknights.tconstruct.library.traits.ITrait; @@ -23,17 +24,35 @@ public class TinkersConstruct extends GroovyPropertyContainer { public final CastingBasin castingBasin = new CastingBasin(); public final Materials materials = new Materials(); + public static String asGroovyCode(Material material, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler("toolMaterial", material.identifier, colored); + } + + public static String asGroovyCode(String handler, ITrait trait, boolean colored) { + return GroovyScriptCodeConverter.formatGenericHandler(handler, trait.getIdentifier(), colored); + } + + public static String asGroovyCodeTool(ITrait trait, boolean colored) { + return asGroovyCode("toolTrait", trait, colored); + } + + public static String asGroovyCodeArmor(ITrait trait, boolean colored) { + return asGroovyCode("armorTrait", trait, colored); + } + @Override public void initialize(GroovyContainer container) { container.objectMapperBuilder("toolMaterial", Material.class) .parser(IObjectParser.wrapStringGetter(TinkerRegistryAccessor.getMaterials()::get)) .completerOfNames(TinkerRegistryAccessor.getMaterials()::keySet) .docOfType("tool material") + .toGroovyCode(x -> asGroovyCode(x, false)) .register(); container.objectMapperBuilder("toolTrait", ITrait.class) .parser(IObjectParser.wrapStringGetter(TinkerRegistryAccessor.getTraits()::get)) .completerOfNamed(TinkerRegistryAccessor.getTraits()::keySet, v -> v.endsWith("_armor") ? null : v) // only suggest non armor traits .docOfType("tool trait") + .toGroovyCode(x -> asGroovyCodeTool(x, false)) .register(); container.objectMapperBuilder("armorTrait", ITrait.class) .parser(IObjectParser.wrapStringGetter(s -> TinkerRegistryAccessor.getTraits().get(s + "_armor"))) @@ -41,6 +60,7 @@ public void initialize(GroovyContainer container) { TinkerRegistryAccessor.getTraits()::keySet, v -> v.endsWith("_armor") ? v.substring(0, v.length() - 6) : null) // only suggest armor traits .docOfType("armor trait") + .toGroovyCode(x -> asGroovyCodeArmor(x, false)) .register(); } diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java index 0b9fef324..a88b223f8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java +++ b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/GroovyScriptCodeConverter.java @@ -15,6 +15,7 @@ import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; import net.minecraft.world.DimensionType; import net.minecraft.world.biome.Biome; import net.minecraftforge.fluids.FluidStack; @@ -190,6 +191,10 @@ public static String asGroovyCode(Potion potion, boolean colored) { return formatResourceLocation("potion", Potion.REGISTRY.getNameForObject(potion), colored); } + public static String asGroovyCode(SoundEvent sound, boolean colored) { + return formatForgeRegistryImpl("sound", sound, colored); + } + public static String asGroovyCode(PotionEffect potionEffect, boolean colored) { StringBuilder builder = new StringBuilder(); List list = Lists.newArrayList( diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java index ab602f29d..8ac462556 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java @@ -22,7 +22,7 @@ import java.lang.reflect.Modifier; import java.util.*; -public abstract class AbstractObjectMapper extends Closure implements INamed, IDocumented, IObjectParser, TextureBinder { +public abstract class AbstractObjectMapper extends Closure implements INamed, IDocumented, IObjectParser, IObjectMapperInverter, TextureBinder { private final String name; private final GroovyContainer mod; diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java index 9221a5ef6..e75f7506a 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java @@ -2,6 +2,7 @@ import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import net.minecraft.block.Block; @@ -60,6 +61,11 @@ public void provideCompletion(int index, CompletionParams params, Completions it } } + @Override + public String getGroovyCode(IBlockState value) { + return GroovyScriptCodeConverter.asGroovyCode(value, false); + } + @Override public void bindTexture(IBlockState iBlockState) { ItemStack itemStack = new ItemStack(iBlockState.getBlock(), 1, iBlockState.getBlock().getMetaFromState(iBlockState)); diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/IObjectMapperInverter.java b/src/main/java/com/cleanroommc/groovyscript/mapper/IObjectMapperInverter.java new file mode 100644 index 000000000..9760618a1 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/IObjectMapperInverter.java @@ -0,0 +1,68 @@ +package com.cleanroommc.groovyscript.mapper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * A function to create a string from an object, with the string reprenting a full Object Mapper. + * This is used for {@link com.cleanroommc.groovyscript.mapper.ObjectMapper object mappers}. + *

+ * A few examples of what this outputs would be + * {@code item('minecraft:clay')}, {@code biome('minecraft:desert')}, or {@code blockstate('minecraft:log', 'axis=z', 'variant=oak')}. + *

+ * For Object Mappers with only one creation method, + * the return value should exactly correspond to the Object Mapper that creates it: + *
+ * {@code item % item('minecraft:clay') == "item('minecraft:clay')"}. + *

+ * Some Object Mappers may have multiple alternative creation methods, + * in which case the return value can be any one of those alternatives, + * but must still create the same object: + *
+ * {@code blockstate % blockstate('minecraft:log:0') == "blockstate('minecraft:log', 'axis=y', 'variant=oak')"} + * and + *
+ * {@code blockstate % blockstate('minecraft:log', 'axis=y', 'variant=oak') == "blockstate('minecraft:log', 'axis=y', 'variant=oak')"} + * + * @param the type of the objects being inverted + */ +@FunctionalInterface +public interface IObjectMapperInverter { + + /** + * @param value the object being converted + * @return a String directly corresponding to the code that would create {@param value} + */ + String getGroovyCode(T value); + + /** + * Using Groovy's Operator Overloading, this is %. + */ + default String mod(T value) { + return getGroovyCode(value); + } + + /** + * Converts any number of objects into a collection of their strings + */ + @SuppressWarnings("unchecked") + default Collection mod(T... values) { + List list = new ArrayList<>(); + for (T value : values) { + list.add(getGroovyCode(value)); + } + return list; + } + + /** + * Converts any number of objects into a collection of their strings + */ + default Collection mod(Iterable values) { + List list = new ArrayList<>(); + for (T value : values) { + list.add(getGroovyCode(value)); + } + return list; + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java index 175a89073..c3b0304fb 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java @@ -2,6 +2,7 @@ import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.helper.ingredient.GroovyScriptCodeConverter; import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import net.minecraft.client.Minecraft; @@ -39,6 +40,11 @@ public void provideCompletion(int index, CompletionParams params, Completions it if (index == 0) items.addAllOfRegistry(ForgeRegistries.ITEMS); } + @Override + public String getGroovyCode(ItemStack value) { + return GroovyScriptCodeConverter.asGroovyCode(value, false, false); + } + @Override public void bindTexture(ItemStack item) { GlStateManager.enableDepth(); diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java index ad8c8f44e..efd79eb81 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java @@ -45,12 +45,14 @@ public static Builder builder(String name, Class returnType) { private final Supplier> defaultValue; private final Completer completer; private final TextureBinder textureBinder; + private final Function toGroovyCode; private final Function> tooltip; - private ObjectMapper(String name, GroovyContainer mod, IObjectParser handler, Supplier> defaultValue, Class returnType, List[]> paramTypes, Completer completer, String documentation, TextureBinder textureBinder, Function> tooltip) { + private ObjectMapper(String name, GroovyContainer mod, IObjectParser handler, Supplier> defaultValue, Class returnType, List[]> paramTypes, Completer completer, String documentation, TextureBinder textureBinder, Function toGroovyCode, Function> tooltip) { super(name, mod, returnType); this.handler = handler; this.defaultValue = defaultValue; + this.toGroovyCode = toGroovyCode; this.tooltip = tooltip; this.completer = completer; this.documentation = documentation; @@ -85,6 +87,11 @@ public void bindTexture(T t) { } } + @Override + public String getGroovyCode(T t) { + return this.toGroovyCode == null ? null : this.toGroovyCode.apply(t); + } + @Override public @NotNull List getTooltip(T t) { if (this.tooltip != null) { @@ -111,6 +118,7 @@ public static class Builder { private Supplier> defaultValue; private final Class returnType; private final List[]> paramTypes = new ArrayList<>(); + private Function toGroovyCode; private Completer completer; private String documentation; private TextureBinder textureBinder; @@ -244,6 +252,17 @@ public Builder defaultValueSup(Supplier> defaultValue) { return this; } + /** + * Sets toGroovyCode. If present, this is what converts an object into a String representing the code that would reproduce that object. Default is null. + * + * @param toGroovyCode a function that converts the output into the code that would create that output + * @return this builder + */ + public Builder toGroovyCode(Function toGroovyCode) { + this.toGroovyCode = toGroovyCode; + return this; + } + /** * Adds a method signature. This is only used by LSP to provide helpful tooltips. * @@ -349,6 +368,7 @@ public void register() { this.completer, this.documentation, this.textureBinder, + this.toGroovyCode, this.tooltip); ObjectMapperManager.registerObjectMapper(mapper); } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java index 9d013915c..79a8c692b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java @@ -7,6 +7,8 @@ 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.GroovyScriptCodeConverter; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; @@ -83,11 +85,13 @@ public static void init() { .addSignature(String.class) .addSignature(String.class, String.class) .docOfType("resource location") + .toGroovyCode(x -> GroovyScriptCodeConverter.formatResourceLocation("resource", x, false)) .register(); - ObjectMapper.builder("ore", IIngredient.class) + ObjectMapper.builder("ore", OreDictIngredient.class) .parser(ObjectMappers::parseOreDict) .completerOfNames(OreDictionaryAccessor::getIdToName) .docOfType("ore dict entry") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x.getOreDict(), false)) .textureBinder(TextureBinder.ofArray(IIngredient::getMatchingStacks, TextureBinder.ofItem())) .tooltipOfArray(IIngredient::getMatchingStacks, i -> String.format("![](${item('%s')}) %s", i.getItem().getRegistryName(), i.getDisplayName())) .register(); @@ -104,11 +108,15 @@ public static void init() { .parser(ObjectMappers::parseFluidStack) .completerOfNames(FluidRegistry.getRegisteredFluids()::keySet) .docOfType("fluid stack") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .textureBinder(TextureBinder.ofFluid()) + .tooltip(f -> Collections.singletonList(f.getLocalizedName())) .register(); ObjectMapper.builder("fluid", FluidStack.class) .parser(ObjectMappers::parseFluidStack) .completerOfNames(FluidRegistry.getRegisteredFluids()::keySet) + .docOfType("fluid stack") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .textureBinder(TextureBinder.ofFluid()) .tooltip(f -> Collections.singletonList(f.getLocalizedName())) .register(); @@ -117,6 +125,7 @@ public static void init() { .completer(ForgeRegistries.BLOCKS) .defaultValue(() -> Blocks.AIR) .docOfType("block") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .textureBinder(TextureBinder.of(ItemStack::new, TextureBinder.ofItem())) .register(); ObjectMapper.builder("blockmaterial", Material.class) @@ -137,41 +146,49 @@ public static void init() { .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.ENCHANTMENTS)) .completer(ForgeRegistries.ENCHANTMENTS) .docOfType("enchantment") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .register(); ObjectMapper.builder("potion", Potion.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.POTIONS)) .completer(ForgeRegistries.POTIONS) .docOfType("potion") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .textureBinder(TextureBinder.of(potion -> PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM), PotionType.REGISTRY.getObject(potion.getRegistryName())), TextureBinder.ofItem())) .register(); ObjectMapper.builder("potionType", PotionType.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.POTION_TYPES)) .completer(ForgeRegistries.POTION_TYPES) .docOfType("potion type") + .toGroovyCode(x -> GroovyScriptCodeConverter.formatForgeRegistryImpl("potionType", x, false)) .register(); ObjectMapper.builder("sound", SoundEvent.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.SOUND_EVENTS)) .completer(ForgeRegistries.SOUND_EVENTS) .docOfType("sound") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .register(); ObjectMapper.builder("entity", EntityEntry.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.ENTITIES)) .completer(ForgeRegistries.ENTITIES) .docOfType("entity entry") + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .register(); ObjectMapper.builder("dimension", DimensionType.class) .parser(IObjectParser.wrapStringGetter(DimensionType::byName)) .completerOfNamed(() -> Arrays.asList(DimensionType.values()), DimensionType::getName) + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .docOfType("dimension") .register(); ObjectMapper.builder("biome", Biome.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.BIOMES)) .completer(ForgeRegistries.BIOMES) + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .docOfType("biome") .register(); ObjectMapper.builder("profession", VillagerRegistry.VillagerProfession.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.VILLAGER_PROFESSIONS)) .completer(ForgeRegistries.VILLAGER_PROFESSIONS) + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .docOfType("villager profession") .register(); ObjectMapper.builder("career", VillagerRegistry.VillagerCareer.class) @@ -192,23 +209,27 @@ public static void init() { } return careers; }) + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .docOfType("villager career") .register(); ObjectMapper.builder("creativeTab", CreativeTabs.class) .parser(ObjectMappers::parseCreativeTab) .completerOfNamed(() -> Arrays.asList(CreativeTabs.CREATIVE_TAB_ARRAY), v -> ((CreativeTabsAccessor) v).getTabLabel2()) .defaultValue(() -> CreativeTabs.SEARCH) + .toGroovyCode(x -> GroovyScriptCodeConverter.asGroovyCode(x, false)) .docOfType("creative tab") .register(); ObjectMapper.builder("textformat", TextFormatting.class) .parser(ObjectMappers::parseTextFormatting) .completerOfNamed(() -> Arrays.asList(TextFormatting.values()), format -> format.name().toLowerCase(Locale.ROOT).replaceAll("[^a-z]", "")) .defaultValue(() -> TextFormatting.RESET) + .toGroovyCode(x -> GroovyScriptCodeConverter.formatGenericHandler("textformat", x.getFriendlyName(), false)) .docOfType("text format") .register(); ObjectMapper.builder("nbt", NBTTagCompound.class) .parser(ObjectMappers::parseNBT) .defaultValue(NBTTagCompound::new) + .toGroovyCode(x -> GroovyScriptCodeConverter.formatNBTTag(x, false, false)) .docOfType("nbt tag") .register(); } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java index 82638d00e..08c41ca89 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMappers.java @@ -2,7 +2,6 @@ import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; -import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.core.mixin.CreativeTabsAccessor; import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; @@ -57,7 +56,7 @@ public class ObjectMappers { return Result.some(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), mainArg)); } - public static @NotNull Result parseOreDict(String mainArg, Object... args) { + public static @NotNull Result parseOreDict(String mainArg, Object... args) { if (args.length > 0) { return Result.error("Arguments not valid for object mapper. Use 'ore(String)'"); }