From 589a06a5a5b0794db5bfb6e38d4d4882e7d6002d Mon Sep 17 00:00:00 2001 From: brachy84 Date: Sun, 8 Dec 2024 00:58:32 +0100 Subject: [PATCH 01/10] mapper backend refactor & texturedeco improvements --- .../mapper/AbstractObjectMapper.java | 163 ++++++++++++++++ .../groovyscript/mapper/BlockStateMapper.java | 49 +++++ .../groovyscript/mapper/ItemStackMapper.java | 60 ++++++ .../groovyscript/mapper/ObjectMapper.java | 184 ++++++++---------- .../mapper/ObjectMapperManager.java | 72 +++---- .../mapper/ObjectMapperMetaMethod.java | 4 +- .../groovyscript/mapper/TextureBinder.java | 85 ++++---- .../groovyscript/mapper/TextureTooltip.java | 93 --------- .../groovyscript/mapper/TooltipEmbedding.java | 70 +++++++ .../groovyscript/server/Completions.java | 23 +++ .../textureDecoration/TextureDecoration.java | 106 ++++++++++ .../TextureDecorationProvider.java | 168 +++++----------- .../compiler/util/GroovyASTUtils.java | 3 +- .../providers/CompletionProvider.java | 6 +- 14 files changed, 676 insertions(+), 410 deletions(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java delete mode 100644 src/main/java/com/cleanroommc/groovyscript/mapper/TextureTooltip.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java new file mode 100644 index 000000000..1731f6f96 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java @@ -0,0 +1,163 @@ +package com.cleanroommc.groovyscript.mapper; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.INamed; +import com.cleanroommc.groovyscript.api.IObjectParser; +import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.helper.ArrayUtils; +import com.cleanroommc.groovyscript.sandbox.expand.IDocumented; +import com.cleanroommc.groovyscript.server.Completions; +import groovy.lang.Closure; +import groovy.lang.groovydoc.Groovydoc; +import groovy.lang.groovydoc.GroovydocHolder; +import org.apache.commons.lang3.StringUtils; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.Parameter; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; + +public abstract class AbstractObjectMapper extends Closure implements INamed, IDocumented, IObjectParser, TextureBinder { + + private final String name; + private final GroovyContainer mod; + private final Class returnType; + protected List[]> paramTypes; + protected String documentation = StringUtils.EMPTY; + private List methodNodes; + private Boolean hasTextureBinder; + + protected AbstractObjectMapper(String name, GroovyContainer mod, Class returnType) { + super(null); + this.name = name; + this.mod = mod; + this.returnType = returnType; + this.paramTypes = new ArrayList<>(); + addSignature(String.class); + } + + protected final void addSignature(Class... types) { + this.paramTypes.add(types); + } + + public final T doCall(String s, Object... args) { + return invokeWithDefault(false, s, args); + } + + public final T doCall() { + return invokeDefault(); + } + + @Nullable + public final T invoke(boolean silent, String s, Object... args) { + Result t = Objects.requireNonNull(parse(s, args), "Object mapper must return a non null result!"); + if (t.hasError()) { + if (!silent) { + if (this.mod == null) { + GroovyLog.get().error("Can't find {} for name {}!", name, s); + } else { + GroovyLog.get().error("Can't find {} {} for name {}!", mod, name, s); + } + if (t.getError() != null && !t.getError().isEmpty()) { + GroovyLog.get().error(" - reason: {}", t.getError()); + } + } + return null; + } + return Objects.requireNonNull(t.getValue(), "Object mapper result must contain a non-null value!"); + } + + public final T invokeWithDefault(boolean silent, String s, Object... args) { + T t = invoke(silent, s, args); + return t != null ? t : invokeDefault(); + } + + public final T invokeDefault() { + Result t = getDefaultValue(); + return t == null || t.hasError() ? null : t.getValue(); + } + + public abstract Result getDefaultValue(); + + + public void provideCompletion(int index, Completions items) {} + + public void bindTexture(T t) {} + + public List getTooltip(T t) { + return Collections.emptyList(); + } + + public boolean hasTextureBinder() { + if (this.hasTextureBinder == null) { + for (Method method : getClass().getDeclaredMethods()) { + if (method.getName().equals("bindTexture") && method.getParameterTypes().length == 1 && this.returnType.isAssignableFrom(method.getParameterTypes()[0])) { + this.hasTextureBinder = true; + return true; + } + } + this.hasTextureBinder = false; + } + return this.hasTextureBinder; + } + + public List getMethodNodes() { + if (methodNodes == null) { + this.methodNodes = new ArrayList<>(); + for (Class[] paramType : this.paramTypes) { + Parameter[] params = ArrayUtils.map( + paramType, + c -> new Parameter(ClassHelper.makeCached(c), ""), + new Parameter[paramType.length]); + MethodNode node = new MethodNode( + this.name, + Modifier.PUBLIC | Modifier.FINAL, + ClassHelper.makeCached(this.returnType), + params, + null, + null); + node.setDeclaringClass( + this.mod != null ? ClassHelper.makeCached(this.mod.get().getClass()) : ClassHelper.makeCached(ObjectMapperManager.class)); + node.setNodeMetaData(GroovydocHolder.DOC_COMMENT, new Groovydoc(getDocumentation(), node)); + this.methodNodes.add(node); + } + } + return methodNodes; + } + + @Override + public String getName() { + return name; + } + + @Override + public Collection getAliases() { + return Collections.singleton(this.name); + } + + public GroovyContainer getMod() { + return mod; + } + + public Class getReturnType() { + return returnType; + } + + public List[]> getParamTypes() { + return paramTypes; + } + + @Override + public final String getDocumentation() { + return documentation; + } + + protected final String docOfType(String type) { + String mod = this.mod == null ? StringUtils.EMPTY : this.mod.getContainerName() + ' '; + return "returns a " + mod + type; + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java new file mode 100644 index 000000000..15ee00ed8 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java @@ -0,0 +1,49 @@ +package com.cleanroommc.groovyscript.mapper; + +import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.server.Completions; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.registry.ForgeRegistries; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class BlockStateMapper extends AbstractObjectMapper { + + public static final BlockStateMapper INSTANCE = new BlockStateMapper("blockstate", null); + + protected BlockStateMapper(String name, GroovyContainer mod) { + super(name, mod, IBlockState.class); + } + + @Override + public Result getDefaultValue() { + return Result.some(Blocks.AIR.getDefaultState()); + } + + @Override + public @NotNull Result parse(String mainArg, Object[] args) { + return ObjectMappers.parseBlockState(mainArg, args); + } + + @Override + public void provideCompletion(int index, Completions items) { + if (index == 0) items.addAllOfRegistry(ForgeRegistries.BLOCKS); + } + + @Override + public void bindTexture(IBlockState iBlockState) { + ItemStack itemStack = new ItemStack(iBlockState.getBlock(), 1, iBlockState.getBlock().getMetaFromState(iBlockState)); + TextureBinder.ofItem().bindTexture(itemStack); + } + + @Override + public List getTooltip(IBlockState iBlockState) { + ItemStack itemStack = new ItemStack(iBlockState.getBlock(), 1, iBlockState.getBlock().getMetaFromState(iBlockState)); + return Collections.singletonList(itemStack.getDisplayName()); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java new file mode 100644 index 000000000..57ba06979 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java @@ -0,0 +1,60 @@ +package com.cleanroommc.groovyscript.mapper; + +import com.cleanroommc.groovyscript.api.Result; +import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.server.Completions; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.registry.ForgeRegistries; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class ItemStackMapper extends AbstractObjectMapper { + + public static final ItemStackMapper INSTANCE = new ItemStackMapper("item", null); + + protected ItemStackMapper(String name, GroovyContainer mod) { + super(name, mod, ItemStack.class); + addSignature(String.class, int.class); + this.documentation = docOfType("item stack"); + } + + @Override + public Result getDefaultValue() { + return Result.some(ItemStack.EMPTY); + } + + @Override + public @NotNull Result parse(String mainArg, Object[] args) { + return ObjectMappers.parseItemStack(mainArg, args); + } + + @Override + public void provideCompletion(int index, Completions items) { + if (index == 0) items.addAllOfRegistry(ForgeRegistries.ITEMS); + } + + @Override + public void bindTexture(ItemStack item) { + GlStateManager.enableDepth(); + RenderHelper.enableGUIStandardItemLighting(); + var mc = Minecraft.getMinecraft(); + var fontRenderer = item.getItem().getFontRenderer(item); + if (fontRenderer == null) fontRenderer = mc.fontRenderer; + mc.getRenderItem().renderItemAndEffectIntoGUI(null, item, 0, 0); + mc.getRenderItem().renderItemOverlayIntoGUI(fontRenderer, item, 0, 0, null); + GlStateManager.disableBlend(); + RenderHelper.disableStandardItemLighting(); + GlStateManager.enableAlpha(); + GlStateManager.disableDepth(); + } + + @Override + public List getTooltip(ItemStack itemStack) { + return Collections.singletonList(itemStack.getDisplayName()); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java index a958652b1..9becb3976 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java @@ -1,26 +1,20 @@ package com.cleanroommc.groovyscript.mapper; -import com.cleanroommc.groovyscript.api.*; +import com.cleanroommc.groovyscript.api.IObjectParser; +import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.ModSupport; -import com.cleanroommc.groovyscript.helper.ArrayUtils; import com.cleanroommc.groovyscript.sandbox.expand.IDocumented; -import groovy.lang.Closure; -import groovy.lang.groovydoc.Groovydoc; -import groovy.lang.groovydoc.GroovydocHolder; +import com.cleanroommc.groovyscript.server.Completions; import net.minecraft.util.ResourceLocation; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.IForgeRegistryEntry; import org.apache.commons.lang3.StringUtils; -import org.codehaus.groovy.ast.ClassHelper; -import org.codehaus.groovy.ast.MethodNode; -import org.codehaus.groovy.ast.Parameter; import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.CompletionItemKind; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; -import java.lang.reflect.Modifier; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; @@ -30,7 +24,7 @@ * * @param return type of the function */ -public class ObjectMapper extends Closure implements INamed, IDocumented { +public class ObjectMapper extends AbstractObjectMapper { /** * Creates an object mapper builder. @@ -46,124 +40,58 @@ public static Builder builder(String name, Class returnType) { return new Builder<>(name, returnType); } - private final String name; - private final GroovyContainer mod; private final IObjectParser handler; private final Supplier> defaultValue; - private final Class returnType; - private final List[]> paramTypes; private final Completer completer; - private final String documentation; private final TextureBinder textureBinder; - private List methodNodes; + private final Function> tooltip; - private ObjectMapper(String name, GroovyContainer mod, IObjectParser handler, Supplier> defaultValue, Class returnType, List[]> paramTypes, Completer completer, String documentation, TextureBinder textureBinder) { - super(null); - this.name = name; - this.mod = mod; + private ObjectMapper(String name, GroovyContainer mod, IObjectParser handler, Supplier> defaultValue, Class returnType, List[]> paramTypes, Completer completer, String documentation, TextureBinder textureBinder, Function> tooltip) { + super(name, mod, returnType); this.handler = handler; this.defaultValue = defaultValue; - this.returnType = returnType; + this.tooltip = tooltip; this.paramTypes = paramTypes; this.completer = completer; this.documentation = documentation; this.textureBinder = textureBinder; } - @Nullable - public T invoke(boolean silent, String s, Object... args) { - Result t = Objects.requireNonNull(handler.parse(s, args), "Object mapper must return a non null result!"); - if (t.hasError()) { - if (!silent) { - if (this.mod == null) { - GroovyLog.get().error("Can't find {} for name {}!", name, s); - } else { - GroovyLog.get().error("Can't find {} {} for name {}!", mod, name, s); - } - if (t.getError() != null && !t.getError().isEmpty()) { - GroovyLog.get().error(" - reason: {}", t.getError()); - } - } - return null; - } - return Objects.requireNonNull(t.getValue(), "Object mapper result must contain a non-null value!"); - } - - public T invokeWithDefault(boolean silent, String s, Object... args) { - T t = invoke(silent, s, args); - return t != null ? t : invokeDefault(); - } - - public T invokeDefault() { - Result t = this.defaultValue.get(); - return t == null || t.hasError() ? null : t.getValue(); - } - - public GroovyContainer getMod() { - return mod; - } - @Override - public Collection getAliases() { - return Collections.singleton(this.name); + public @NotNull Result parse(String mainArg, Object[] args) { + return this.handler.parse(mainArg, args); } - public String getName() { - return name; - } - - public List[]> getParamTypes() { - return this.paramTypes; - } - - public Class getReturnType() { - return returnType; - } - - @GroovyBlacklist - public Completer getCompleter() { - return completer; - } - - public T doCall(String s, Object... args) { - return invokeWithDefault(false, s, args); + @Override + public Result getDefaultValue() { + return defaultValue.get(); } - public T doCall() { - return invokeDefault(); + @Override + public void provideCompletion(int index, Completions items) { + if (this.completer != null) { + this.completer.complete(index, items); + } } @Override - public String getDocumentation() { - return documentation; + public void bindTexture(T t) { + if (this.textureBinder != null) { + this.textureBinder.bindTexture(t); + } } - public List getMethodNodes() { - if (methodNodes == null) { - this.methodNodes = new ArrayList<>(); - for (Class[] paramType : this.paramTypes) { - Parameter[] params = ArrayUtils.map( - paramType, - c -> new Parameter(ClassHelper.makeCached(c), ""), - new Parameter[paramType.length]); - MethodNode node = new MethodNode( - this.name, - Modifier.PUBLIC | Modifier.FINAL, - ClassHelper.makeCached(this.returnType), - params, - null, - null); - node.setDeclaringClass(this.mod != null ? ClassHelper.makeCached(this.mod.get().getClass()) : ClassHelper.makeCached(ObjectMapperManager.class)); - node.setNodeMetaData(GroovydocHolder.DOC_COMMENT, new Groovydoc(this.documentation, node)); - this.methodNodes.add(node); - } + @Override + public List getTooltip(T t) { + if (this.tooltip != null) { + return this.tooltip.apply(t); } - return methodNodes; + return null; } - @ApiStatus.Experimental - public TextureBinder getTextureBinder() { - return textureBinder; + @Override + public boolean hasTextureBinder() { + return this.textureBinder != null; } /** @@ -181,7 +109,8 @@ public static class Builder { private final List[]> paramTypes = new ArrayList<>(); private Completer completer; private String documentation; - private TextureBinder textureBinder; + private TextureBinder textureBinder; + private Function> tooltip; @ApiStatus.Internal public Builder(String name, Class returnType) { @@ -350,6 +279,46 @@ public Builder textureBinder(TextureBinder textureBinder) { return this; } + @ApiStatus.Experimental + public Builder textureBinder(Function mapper, TextureBinder binder) { + return textureBinder(TextureBinder.of(mapper, binder)); + } + + @ApiStatus.Experimental + public Builder textureBinderOfList(Function> mapper, TextureBinder binder) { + return textureBinder(TextureBinder.ofList(mapper, binder)); + } + + @ApiStatus.Experimental + public Builder textureBinderOfArray(Function mapper, TextureBinder binder) { + return textureBinder(TextureBinder.ofArray(mapper, binder)); + } + + public Builder tooltip(Function> tooltip) { + this.tooltip = tooltip; + return this; + } + + public Builder tooltipOfValues(Function> values, Function toString) { + return tooltip(t -> { + List list = new ArrayList<>(); + for (V v : values.apply(t)) { + list.add(toString.apply(v)); + } + return list; + }); + } + + public Builder tooltipOfArray(Function values, Function toString) { + return tooltip(t -> { + List list = new ArrayList<>(); + for (V v : values.apply(t)) { + list.add(toString.apply(v)); + } + return list; + }); + } + /** * Registers the mapper. * @@ -366,7 +335,7 @@ public void register() { }); if (this.defaultValue == null) this.defaultValue = () -> null; this.documentation = IDocumented.toJavaDoc(this.documentation); - ObjectMapper goh = new ObjectMapper<>( + ObjectMapper mapper = new ObjectMapper<>( this.name, this.mod, this.handler, @@ -375,8 +344,9 @@ public void register() { this.paramTypes, this.completer, this.documentation, - this.textureBinder); - ObjectMapperManager.registerObjectMapper(this.mod, goh); + this.textureBinder, + 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 2cb545716..024cf1849 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java @@ -41,42 +41,43 @@ public class ObjectMapperManager { - private static final Map> handlers = new Object2ObjectOpenHashMap<>(); - private static final Map>> handlerConflicts = new Object2ObjectOpenHashMap<>(); - private static final Map, Map>> modHandlers = new Object2ObjectOpenHashMap<>(); + private static final Map> handlers = new Object2ObjectOpenHashMap<>(); + private static final Map>> handlerConflicts = new Object2ObjectOpenHashMap<>(); + private static final Map, Map>> modHandlers = new Object2ObjectOpenHashMap<>(); public static final String EMPTY = "empty"; public static final String WILDCARD = "*"; public static final String SPLITTER = ":"; - static void registerObjectMapper(GroovyContainer container, ObjectMapper goh) { - String key = goh.getName(); - if (goh.getMod() != null) { - Class clazz = goh.getMod().get().getClass(); - for (Class[] paramTypes : goh.getParamTypes()) { + public static void registerObjectMapper(AbstractObjectMapper mapper) { + String key = mapper.getName(); + if (mapper.getMod() != null) { + GroovyContainer mod = mapper.getMod(); + Class clazz = mapper.getMod().get().getClass(); + for (Class[] paramTypes : mapper.getParamTypes()) { ExpandoMetaClass emc = ExpansionHelper.getExpandoClass(clazz); - emc.registerInstanceMethod(new ObjectMapperMetaMethod(goh, paramTypes, clazz)); + emc.registerInstanceMethod(new ObjectMapperMetaMethod(mapper, paramTypes, clazz)); } + GroovyPropertyContainer propertyContainer = mod.get(); + var map = modHandlers.computeIfAbsent(propertyContainer.getClass(), k -> new Object2ObjectOpenHashMap<>()); + if (map.containsKey(key)) { + throw new IllegalStateException("There already is a ObjectMapper with name '" + key + "' in mod " + mod.getContainerName()); + } + map.put(key, mapper); } if (handlerConflicts.containsKey(key)) { - handlerConflicts.get(key).add(goh); + handlerConflicts.get(key).add(mapper); } else if (handlers.containsKey(key)) { - List> conflicts = handlerConflicts.computeIfAbsent(key, k -> new ArrayList<>()); + List> conflicts = handlerConflicts.computeIfAbsent(key, k -> new ArrayList<>()); conflicts.add(handlers.remove(key)); - conflicts.add(goh); + conflicts.add(mapper); } else { - handlers.put(key, goh); - } - if (container != null) { - GroovyPropertyContainer propertyContainer = container.get(); - var map = modHandlers.computeIfAbsent(propertyContainer.getClass(), k -> new Object2ObjectOpenHashMap<>()); - if (map.containsKey(key)) { - throw new IllegalStateException("There already is a ObjectMapper with name '" + key + "' in mod " + container.getContainerName()); - } - map.put(key, goh); + handlers.put(key, mapper); } } public static void init() { + registerObjectMapper(ItemStackMapper.INSTANCE); + registerObjectMapper(BlockStateMapper.INSTANCE); ObjectMapper.builder("resource", ResourceLocation.class) .parser(ObjectMappers::parseResourceLocation) .addSignature(String.class) @@ -87,9 +88,10 @@ public static void init() { .parser((s, args) -> s.contains(WILDCARD) ? Result.some(OreDictWildcardIngredient.of(s)) : Result.some(new OreDictIngredient(s))) .completerOfNames(OreDictionaryAccessor::getIdToName) .docOfType("ore dict entry") - .textureBinder(TextureBinder.of(i -> Arrays.asList(i.getMatchingStacks()), TextureBinder.ofItem(), i -> String.format("![](${item('%s')}) %s", i.getItem().getRegistryName(), i.getDisplayName()))) + .textureBinder(TextureBinder.ofArray(IIngredient::getMatchingStacks, TextureBinder.ofItem())) + .tooltipOfArray(IIngredient::getMatchingStacks, i -> String.format("![](${item('%s')}) %s", i.getItem().getRegistryName(), i.getDisplayName())) .register(); - ObjectMapper.builder("item", ItemStack.class) + /*ObjectMapper.builder("item", ItemStack.class) .parser(ObjectMappers::parseItemStack) .addSignature(String.class) .addSignature(String.class, int.class) @@ -97,7 +99,7 @@ public static void init() { .completer(ForgeRegistries.ITEMS) .docOfType("item stack") .textureBinder(TextureBinder.ofItem()) - .register(); + .register();*/ ObjectMapper.builder("liquid", FluidStack.class) .parser(ObjectMappers::parseFluidStack) .completerOfNames(FluidRegistry.getRegisteredFluids()::keySet) @@ -116,7 +118,7 @@ public static void init() { .docOfType("block") .textureBinder(TextureBinder.of(ItemStack::new, TextureBinder.ofItem())) .register(); - ObjectMapper.builder("blockstate", IBlockState.class) + /*ObjectMapper.builder("blockstate", IBlockState.class) .parser(ObjectMappers::parseBlockState) .addSignature(String.class) .addSignature(String.class, int.class) @@ -124,7 +126,7 @@ public static void init() { .completer(ForgeRegistries.BLOCKS) .defaultValue(() -> Blocks.AIR.getBlockState().getBaseState()) .docOfType("block state") - .register(); + .register();*/ ObjectMapper.builder("enchantment", Enchantment.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.ENCHANTMENTS)) .completer(ForgeRegistries.ENCHANTMENTS) @@ -225,7 +227,7 @@ public static Object getGameObject(String name, String mainArg, Object... args) */ @Nullable public static Object getGameObject(boolean silent, String name, String mainArg, Object... args) { - ObjectMapper objectMapper = handlers.get(name); + AbstractObjectMapper objectMapper = handlers.get(name); if (objectMapper != null) { return objectMapper.invokeWithDefault(silent, mainArg, args); } @@ -236,32 +238,32 @@ public static boolean hasObjectMapper(String key) { return handlers.containsKey(key); } - public static ObjectMapper getObjectMapper(String key) { + public static AbstractObjectMapper getObjectMapper(String key) { return handlers.get(key); } - public static List> getConflicts(String key) { + public static List> getConflicts(String key) { return handlerConflicts.get(key); } - public static ObjectMapper getObjectMapper(Class containerClass, String key) { + public static AbstractObjectMapper getObjectMapper(Class containerClass, String key) { if (!GroovyPropertyContainer.class.isAssignableFrom(containerClass)) return null; var map = modHandlers.get(containerClass); return map != null ? map.get(key) : null; } - public static Collection> getObjectMappers() { + public static Collection> getObjectMappers() { return handlers.values(); } + @Deprecated public static Class getReturnTypeOf(String name) { - ObjectMapper goh = handlers.get(name); + AbstractObjectMapper goh = handlers.get(name); return goh == null ? null : goh.getReturnType(); } + @Deprecated public static void provideCompletion(String name, int index, Completions items) { - Completer completer = handlers.get(name).getCompleter(); - if (completer == null) return; - completer.complete(index, items); + handlers.get(name).provideCompletion(index, items); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperMetaMethod.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperMetaMethod.java index 08e155e7a..4c5663a17 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperMetaMethod.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperMetaMethod.java @@ -9,10 +9,10 @@ public class ObjectMapperMetaMethod extends MetaMethod implements IDocumented { - private final ObjectMapper closure; + private final AbstractObjectMapper closure; private final Class owner; - ObjectMapperMetaMethod(ObjectMapper closure, Class[] nativeParamTypes, Class owner) { + ObjectMapperMetaMethod(AbstractObjectMapper closure, Class[] nativeParamTypes, Class owner) { super(nativeParamTypes); this.closure = closure; this.nativeParamTypes = nativeParamTypes; diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/TextureBinder.java b/src/main/java/com/cleanroommc/groovyscript/mapper/TextureBinder.java index 66fe30560..9fa4ad5f1 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/TextureBinder.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/TextureBinder.java @@ -12,77 +12,70 @@ import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.ApiStatus; -import java.util.Collections; import java.util.List; import java.util.function.Function; -import java.util.stream.Collectors; /** * This interface draws objects, so they can be rendered as icons in an ide. - * + *

* This is marked as experimental. This class is likely to change and may even be removed in a future update. */ @ApiStatus.Experimental -public interface TextureBinder extends Function> { +public interface TextureBinder { + + void bindTexture(T t); static TextureBinder of(Function mapper, TextureBinder binder) { - return o -> binder.apply(mapper.apply(o)); + return o -> binder.bindTexture(mapper.apply(o)); } - static TextureBinder of(Function> mapper, TextureBinder binder, Function tooltipMapper) { + static TextureBinder ofList(Function> mapper, TextureBinder binder) { return o -> { var list = mapper.apply(o); - if (list == null || list.isEmpty()) return Collections.emptyList(); - binder.apply(list.get(0)); - return list.stream().map(tooltipMapper).collect(Collectors.toList()); + if (list == null || list.isEmpty()) return; + binder.bindTexture(list.get(0)); + }; + } + + static TextureBinder ofArray(Function mapper, TextureBinder binder) { + return o -> { + var array = mapper.apply(o); + if (array == null || array.length == 0) return; + binder.bindTexture(array[0]); }; } static TextureBinder ofItem() { return item -> { - if (Minecraft.getMinecraft().isCallingFromMinecraftThread()) { - GlStateManager.enableDepth(); - RenderHelper.enableGUIStandardItemLighting(); - var mc = Minecraft.getMinecraft(); - var fontRenderer = item.getItem().getFontRenderer(item); - if (fontRenderer == null) - fontRenderer = mc.fontRenderer; - mc.getRenderItem().renderItemAndEffectIntoGUI(null, item, 0, 0); - mc.getRenderItem().renderItemOverlayIntoGUI(fontRenderer, item, 0, 0, null); - GlStateManager.disableBlend(); - RenderHelper.disableStandardItemLighting(); - GlStateManager.enableAlpha(); - GlStateManager.disableDepth(); - } - - return Collections.singletonList(item.getDisplayName()); + GlStateManager.enableDepth(); + RenderHelper.enableGUIStandardItemLighting(); + var mc = Minecraft.getMinecraft(); + var fontRenderer = item.getItem().getFontRenderer(item); + if (fontRenderer == null) + fontRenderer = mc.fontRenderer; + mc.getRenderItem().renderItemAndEffectIntoGUI(null, item, 0, 0); + mc.getRenderItem().renderItemOverlayIntoGUI(fontRenderer, item, 0, 0, null); + GlStateManager.disableBlend(); + RenderHelper.disableStandardItemLighting(); + GlStateManager.enableAlpha(); + GlStateManager.disableDepth(); }; } static TextureBinder ofFluid() { return fluid -> { - if (Minecraft.getMinecraft().isCallingFromMinecraftThread()) { - GlStateManager.enableBlend(); - GlStateManager.enableAlpha(); - - Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); - - var texture = Minecraft.getMinecraft().getTextureMapBlocks().getTextureExtry(fluid.getFluid().getStill(fluid).toString()); - - if (texture == null) { - texture = Minecraft.getMinecraft().getTextureMapBlocks().getMissingSprite(); - } - - var color = fluid.getFluid().getColor(fluid); - GlStateManager.color((color >> 16 & 0xFF) / 255.0F, (color >> 8 & 0xFF) / 255.0F, (color & 0xFF) / 255.0F, (color >> 24 & 0xFF) / 255.0F); - - drawSprite(texture); - - GlStateManager.disableAlpha(); - GlStateManager.disableBlend(); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); + var texture = Minecraft.getMinecraft().getTextureMapBlocks().getTextureExtry(fluid.getFluid().getStill(fluid).toString()); + if (texture == null) { + texture = Minecraft.getMinecraft().getTextureMapBlocks().getMissingSprite(); } - - return Collections.singletonList(fluid.getLocalizedName()); + var color = fluid.getFluid().getColor(fluid); + GlStateManager.color((color >> 16 & 0xFF) / 255.0F, (color >> 8 & 0xFF) / 255.0F, (color & 0xFF) / 255.0F, (color >> 24 & 0xFF) / 255.0F); + drawSprite(texture); + GlStateManager.disableAlpha(); + GlStateManager.disableBlend(); }; } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/TextureTooltip.java b/src/main/java/com/cleanroommc/groovyscript/mapper/TextureTooltip.java deleted file mode 100644 index ca839488f..000000000 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/TextureTooltip.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.cleanroommc.groovyscript.mapper; - -import org.apache.commons.codec.digest.DigestUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; - -public class TextureTooltip { - - private static final Pattern embeddingPattern = Pattern.compile("(?>\\$\\{(?\\w+)\\(['\\\"](?[\\w\\s:-]+)['\\\"]\\)})"); - - private final String content; - private final List embeddings; - - public TextureTooltip(String content) { - this.content = content; - this.embeddings = new ArrayList<>(); - - var matcher = embeddingPattern.matcher(content); - - while (matcher.find()) { - var mapper = ObjectMapperManager.getObjectMapper(matcher.group("mapper")); - if (mapper == null) { - continue; - } - - var binder = mapper.getTextureBinder(); - - if (binder == null) { - continue; - } - - var key = matcher.group("key"); - var result = mapper.invoke(true, key); - - if (result == null) { - continue; - } - - embeddings.add(new Embedding(matcher.start(), matcher.end(), result, binder, computeTextureName(mapper.getName(), key))); - } - } - - private static String computeTextureName(String name, String arg) { - return DigestUtils.sha1Hex(name + arg); - } - - public String getContent() { - return content; - } - - public List getEmbeddings() { - return embeddings; - } - - public class Embedding { - - private final int start; - private final int end; - private final T context; - private final TextureBinder textureBinder; - private final String textureName; - - private Embedding(int start, int end, T context, TextureBinder textureBinder, String textureName) { - this.start = start; - this.end = end; - this.context = context; - this.textureBinder = textureBinder; - this.textureName = textureName; - } - - public int getStart() { - return start; - } - - public int getEnd() { - return end; - } - - public T getContext() { - return context; - } - - public TextureBinder getTextureBinder() { - return textureBinder; - } - - public String getTextureName() { - return textureName; - } - } -} diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java b/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java new file mode 100644 index 000000000..7e253795e --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java @@ -0,0 +1,70 @@ +package com.cleanroommc.groovyscript.mapper; + +import org.apache.commons.codec.digest.DigestUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +public class TooltipEmbedding { + + private static final Pattern embeddingPattern = Pattern.compile("(?>\\$\\{(?\\w+)\\(['\\\"](?[\\w\\s:-]+)['\\\"]\\)})"); + + private static String computeTextureName(String name, String arg) { + return DigestUtils.sha1Hex(name + arg); + } + + public static List> parseEmbeddings(String content) { + List> embeddings = new ArrayList<>(); + var matcher = embeddingPattern.matcher(content); + while (matcher.find()) { + AbstractObjectMapper mapper = ObjectMapperManager.getObjectMapper(matcher.group("mapper")); + if (mapper == null) continue; + TooltipEmbedding embedding = TooltipEmbedding.of(matcher.start(), matcher.end(), matcher.group("key"), mapper); + if (embedding == null) continue; + embeddings.add(embedding); + } + return embeddings; + } + + private final int start; + private final int end; + private final T context; + private final AbstractObjectMapper mapper; + private final String textureName; + + private static TooltipEmbedding of(int start, int end, String key, AbstractObjectMapper mapper) { + if (!mapper.hasTextureBinder()) return null; + T result = mapper.invoke(true, key); + if (result == null) return null; + return new TooltipEmbedding<>(start, end, result, mapper, computeTextureName(mapper.getName(), key)); + } + + private TooltipEmbedding(int start, int end, T context, AbstractObjectMapper mapper, String textureName) { + this.start = start; + this.end = end; + this.context = context; + this.mapper = mapper; + this.textureName = textureName; + } + + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + + public T getContext() { + return context; + } + + public AbstractObjectMapper getMapper() { + return mapper; + } + + public String getTextureName() { + return textureName; + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/server/Completions.java b/src/main/java/com/cleanroommc/groovyscript/server/Completions.java index b5bd55b24..96abaa6bc 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/Completions.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/Completions.java @@ -1,6 +1,9 @@ package com.cleanroommc.groovyscript.server; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistry; import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; import org.eclipse.lsp4j.CompletionList; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.jetbrains.annotations.Nullable; @@ -45,6 +48,26 @@ public void addAll(V[] values, Function toCompl } } + public void addAllNamed(Iterable values, Function toString) { + addAll(values, v -> { + String s = toString.apply(v); + if (s != null) { + var item = new CompletionItem(toString.apply(v)); + item.setKind(CompletionItemKind.Constant); + return item; + } + return null; + }); + } + + public void addAllNamed(Iterable values) { + addAllNamed(values, ResourceLocation::toString); + } + + public void addAllOfRegistry(IForgeRegistry registry) { + addAllNamed(registry.getKeys()); + } + public Either, CompletionList> getResult(boolean incomplete) { return incomplete || reachedLimit() ? Either.forRight(new CompletionList(true, this)) : Either.forLeft(this); } diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java new file mode 100644 index 000000000..9b3ec8673 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java @@ -0,0 +1,106 @@ +package com.cleanroommc.groovyscript.server.features.textureDecoration; + +import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; +import com.cleanroommc.groovyscript.mapper.TooltipEmbedding; +import net.minecraft.client.renderer.GlStateManager; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.opengl.GL11; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.nio.ByteBuffer; +import java.util.List; + +public class TextureDecoration { + + private static T getObjectWithConstArgs(AbstractObjectMapper mapper, ArgumentListExpression args) { + var additionalArgs = new Object[args.getExpressions().size() - 1]; + for (int i = 0; i < additionalArgs.length; i++) { + if (args.getExpressions().get(i + 1) instanceof ConstantExpression argExpression) + additionalArgs[i] = argExpression.getValue(); + } + return mapper.invoke(true, args.getExpressions().get(0).getText(), additionalArgs); + } + + private final String name; + private final String uri; + private final AbstractObjectMapper mapper; + private final T bindable; + boolean fileExists; + boolean queued; + + public static TextureDecoration create(String name, String uri, AbstractObjectMapper mapper, ArgumentListExpression args) { + T bindable = getObjectWithConstArgs(mapper, args); + if (bindable == null) return null; + return new TextureDecoration<>(name, mapper, bindable, uri); + } + + public static TextureDecoration of(TooltipEmbedding embedding) { + return new TextureDecoration<>(embedding.getTextureName(), embedding.getMapper(), embedding.getContext(), TextureDecorationProvider.getURIForDecoration(embedding.getTextureName())); + } + + private TextureDecoration(String name, AbstractObjectMapper mapper, T bindable, String uri) { + this.name = name; + this.mapper = mapper; + this.bindable = bindable; + this.uri = uri; + File file = getFile(); + this.fileExists = !file.getParentFile().mkdirs() && file.exists(); + } + + public void bindTexture() { + this.mapper.bindTexture(this.bindable); + } + + public List getTooltip() { + return this.mapper.getTooltip(this.bindable); + } + + public String getUri() { + return uri; + } + + private @NotNull File getFile() { + return new File(TextureDecorationProvider.cacheRoot, name + ".png"); + } + + public boolean isFileExists() { + return fileExists; + } + + void render(ByteBuffer buffer) { + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); + bindTexture(); + GL11.glReadPixels(0, 0, TextureDecorationProvider.ICON_W, TextureDecorationProvider.ICON_H, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); + saveImage(getFile(), buffer); + buffer.rewind(); + synchronized (this) { + this.fileExists = true; + this.queued = false; + } + } + + private static void saveImage(File file, ByteBuffer buffer) { + final int w = TextureDecorationProvider.ICON_W, h = TextureDecorationProvider.ICON_H; + var image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int r = buffer.get() & 0xFF; + int g = buffer.get() & 0xFF; + int b = buffer.get() & 0xFF; + int a = buffer.get() & 0xFF; + int color = (a << 24) | (r << 16) | (g << 8) | b; + image.setRGB(x, h - 1 - y, color); // Flip the y-coordinate to correct the image orientation + } + } + + try { + ImageIO.write(image, "PNG", file); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java index b4130fda7..587d2f18b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java @@ -1,8 +1,7 @@ package com.cleanroommc.groovyscript.server.features.textureDecoration; -import com.cleanroommc.groovyscript.mapper.ObjectMapper; -import com.cleanroommc.groovyscript.mapper.TextureBinder; -import com.cleanroommc.groovyscript.mapper.TextureTooltip; +import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; +import com.cleanroommc.groovyscript.mapper.TooltipEmbedding; import com.cleanroommc.groovyscript.sandbox.SandboxData; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -17,14 +16,11 @@ import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.expr.*; import org.eclipse.lsp4j.Range; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; import java.io.File; import java.net.URI; import java.nio.ByteBuffer; @@ -33,15 +29,14 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; public class TextureDecorationProvider extends DocProvider { - private static final int ICON_W = 16, ICON_H = 16; - private static final int ICON_X = 0, ICON_Y = 0; - private static final Map textures = new Object2ObjectOpenHashMap<>(); + public static final int ICON_W = 16, ICON_H = 16; + public static final int ICON_X = 0, ICON_Y = 0; + private static final Map> textures = new Object2ObjectOpenHashMap<>(); - private final File cacheRoot = new File(SandboxData.getCachePath(), "textureDecorations"); + public static final File cacheRoot = new File(SandboxData.getCachePath(), "textureDecorations"); public TextureDecorationProvider(URI doc, ASTContext context) { super(doc, context); @@ -49,7 +44,7 @@ public TextureDecorationProvider(URI doc, ASTContext context) { public CompletableFuture> provideTextureDecorations() { List decorationInformations = new ArrayList<>(); - List queueDeco = new ArrayList<>(); + List> queueDeco = new ArrayList<>(); List queueRange = new ArrayList<>(); Set mappers = new ObjectOpenHashSet<>(); for (ASTNode node : getNodes()) { @@ -70,7 +65,7 @@ public CompletableFuture> provideTextureDecor } } else continue; if (mappers.contains(call) || !(call.getArguments() instanceof ArgumentListExpression args) || args.getExpressions().isEmpty()) continue; - ObjectMapper mapper; + AbstractObjectMapper mapper; try { mapper = GroovyASTUtils.getMapperOfNode(call, astContext); } catch (GroovyBugError e) { @@ -79,36 +74,37 @@ public CompletableFuture> provideTextureDecor if (mapper == null) continue; mappers.add(call); - if (!args.getExpressions().stream().allMatch(e -> e instanceof ConstantExpression)) { + if (!mapper.hasTextureBinder() || !args.getExpressions().stream().allMatch(e -> e instanceof ConstantExpression)) { continue; } - var binder = mapper.getTextureBinder(); - if (binder == null) continue; - var textureName = computeTextureName(mapper.getName(), args.getExpressions()); var uri = getURIForDecoration(textureName); - var decoration = textures.get(uri); - if (decoration == null) { - var bindable = getObjectWithConstArgs(mapper, args); - if (bindable == null) continue; - decoration = new TextureDecoration(textureName, binder, bindable, uri); - textures.put(uri, decoration); + TextureDecoration decoration; + synchronized (textures) { + decoration = textures.get(uri); + if (decoration == null) { + decoration = TextureDecoration.create(textureName, uri, mapper, args); + if (decoration == null) continue; + textures.put(uri, decoration); + } } var range = GroovyLSUtils.astNodeToRange(start, call); if (decoration.isFileExists()) { - var tooltips = new ArrayList<>(decoration.render()); + List tooltips = new ArrayList<>(decoration.getTooltip()); if (formatTooltips(tooltips, null)) { decorationInformations.add(new TextureDecorationInformation(range, uri, tooltips)); continue; } } - if (!decoration.queued) { - decoration.queued = true; - queueDeco.add(decoration); - queueRange.add(range); + synchronized (decoration) { + if (!decoration.queued) { + decoration.queued = true; + queueDeco.add(decoration); + queueRange.add(range); + } } } @@ -125,15 +121,6 @@ public CompletableFuture> provideTextureDecor return future; } - private static T getObjectWithConstArgs(ObjectMapper mapper, ArgumentListExpression args) { - var additionalArgs = new Object[args.getExpressions().size() - 1]; - for (int i = 0; i < additionalArgs.length; i++) { - if (args.getExpressions().get(i + 1) instanceof ConstantExpression argExpression) - additionalArgs[i] = argExpression.getValue(); - } - return mapper.invoke(true, args.getExpressions().get(0).getText(), additionalArgs); - } - private String computeTextureName(String name, List expressions) { var sb = new StringBuilder(name); for (Expression expression : expressions) { @@ -142,7 +129,7 @@ private String computeTextureName(String name, List expressions) { return DigestUtils.sha1Hex(sb.toString()); } - private void render(List queueDeco, + private void render(List> queueDeco, List queueRange, List decorationInformations) { var framebuffer = GL30.glGenFramebuffers(); @@ -192,15 +179,11 @@ private void render(List queueDeco, var buffer = BufferUtils.createByteBuffer(ICON_W * ICON_H * 4); for (int i = 0; i < queueDeco.size(); i++) { - TextureDecoration decoration = queueDeco.get(i); + TextureDecoration decoration = queueDeco.get(i); Range range = queueRange.get(i); - - var tooltipStrings = new ArrayList<>(render(buffer, decoration.getFile(), decoration::render)); - + decoration.render(buffer); + var tooltipStrings = new ArrayList<>(decoration.getTooltip()); formatTooltips(tooltipStrings, buffer); - - decoration.fileExists = true; - decoration.queued = false; decorationInformations.add(new TextureDecorationInformation(range, decoration.getUri(), tooltipStrings)); } @@ -213,25 +196,32 @@ private void render(List queueDeco, GL30.glDeleteFramebuffers(framebuffer); } - private boolean formatTooltips(ArrayList tooltipStrings, @Nullable ByteBuffer buffer) { + private boolean formatTooltips(List tooltipStrings, @Nullable ByteBuffer buffer) { for (int j = 0; j < tooltipStrings.size(); j++) { var str = tooltipStrings.get(j); - var tooltip = new TextureTooltip(str); - - for (var embedding : tooltip.getEmbeddings()) { - var embeddingDeco = new TextureDecoration(embedding.getTextureName(), embedding.getTextureBinder(), embedding.getContext(), getURIForDecoration(embedding.getTextureName())); - - if (!embeddingDeco.isFileExists()) { + var tooltip = TooltipEmbedding.parseEmbeddings(str); + + for (var embedding : tooltip) { + var uri = getURIForDecoration(embedding.getTextureName()); + TextureDecoration decoration; + synchronized (textures) { + decoration = textures.get(uri); + if (decoration == null) { + decoration = TextureDecoration.of(embedding); + textures.put(uri, decoration); + } + } + if (!decoration.isFileExists()) { if (buffer == null) { return false; } - render(buffer, embeddingDeco.getFile(), embeddingDeco::render); + decoration.render(buffer); } var before = embedding.getStart() == 0 ? "" : str.substring(0, embedding.getStart()); var after = embedding.getEnd() == str.length() - 1 ? "" : str.substring(embedding.getEnd()); - str = before + embeddingDeco.getUri() + after; + str = before + decoration.getUri() + after; } tooltipStrings.set(j, str); @@ -240,75 +230,7 @@ private boolean formatTooltips(ArrayList tooltipStrings, @Nullable ByteB return true; } - private static List render(ByteBuffer buffer, File outputFile, Supplier> renderer) { - GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); - - var tooltips = renderer.get(); - - GL11.glReadPixels(0, 0, ICON_W, ICON_H, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); - - saveImage(outputFile, buffer); - buffer.rewind(); - - return tooltips; - } - - private static void saveImage(File file, ByteBuffer buffer) { - var image = new BufferedImage(ICON_W, ICON_H, BufferedImage.TYPE_INT_ARGB); - for (int y = 0; y < ICON_H; y++) { - for (int x = 0; x < ICON_W; x++) { - int r = buffer.get() & 0xFF; - int g = buffer.get() & 0xFF; - int b = buffer.get() & 0xFF; - int a = buffer.get() & 0xFF; - int color = (a << 24) | (r << 16) | (g << 8) | b; - image.setRGB(x, ICON_H - 1 - y, color); // Flip the y-coordinate to correct the image orientation - } - } - - try { - ImageIO.write(image, "PNG", file); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private String getURIForDecoration(String name) { + static String getURIForDecoration(String name) { return new File(cacheRoot, name + ".png").toURI().toString(); } - - private class TextureDecoration { - - private final String name; - private final String uri; - private final TextureBinder binder; - private final Object bindable; - private boolean fileExists; - private boolean queued; - - private TextureDecoration(String name, TextureBinder binder, Object bindable, String uri) { - this.name = name; - this.binder = binder; - this.bindable = bindable; - this.uri = uri; - File file = getFile(); - this.fileExists = !file.getParentFile().mkdirs() && file.exists(); - } - - public String getUri() { - return uri; - } - - private @NotNull File getFile() { - return new File(cacheRoot, name + ".png"); - } - - public List render() { - return (List) ((TextureBinder) binder).apply(bindable); - } - - public boolean isFileExists() { - return fileExists; - } - } } diff --git a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java index 73181ed01..9eef3fff4 100644 --- a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java +++ b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java @@ -21,6 +21,7 @@ import com.cleanroommc.groovyscript.api.Hidden; import com.cleanroommc.groovyscript.helper.ArrayUtils; +import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapperManager; import com.cleanroommc.groovyscript.sandbox.Preprocessor; @@ -478,7 +479,7 @@ public static MethodNode methodNodeOfClosure(String name, Closure closure) { return method; } - public static ObjectMapper getMapperOfNode(MethodCallExpression expr, ASTContext context) { + public static AbstractObjectMapper getMapperOfNode(MethodCallExpression expr, ASTContext context) { if (expr.isImplicitThis()) { return ObjectMapperManager.getObjectMapper(expr.getMethodAsString()); } diff --git a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java index 5aa102114..a8d11ffab 100644 --- a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java +++ b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java @@ -178,8 +178,8 @@ private boolean populateItemsFromConstantExpression(ConstantExpression node, AST ASTNode parentParent = astContext.getVisitor().getParent(parent); if (parentParent instanceof MethodCallExpression expr && expr.getArguments() instanceof ArgumentListExpression args && !args.getExpressions().isEmpty()) { // TODO completions in file() - ObjectMapper goh = GroovyASTUtils.getMapperOfNode(expr, astContext); - if (goh != null && goh.getCompleter() != null) { + ObjectMapper mapper = GroovyASTUtils.getMapperOfNode(expr, astContext); + if (mapper != null) { int index = -1; for (int i = 0; i < args.getExpressions().size(); i++) { if (args.getExpression(i) == node) { @@ -187,7 +187,7 @@ private boolean populateItemsFromConstantExpression(ConstantExpression node, AST break; } } - goh.getCompleter().complete(index, items); + mapper.provideCompletion(index, items); } } return false; // don't complete keyword in strings From c6edb5e95143a0a50e18e1f292283b714fe4115d Mon Sep 17 00:00:00 2001 From: brachy84 Date: Sun, 8 Dec 2024 01:14:26 +0100 Subject: [PATCH 02/10] change texture deco cache path --- .../features/textureDecoration/TextureDecorationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java index 587d2f18b..9c328b49e 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java @@ -36,7 +36,7 @@ public class TextureDecorationProvider extends DocProvider { public static final int ICON_X = 0, ICON_Y = 0; private static final Map> textures = new Object2ObjectOpenHashMap<>(); - public static final File cacheRoot = new File(SandboxData.getCachePath(), "textureDecorations"); + public static final File cacheRoot = new File(SandboxData.getCachePath(), "texdecs"); public TextureDecorationProvider(URI doc, ASTContext context) { super(doc, context); From d1c9f7cd25851290da8ed4b4876f75f3893904c4 Mon Sep 17 00:00:00 2001 From: brachy84 Date: Sun, 8 Dec 2024 13:57:42 +0100 Subject: [PATCH 03/10] fixes & optimisations --- src/main/java/com/cleanroommc/groovyscript/GroovyScript.java | 4 ++-- .../groovyscript/mapper/AbstractObjectMapper.java | 2 ++ .../cleanroommc/groovyscript/mapper/BlockStateMapper.java | 2 +- .../com/cleanroommc/groovyscript/mapper/ItemStackMapper.java | 2 +- .../com/cleanroommc/groovyscript/mapper/ObjectMapper.java | 4 ++-- .../cleanroommc/groovyscript/mapper/ObjectMapperManager.java | 2 +- .../sandbox/transformer/GroovyScriptTransformer.java | 4 ++-- .../server/features/textureDecoration/TextureDecoration.java | 4 +++- .../textureDecoration/TextureDecorationProvider.java | 5 +++-- .../net/prominic/groovyls/compiler/util/GroovyASTUtils.java | 2 +- .../net/prominic/groovyls/providers/CompletionProvider.java | 3 ++- 11 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java index f0fc00285..9a071ba4b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java +++ b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java @@ -15,7 +15,7 @@ import com.cleanroommc.groovyscript.event.EventHandler; import com.cleanroommc.groovyscript.helper.JsonHelper; import com.cleanroommc.groovyscript.helper.StyleConstant; -import com.cleanroommc.groovyscript.mapper.ObjectMapper; +import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapperManager; import com.cleanroommc.groovyscript.network.CReload; import com.cleanroommc.groovyscript.network.NetworkHandler; @@ -153,7 +153,7 @@ public static void initializeGroovyPreInit() { StandardInfoParserRegistry.init(); VanillaModule.initializeBinding(); ModSupport.init(); - for (ObjectMapper goh : ObjectMapperManager.getObjectMappers()) { + for (AbstractObjectMapper goh : ObjectMapperManager.getObjectMappers()) { getSandbox().registerBinding(goh); } if (FMLLaunchHandler.isDeobfuscatedEnvironment()) Documentation.generate(); diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java index 1731f6f96..3287eedb1 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java @@ -15,6 +15,7 @@ import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.Parameter; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Method; @@ -88,6 +89,7 @@ public void provideCompletion(int index, Completions items) {} public void bindTexture(T t) {} + @NotNull public List getTooltip(T t) { return Collections.emptyList(); } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java index 15ee00ed8..63d4f0893 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java @@ -42,7 +42,7 @@ public void bindTexture(IBlockState iBlockState) { } @Override - public List getTooltip(IBlockState iBlockState) { + public @NotNull List getTooltip(IBlockState iBlockState) { ItemStack itemStack = new ItemStack(iBlockState.getBlock(), 1, iBlockState.getBlock().getMetaFromState(iBlockState)); return Collections.singletonList(itemStack.getDisplayName()); } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java index 57ba06979..53b1742ba 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java @@ -54,7 +54,7 @@ public void bindTexture(ItemStack item) { } @Override - public List getTooltip(ItemStack itemStack) { + public @NotNull List getTooltip(ItemStack itemStack) { return Collections.singletonList(itemStack.getDisplayName()); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java index 9becb3976..fc429dba7 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java @@ -82,11 +82,11 @@ public void bindTexture(T t) { } @Override - public List getTooltip(T t) { + public @NotNull List getTooltip(T t) { if (this.tooltip != null) { return this.tooltip.apply(t); } - return null; + return Collections.emptyList(); } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java index 024cf1849..c929b1c85 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java @@ -15,7 +15,6 @@ import groovy.lang.ExpandoMetaClass; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.enchantment.Enchantment; import net.minecraft.init.Blocks; @@ -110,6 +109,7 @@ public static void init() { .parser(ObjectMappers::parseFluidStack) .completerOfNames(FluidRegistry.getRegisteredFluids()::keySet) .textureBinder(TextureBinder.ofFluid()) + .tooltip(f -> Collections.singletonList(f.getLocalizedName())) .register(); ObjectMapper.builder("block", Block.class) .parser(IObjectParser.wrapForgeRegistry(ForgeRegistries.BLOCKS)) diff --git a/src/main/java/com/cleanroommc/groovyscript/sandbox/transformer/GroovyScriptTransformer.java b/src/main/java/com/cleanroommc/groovyscript/sandbox/transformer/GroovyScriptTransformer.java index 7dad2460b..71ba2b0c1 100644 --- a/src/main/java/com/cleanroommc/groovyscript/sandbox/transformer/GroovyScriptTransformer.java +++ b/src/main/java/com/cleanroommc/groovyscript/sandbox/transformer/GroovyScriptTransformer.java @@ -2,7 +2,7 @@ import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.helper.GroovyFile; -import com.cleanroommc.groovyscript.mapper.ObjectMapper; +import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapperManager; import org.codehaus.groovy.ast.ClassCodeExpressionTransformer; import org.codehaus.groovy.ast.ClassHelper; @@ -101,7 +101,7 @@ private Expression transformClosure(ClosureExpression closure) { private Expression transformMethodCall(MethodCallExpression mce) { if (mce.isImplicitThis()) { - List> conflicts = ObjectMapperManager.getConflicts(mce.getMethodAsString()); + List> conflicts = ObjectMapperManager.getConflicts(mce.getMethodAsString()); if (conflicts != null) { List suggestions = conflicts.stream() .map(goh -> goh.getMod() == null ? goh.getName() : "mods." + goh.getMod().getModId() + "." + goh.getName()) diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java index 9b3ec8673..0dd850ea6 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java @@ -12,6 +12,7 @@ import java.awt.image.BufferedImage; import java.io.File; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.List; public class TextureDecoration { @@ -56,7 +57,8 @@ public void bindTexture() { } public List getTooltip() { - return this.mapper.getTooltip(this.bindable); + List tooltip = this.mapper.getTooltip(this.bindable); + return tooltip.isEmpty() ? tooltip : new ArrayList<>(tooltip); } public String getUri() { diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java index 9c328b49e..dfc1535bb 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java @@ -93,7 +93,7 @@ public CompletableFuture> provideTextureDecor var range = GroovyLSUtils.astNodeToRange(start, call); if (decoration.isFileExists()) { - List tooltips = new ArrayList<>(decoration.getTooltip()); + List tooltips = decoration.getTooltip(); if (formatTooltips(tooltips, null)) { decorationInformations.add(new TextureDecorationInformation(range, uri, tooltips)); continue; @@ -182,7 +182,7 @@ private void render(List> queueDeco, TextureDecoration decoration = queueDeco.get(i); Range range = queueRange.get(i); decoration.render(buffer); - var tooltipStrings = new ArrayList<>(decoration.getTooltip()); + var tooltipStrings = decoration.getTooltip(); formatTooltips(tooltipStrings, buffer); decorationInformations.add(new TextureDecorationInformation(range, decoration.getUri(), tooltipStrings)); } @@ -197,6 +197,7 @@ private void render(List> queueDeco, } private boolean formatTooltips(List tooltipStrings, @Nullable ByteBuffer buffer) { + if (tooltipStrings.isEmpty()) return true; for (int j = 0; j < tooltipStrings.size(); j++) { var str = tooltipStrings.get(j); var tooltip = TooltipEmbedding.parseEmbeddings(str); diff --git a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java index 9eef3fff4..574d04b18 100644 --- a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java +++ b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java @@ -279,7 +279,7 @@ public static ClassNode getTypeOfNode(ASTNode node, ASTContext context) { } else if (node instanceof ConstructorCallExpression expression) { return expression.getType(); } else if (node instanceof MethodCallExpression expression) { - ObjectMapper goh = getMapperOfNode(expression, context); + AbstractObjectMapper goh = getMapperOfNode(expression, context); if (goh != null) { return ClassHelper.makeCached(goh.getReturnType()); } diff --git a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java index a8d11ffab..50af8379a 100644 --- a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java +++ b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java @@ -19,6 +19,7 @@ //////////////////////////////////////////////////////////////////////////////// package net.prominic.groovyls.providers; +import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapper; import com.cleanroommc.groovyscript.server.Completions; import groovy.lang.Closure; @@ -178,7 +179,7 @@ private boolean populateItemsFromConstantExpression(ConstantExpression node, AST ASTNode parentParent = astContext.getVisitor().getParent(parent); if (parentParent instanceof MethodCallExpression expr && expr.getArguments() instanceof ArgumentListExpression args && !args.getExpressions().isEmpty()) { // TODO completions in file() - ObjectMapper mapper = GroovyASTUtils.getMapperOfNode(expr, astContext); + AbstractObjectMapper mapper = GroovyASTUtils.getMapperOfNode(expr, astContext); if (mapper != null) { int index = -1; for (int i = 0; i < args.getExpressions().size(); i++) { From ef6c98c77d2279ae10b6ed52e8f5792d0e39a44a Mon Sep 17 00:00:00 2001 From: brachy84 Date: Wed, 11 Dec 2024 16:42:42 +0100 Subject: [PATCH 04/10] reviews --- .../groovyscript/mapper/AbstractObjectMapper.java | 14 +++++++++++++- .../groovyscript/mapper/TooltipEmbedding.java | 2 +- .../textureDecoration/TextureDecoration.java | 8 +++++--- .../TextureDecorationProvider.java | 10 ++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java index 3287eedb1..5a3ae09cb 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java @@ -27,7 +27,7 @@ public abstract class AbstractObjectMapper extends Closure implements INam private final String name; private final GroovyContainer mod; private final Class returnType; - protected List[]> paramTypes; + private final List[]> paramTypes; protected String documentation = StringUtils.EMPTY; private List methodNodes; private Boolean hasTextureBinder; @@ -41,8 +41,20 @@ protected AbstractObjectMapper(String name, GroovyContainer mod, Class ret addSignature(String.class); } + /** + * Call in ctor to configure signatures + */ + protected final void clearSignatures() { + this.paramTypes.clear(); + this.methodNodes = null; + } + + /** + * Call in ctor to configure signatures + */ protected final void addSignature(Class... types) { this.paramTypes.add(types); + this.methodNodes = null; } public final T doCall(String s, Object... args) { diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java b/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java index 7e253795e..fdae1f587 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/TooltipEmbedding.java @@ -8,7 +8,7 @@ public class TooltipEmbedding { - private static final Pattern embeddingPattern = Pattern.compile("(?>\\$\\{(?\\w+)\\(['\\\"](?[\\w\\s:-]+)['\\\"]\\)})"); + private static final Pattern embeddingPattern = Pattern.compile("(?>\\$\\{(?\\w+)\\(['\"](?[\\w\\s:-]+)['\"]\\)})"); private static String computeTextureName(String name, String arg) { return DigestUtils.sha1Hex(name + arg); diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java index 0dd850ea6..18a632cb8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecoration.java @@ -20,8 +20,9 @@ public class TextureDecoration { private static T getObjectWithConstArgs(AbstractObjectMapper mapper, ArgumentListExpression args) { var additionalArgs = new Object[args.getExpressions().size() - 1]; for (int i = 0; i < additionalArgs.length; i++) { - if (args.getExpressions().get(i + 1) instanceof ConstantExpression argExpression) + if (args.getExpressions().get(i + 1) instanceof ConstantExpression argExpression) { additionalArgs[i] = argExpression.getValue(); + } } return mapper.invoke(true, args.getExpressions().get(0).getText(), additionalArgs); } @@ -49,7 +50,7 @@ private TextureDecoration(String name, AbstractObjectMapper mapper, T bindabl this.bindable = bindable; this.uri = uri; File file = getFile(); - this.fileExists = !file.getParentFile().mkdirs() && file.exists(); + this.fileExists = file.exists(); } public void bindTexture() { @@ -86,7 +87,8 @@ void render(ByteBuffer buffer) { } private static void saveImage(File file, ByteBuffer buffer) { - final int w = TextureDecorationProvider.ICON_W, h = TextureDecorationProvider.ICON_H; + final int w = TextureDecorationProvider.ICON_W; + final int h = TextureDecorationProvider.ICON_H; var image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { diff --git a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java index dfc1535bb..994ea8142 100644 --- a/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java +++ b/src/main/java/com/cleanroommc/groovyscript/server/features/textureDecoration/TextureDecorationProvider.java @@ -32,12 +32,18 @@ public class TextureDecorationProvider extends DocProvider { - public static final int ICON_W = 16, ICON_H = 16; - public static final int ICON_X = 0, ICON_Y = 0; + public static final int ICON_W = 16; + public static final int ICON_H = 16; + public static final int ICON_X = 0; + public static final int ICON_Y = 0; private static final Map> textures = new Object2ObjectOpenHashMap<>(); public static final File cacheRoot = new File(SandboxData.getCachePath(), "texdecs"); + static { + cacheRoot.mkdirs(); + } + public TextureDecorationProvider(URI doc, ASTContext context) { super(doc, context); } From 30eebdd8f7fda6209edf438e50ccc849b8007583 Mon Sep 17 00:00:00 2001 From: brachy84 Date: Fri, 17 Jan 2025 10:37:29 +0100 Subject: [PATCH 05/10] fix --- .../com/cleanroommc/groovyscript/mapper/ObjectMapper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java index fc429dba7..9c3373b8b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java @@ -51,10 +51,13 @@ private ObjectMapper(String name, GroovyContainer mod, IObjectParser handl this.handler = handler; this.defaultValue = defaultValue; this.tooltip = tooltip; - this.paramTypes = paramTypes; this.completer = completer; this.documentation = documentation; this.textureBinder = textureBinder; + clearSignatures(); + for (Class[] signature : paramTypes) { + addSignature(signature); + } } @Override From b270570de153db2f71a48293db5cba9d78ea29ad Mon Sep 17 00:00:00 2001 From: brachy84 Date: Fri, 17 Jan 2025 12:28:15 +0100 Subject: [PATCH 06/10] fix exception --- .../net/prominic/groovyls/compiler/util/GroovyASTUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java index 5ef0b0a3c..97155cdc3 100644 --- a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java +++ b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java @@ -469,10 +469,10 @@ public static MethodNode methodNodeOfClosure(String name, Closure closure) { name, Modifier.PUBLIC, ClassHelper.OBJECT_TYPE, - ArrayUtils.map( + closure.getParameterTypes() != null ? ArrayUtils.map( closure.getParameterTypes(), c -> new Parameter(ClassHelper.makeCached(c), ""), - new Parameter[closure.getParameterTypes().length]), + new Parameter[closure.getParameterTypes().length]) : new Parameter[0], null, null); method.setDeclaringClass(ClassHelper.makeCached(declarer)); From 7edd23d07138cd6791cbdb00778d2eb5fbd993ae Mon Sep 17 00:00:00 2001 From: brachy84 Date: Fri, 17 Jan 2025 12:30:22 +0100 Subject: [PATCH 07/10] remove reflection & javadocs --- .../mapper/AbstractObjectMapper.java | 38 ++++++++++--------- .../groovyscript/mapper/BlockStateMapper.java | 5 +++ .../groovyscript/mapper/ItemStackMapper.java | 5 +++ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java index 5a3ae09cb..1f86762f3 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java @@ -18,7 +18,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; @@ -50,7 +49,8 @@ protected final void clearSignatures() { } /** - * Call in ctor to configure signatures + * Call in ctor to configure signatures. + * By default, only `name(String)` exists. */ protected final void addSignature(Class... types) { this.paramTypes.add(types); @@ -94,31 +94,35 @@ public final T invokeDefault() { return t == null || t.hasError() ? null : t.getValue(); } + /** + * Returns a default value for this mapper. This is called every time the parser returns an errored result. + * + * @return default value of this mapper. May be null + */ public abstract Result getDefaultValue(); - public void provideCompletion(int index, Completions items) {} - + /** + * Draws an image representation of the given object. This is used for lsp. + * The icon will show up in VSC or other code editors with compat. + * If this is implemented, {@link #hasTextureBinder()} must return true. Otherwise, this will not be used. + * + * @param t object for which a texture should be drawn. + */ public void bindTexture(T t) {} + /** + * Determines if {@link #bindTexture(Object)} is implemented and should be used. + * + * @return true if this mapper can bind textures + */ + public abstract boolean hasTextureBinder(); + @NotNull public List getTooltip(T t) { return Collections.emptyList(); } - public boolean hasTextureBinder() { - if (this.hasTextureBinder == null) { - for (Method method : getClass().getDeclaredMethods()) { - if (method.getName().equals("bindTexture") && method.getParameterTypes().length == 1 && this.returnType.isAssignableFrom(method.getParameterTypes()[0])) { - this.hasTextureBinder = true; - return true; - } - } - this.hasTextureBinder = false; - } - return this.hasTextureBinder; - } - public List getMethodNodes() { if (methodNodes == null) { this.methodNodes = new ArrayList<>(); diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java index 63d4f0893..ba0d7ebf1 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java @@ -46,4 +46,9 @@ public void bindTexture(IBlockState iBlockState) { ItemStack itemStack = new ItemStack(iBlockState.getBlock(), 1, iBlockState.getBlock().getMetaFromState(iBlockState)); return Collections.singletonList(itemStack.getDisplayName()); } + + @Override + public boolean hasTextureBinder() { + return true; + } } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java index 53b1742ba..9241bcf6b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java @@ -57,4 +57,9 @@ public void bindTexture(ItemStack item) { public @NotNull List getTooltip(ItemStack itemStack) { return Collections.singletonList(itemStack.getDisplayName()); } + + @Override + public boolean hasTextureBinder() { + return true; + } } From f363c3c4c374f8141babe8dbc462f146c8c74f2d Mon Sep 17 00:00:00 2001 From: brachy84 Date: Fri, 17 Jan 2025 12:38:27 +0100 Subject: [PATCH 08/10] completions can consider all params --- .../mapper/AbstractObjectMapper.java | 11 +++- .../groovyscript/mapper/BlockStateMapper.java | 24 ++++++++- .../groovyscript/mapper/ItemStackMapper.java | 3 +- .../groovyscript/mapper/ObjectMapper.java | 3 +- .../mapper/ObjectMapperManager.java | 3 +- .../groovyscript/server/CompletionParams.java | 53 +++++++++++++++++++ .../providers/CompletionProvider.java | 12 ++++- 7 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/server/CompletionParams.java diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java index 1f86762f3..ab602f29d 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/AbstractObjectMapper.java @@ -7,6 +7,7 @@ import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.helper.ArrayUtils; import com.cleanroommc.groovyscript.sandbox.expand.IDocumented; +import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import groovy.lang.Closure; import groovy.lang.groovydoc.Groovydoc; @@ -29,7 +30,6 @@ public abstract class AbstractObjectMapper extends Closure implements INam private final List[]> paramTypes; protected String documentation = StringUtils.EMPTY; private List methodNodes; - private Boolean hasTextureBinder; protected AbstractObjectMapper(String name, GroovyContainer mod, Class returnType) { super(null); @@ -101,6 +101,15 @@ public final T invokeDefault() { */ public abstract Result getDefaultValue(); + /** + * Adds all possible values this mapper can have at a param position. + * For example the `item()` mapper adds all item registry names when the index is 0. + * + * @param index the index of the param to complete + * @param params the values of all current (constant) params of the mapper + * @param items a list of completion items + */ + public void provideCompletion(int index, CompletionParams params, Completions items) {} /** * Draws an image representation of the given object. This is used for lsp. diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java index ba0d7ebf1..60a945ceb 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java @@ -2,11 +2,18 @@ import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.registry.ForgeRegistries; +import net.prominic.groovyls.util.CompletionItemFactory; +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -31,8 +38,23 @@ public Result getDefaultValue() { } @Override - public void provideCompletion(int index, Completions items) { + public void provideCompletion(int index, CompletionParams params, Completions items) { if (index == 0) items.addAllOfRegistry(ForgeRegistries.BLOCKS); + if (index >= 1 && params.isParamType(0, String.class)) { + Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(params.getParamAsType(0, String.class))); + if (block != null) { + // TODO completions for ints doesnt work properly + /*items.addAll(block.getBlockState().getValidStates(), state -> { + return CompletionItemFactory.createCompletion(CompletionItemKind.Value, String.valueOf(state.getBlock().getMetaFromState(state))); + });*/ + for (IProperty property : block.getBlockState().getProperties()) { + items.addAll(property.getAllowedValues(), val -> { + CompletionItem item = CompletionItemFactory.createCompletion(CompletionItemKind.Constant, property.getName() + "=" + property.getName((Comparable) val)); + return item; + }); + } + } + } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ItemStackMapper.java index 9241bcf6b..175a89073 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.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; @@ -34,7 +35,7 @@ public Result getDefaultValue() { } @Override - public void provideCompletion(int index, Completions items) { + public void provideCompletion(int index, CompletionParams params, Completions items) { if (index == 0) items.addAllOfRegistry(ForgeRegistries.ITEMS); } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java index 9c3373b8b..ad8c8f44e 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapper.java @@ -5,6 +5,7 @@ import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.sandbox.expand.IDocumented; +import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import net.minecraft.util.ResourceLocation; import net.minecraftforge.registries.IForgeRegistry; @@ -71,7 +72,7 @@ public Result getDefaultValue() { } @Override - public void provideCompletion(int index, Completions items) { + public void provideCompletion(int index, CompletionParams params, Completions items) { if (this.completer != null) { this.completer.complete(index, items); } diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java index d1ed5d55c..6458158ac 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/ObjectMapperManager.java @@ -11,6 +11,7 @@ import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; import com.cleanroommc.groovyscript.helper.ingredient.OreDictWildcardIngredient; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; +import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import groovy.lang.ExpandoMetaClass; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -263,6 +264,6 @@ public static Class getReturnTypeOf(String name) { @Deprecated public static void provideCompletion(String name, int index, Completions items) { - handlers.get(name).provideCompletion(index, items); + handlers.get(name).provideCompletion(index, CompletionParams.EMPTY, items); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/server/CompletionParams.java b/src/main/java/com/cleanroommc/groovyscript/server/CompletionParams.java new file mode 100644 index 000000000..a4d10b1b3 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/server/CompletionParams.java @@ -0,0 +1,53 @@ +package com.cleanroommc.groovyscript.server; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class CompletionParams { + + private static final Object UNPARSABLE_MARKER = new Object(); + public static final CompletionParams EMPTY = new CompletionParams(); + + public static CompletionParams addParam(CompletionParams params, Object param) { + if (params == EMPTY) params = new CompletionParams(); + params.params.add(param); + return params; + } + + public static CompletionParams addUnparsableParam(CompletionParams params) { + return addParam(params, UNPARSABLE_MARKER); + } + + private final List params = new ArrayList<>(4); + + private CompletionParams() {} + + public Object getParam(int i) { + if (getParamCount() <= i) return null; + Object o = params.get(i); + return o == UNPARSABLE_MARKER ? null : o; + } + + public int getParamCount() { + return params.size(); + } + + public boolean isParamUnparsable(int index) { + return getParamCount() > index && params.get(index) == UNPARSABLE_MARKER; + } + + public boolean isParamType(int index, @Nullable Class type) { + if (getParamCount() <= index) return false; + Object o = params.get(index); + return o == null || o == UNPARSABLE_MARKER ? type == null : type != null && type.isAssignableFrom(o.getClass()); + } + + public T getParamAsType(int index, @NotNull Class type) { + if (getParamCount() <= index) return null; + Object o = params.get(index); + return o != null && o != UNPARSABLE_MARKER && type.isAssignableFrom(o.getClass()) ? type.cast(o) : null; + } +} diff --git a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java index f27a5f11e..e62e4db7e 100644 --- a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java +++ b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java @@ -21,6 +21,7 @@ import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapper; +import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import groovy.lang.Closure; import groovy.lang.DelegatesTo; @@ -181,14 +182,21 @@ private boolean populateItemsFromConstantExpression(ConstantExpression node, AST // TODO completions in file() AbstractObjectMapper mapper = GroovyASTUtils.getMapperOfNode(expr, astContext); if (mapper != null) { + CompletionParams params = CompletionParams.EMPTY; int index = -1; for (int i = 0; i < args.getExpressions().size(); i++) { - if (args.getExpression(i) == node) { + Expression arg = args.getExpression(i); + if (arg instanceof ConstantExpression constArg) { + params = CompletionParams.addParam(params, constArg.getValue()); + } else { + params = CompletionParams.addUnparsableParam(params); + } + if (arg == node) { index = i; break; } } - mapper.provideCompletion(index, items); + mapper.provideCompletion(index, params, items); } } return false; // don't complete keyword in strings From 15ead42e229fa0b2752aa9e854ff84da9b67976e Mon Sep 17 00:00:00 2001 From: brachy84 Date: Fri, 17 Jan 2025 12:52:12 +0100 Subject: [PATCH 09/10] fix issues with custom mapper classes --- .../com/cleanroommc/groovyscript/mapper/BlockStateMapper.java | 3 +++ .../net/prominic/groovyls/compiler/util/GroovyASTUtils.java | 2 +- .../net/prominic/groovyls/providers/CompletionProvider.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java index 60a945ceb..9221a5ef6 100644 --- a/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java +++ b/src/main/java/com/cleanroommc/groovyscript/mapper/BlockStateMapper.java @@ -25,6 +25,9 @@ public class BlockStateMapper extends AbstractObjectMapper { protected BlockStateMapper(String name, GroovyContainer mod) { super(name, mod, IBlockState.class); + addSignature(String.class, int.class); + addSignature(String.class, String[].class); + this.documentation = docOfType("block state"); } @Override diff --git a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java index 97155cdc3..3d1ac70b6 100644 --- a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java +++ b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java @@ -337,7 +337,7 @@ public static List getMethodOverloadsFromCallExpression(MethodCall n List mn = new ArrayList<>(); if (methodCallExpr.isImplicitThis()) { Object o = context.getLanguageServerContext().getSandbox().getBindings().get(node.getMethodAsString()); - if (o instanceof ObjectMappergoh) { + if (o instanceof AbstractObjectMappergoh) { mn.addAll(goh.getMethodNodes()); } else if (o instanceof Closureclosure) { mn.add(methodNodeOfClosure(node.getMethodAsString(), closure)); diff --git a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java index e62e4db7e..88fdff28c 100644 --- a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java +++ b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java @@ -488,7 +488,7 @@ private void populateItemsFromGlobalScope(String memberNamePrefix, Set e String name = entry.getKey(); if (!name.toLowerCase(Locale.ENGLISH).contains(memberNamePrefix) || existingNames.contains(name)) return null; existingNames.add(name); - if (entry.getValue() instanceof ObjectMappergoh) { + if (entry.getValue() instanceof AbstractObjectMappergoh) { for (MethodNode method : goh.getMethodNodes()) { var item = CompletionItemFactory.createCompletion(method, goh.getName(), astContext); item.setLabelDetails(getMethodNodeDetails(method)); From e52b47759a1a32b00ddbf953e538e7104bb1751a Mon Sep 17 00:00:00 2001 From: brachy84 Date: Fri, 17 Jan 2025 12:52:55 +0100 Subject: [PATCH 10/10] spotless --- .../groovyls/compiler/util/GroovyASTUtils.java | 11 ++++++----- .../groovyls/providers/CompletionProvider.java | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java index 3d1ac70b6..3e64393b4 100644 --- a/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java +++ b/src/main/java/net/prominic/groovyls/compiler/util/GroovyASTUtils.java @@ -22,7 +22,6 @@ import com.cleanroommc.groovyscript.api.Hidden; import com.cleanroommc.groovyscript.helper.ArrayUtils; import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; -import com.cleanroommc.groovyscript.mapper.ObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapperManager; import com.cleanroommc.groovyscript.sandbox.Preprocessor; import com.cleanroommc.groovyscript.sandbox.expand.IDocumented; @@ -469,10 +468,12 @@ public static MethodNode methodNodeOfClosure(String name, Closure closure) { name, Modifier.PUBLIC, ClassHelper.OBJECT_TYPE, - closure.getParameterTypes() != null ? ArrayUtils.map( - closure.getParameterTypes(), - c -> new Parameter(ClassHelper.makeCached(c), ""), - new Parameter[closure.getParameterTypes().length]) : new Parameter[0], + closure.getParameterTypes() != null + ? ArrayUtils.map( + closure.getParameterTypes(), + c -> new Parameter(ClassHelper.makeCached(c), ""), + new Parameter[closure.getParameterTypes().length]) + : new Parameter[0], null, null); method.setDeclaringClass(ClassHelper.makeCached(declarer)); diff --git a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java index 88fdff28c..c55352ad0 100644 --- a/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java +++ b/src/main/java/net/prominic/groovyls/providers/CompletionProvider.java @@ -20,7 +20,6 @@ package net.prominic.groovyls.providers; import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; -import com.cleanroommc.groovyscript.mapper.ObjectMapper; import com.cleanroommc.groovyscript.server.CompletionParams; import com.cleanroommc.groovyscript.server.Completions; import groovy.lang.Closure;